MVVM (Model-view-viewmodel).md
 

 

MVVM (Model-view-viewmodel) pattern

MVVM pattern은 Model-View-ViewModel의 약자로 소프트웨어 아키텍쳐 패턴이다. 초기 UI 개발자들은 모든 코드 로직(이벤트 핸들링, 초기화, 데이터 모델)을 뷰에 작성했다. 모든 코드들을 뷰에 작성하다보니 뷰의 크기가 커지고, UI와 데이터 바인딩간의 의존성 문제가 일어나다보니 개발자들의 협업 개발에서 많은 이슈가 일어나고 유지보수, 확장이 어려워졌다. 이를 해결하기 위해 사용자 인터페이스에 해당하는 뷰(View)와 뷰에 표시되는 데이터(Model) 그리고 뷰(View)와 모델(Model) 사이에서 여러 비즈니스 로직을 처리하는 뷰-모델(View-Model)로 분리하여, 유지보수를 쉽게하고 뷰(View) 처리에 다양한 기능을 사용할 수 있게 되었다.

Three key parts in the MVVM pattern

  1. Model (비즈니스 규칙, 데이터 접근, 모델 클래스)
  2. View (사용자 인터페이스)
  3. ViewModel (모델과 뷰 사이의 인터페이스)

뷰모델(ViewModel)은 모델(Model)과 뷰(View)사이에 인터페이스 역할을 한다. 뷰모델은 모델의 데이터를 뷰에 바인딩하고, 명령어를 사용하여 모든 UI의 동작들을 다룬다. 뷰는 뷰모델의 프로퍼티에 제어값을 바인딩하며 차례대로 모델 객체에 있는 데이터를 노출시킨다.

예를 들어 사용자가 뷰에 있는 계산기 프로그램을 사용하여 결과값을 요청하는 버튼을 클릭했을 때, 뷰모델이 요청받은 동작을 수행한다. 뷰모델의 연산 기능을 담당하는 명령어는 연산 후 모델의 데이터 값을 변경시킨다. 만약 뷰모델의 속성값이 변경되면(모델의 데이터 값이 변경되면) 새로운 속성 값들은 데이터 바인딩(data binding)과 알림(notification)을 통해 자동적으로 뷰에 적용된다.

 

MVVM in Vue.js

Vue.js는 위의 설명된 MVVM 패턴에서 ViewModel 계층에 초점을 둔 프레임워크이다. 뷰모델을 통해서 양방향 데이터 바인딩이 가능하게 해주며, 뷰 계층을 좀 더 간단하고 유연하게 디자인하게 해준다.

아래 그림은 Vue.js에서 MVVM을 나타낸 그림이다. (출처 : https://012.vuejs.org/images/mvvm.png)

MVVM Concepts

ViewModel in Vue.js

모델과 뷰의 동기화 역할을 하는 객체이다. Vue.js에서 모든 뷰 인스턴스(View instance)는 뷰모델(ViewModel)이다. 이들은 Vue 생성자 혹은 하위 클래스들에 의해 인스턴스화된다.

 

이렇게 초기 객체를 선언해줌으로써 뷰와 모델 사이에서 양방향 데이터 바인딩이 가능하게 해준다. 더 자세한 정보는 The Vue Constructor를 확인하자.

 

View in Vue.js

뷰의 실제 돔(DOM)은 Vue instances에 의해 관리된다.

 

Vue.js는 DOM 기반의 템플릿을 사용한다. 각 뷰 인스턴스는 해당 DOM 요소에 연관된다. 뷰 인스턴스가 생성되면 필요한 데이터 바인딩을 설정하는 동안 루트 요소의 모든 자식 노드를 반복적으로 탐색한다. 뷰가 컴파일이 되면 데이터 변경에 반응할 수 있게 된다.

즉, 해당 HTML 컴포넌트 범위(해당 DOM 요소가 담긴 템플릿)를 Vue instace의 vm.$el에 설정한다. 뷰는 Vue instance가 생성 될 때 컴파일 되며 뷰모델의 다양한 동작 기능들이 바인딩 된다. 그렇게 됨으로써 뷰의 변경이 감지되면 뷰모델이 이를 감지하여 반응할 수 있게된다. 추가적으로 뷰의 변경은 집단적으로, 비동기로 실행되기 때문에 높은 성능을 발휘한다.

 

Model in Vue.js

 

Vue.js에서 모델은 단순히 자바스크립트 객체 혹은 데이터 객체로 표현할 수 있다. 데이터 객체의 프로퍼티를 조작하면 이를 관찰하는 뷰 인스턴스가 변경을 알린다. Vue.js는 ES5 getter/setters로 데이터 객체의 프로퍼티를 변환한다. 그렇기에 뷰를 변경하기 위해 Vue에 명시적으로 신호를 보낼 필요가 없다. 또한 각 뷰 인스턴스는 데이터 객체에 있는 모든 프로퍼티들을 프록시한다.

아래 그림은 Vue.js에서 반응형 업데이트가 구현되는 방식을 보여준다. (출처 : https://012.vuejs.org/images/data.png)

high-level overview of how reactive updates

 

참고 자료

'Vue.js' 카테고리의 다른 글

Vue.js : 새롭게 추가된 Virtual DOM  (4) 2017.12.26
Webpack-dev-server를 사용한 웹팩 빌드 오류.md

Webpack-dev-server를 사용한 웹팩 빌드 오류

Bulid succeeding with webpack fails with webpack-dev-server (Unexpected token)

 

webpack/webpack-dev-server GIT 페이지의 issues를 참고했습니다.

링크 - https://github.com/webpack/webpack-dev-server/issues/1101

실행 환경 - 오류가 발생한

  • OS : Ubuntu 16.04 LTS

  • Node version : 8.2.1

  • NPM version : 5.6.0

  • webpack version : 3.10.0

  • webpack-dev-version : 2.10.0

에러 메세지

 

webpack을 이용한 빌드는 성공적으로 이루어졌음에도 불구하고 동일한 환경에서 webpack-dev-server를 사용하여 시작했을 때, 위와 같은 에러 메세지를 볼 수 있습니다.

 

에러 추적

  • npm install [dependencies] (의존성 설치)

  • npm list webpack

  • npm list webpack-dev-server (2.10.0이 최신 버전이지만 2.8.0 or 2.8.1 부터 위와 같은 오류 발생)

  • package.json에서 일반적으로 두 가지의 script를 작성합니다.

    • npm run build : 웹팩을 사용한 번들링의 경우 성공적으로 빌드됩니다.
    • npm start : 동일한 환경으로 webpack-dev-server를 사용하여 빌드했을 경우 예외적으로 오류가 발생합니다.

에러 원인

확실하게 원인에 대해 알지 못 하지만 webpack-dev-server의 최신 버전의 경우 ES6(es2015)를 지원하는 반면에 UglifyJS-Plugin은 ES6를 지원하지 않기 때문에 발생하는 오류로 예상하고 있습니다.

현재 uglifyjs-webpack-plugin의 경우 ES6을 지원한다고 합니다. 다만 uglifyjs의 추가 설치 단계가 필요합니다.

 

해결 방법

이러한 문제는 webpack-dev-server 2.8.0에서 나타나는 오류라고 합니다. 검증을 위해

  • npm install webpack-dev-server@~2.7.0
  • npm start

webpack-dev-server version을 2.7.1로 다운그레이드 시킴으로써 간단히 해결할 수 있습니다.

 

그 외 해결 방법들

  • install UglifyJS-Plugin separately

  • temporarily remove UglifyJS-plugin until webpack includes an es6-capable version

  • transpile webpack-dev-server

    •  

 

전역 변수 맛보기.md

이 글은 "JavaScript Patterns" 책을 공부하며 요약해 쓴 글입니다.


전역 변수의 최소화는 좋은 코드 작성과 유지보수를 함에 있어 큰 역할을 한다!!

그렇기에 전역 변수를 사용함에 있어, 안티 패턴을 최대한 피하며 개발을 하는 것이 좋다.

 

전역 변수 맛보기

자바스크립트는 함수를 사용하여 유효 범위를 관리한다. 아래는 지역 변수를 나타낸다.

 

ex) 지역변수 사용 예

 

 

반대로 전역 변수는 어떤 함수에도 속하지 않은 상태에서 선언되거나, 함수에 속하더라도 var를 통해 선언되지 않은 채로 사용되는 변수를 가리킨다.

 

ex) 전역 변수 사용 예

 

 

모든 자바스크립트 실행 환경에는 전역 객체(global object)가 존재하는데, 전역 변수를 선언하면 이는 전역 객체의 프로퍼티가 된다. 브라우저에서는 전역 객체에 window라는 프로퍼티가 존재하는데 이는 전역 객체 자신을 가리킨다.

 

ex) 모두 전역 변수

 

 

전역 객체는 this를 통해서도 접근이 가능하다.

 

ex)

 

 

전역 변수의 문제점

전역 변수의 문제점은 애플리케이션이나 웹페이지 내 모든 코드 사이에서 공유된다는 점이다.

ex) 덮어 쓰기

 

만약 개발자가 자신이 작성하지 않은 외부 코드를 가져와 삽입했을 때, yyy = 0;은 개발자가 정의한 코드이며 test 함수는 외부 코드라고 가정한다면 개발자가 test 함수를 실행했을 때 전역 변수 yyy가 10이 되는 원치않는 결과를 초래할 것이다.

 

이러한 문제를 피하기 위해서 전역 변수에 대한 안티 패턴과 개선하는 코드를 알아 보자.


1. var를 통한 변수 선언

ex) 암묵적 전역 코드 사용 == 안티 패턴

 

자바스크립트에는 암묵적 전역(implied globals)이라는 개념이 있기 때문에 선언하지 않고 사용한 변수는 자동으로 전역 객체의 프로퍼티가 되어 명시적으로 선언된 전역 변수처럼 사용될 수 있다.

 

안티 패턴을 피하기 위해서는 언제나 var를 사용하여 변수를 선언하는 것이 좋다.

 

ex) var 변수 선언

 

유효 범위 안에서만 사용 가능하여 덮어쓰기 같이 의도치 않는 실수가 일어나지 않도록 방지해준다.

 


2. var 선언에서의 연쇄적 할당

아래는 var 선언에 여러 변수를 연쇄적으로 할당한 코드의 예이다.

 

ex)

 

두 변수가 지역 변수로 할당될 것이라 예상하지만 사실 b는 전역 변수가 된다. 그 이유는 자바스크립트는 표현식의 "평가(evaulation)"가 오른쪽에서 왼쪽으로 진행되기 때문이다. 코드의 평가는 아래와 같이 된다.

 

괄호 안의 b = 0 이라는 식이 먼저 평가되는데, 이때 b는 var를 통해 선언되는 것이 아니므로 전역 변수가 된다.

 

 

변수를 미리 선언해둠으로써 연쇄 할당문의 전역 변수 생성을 피할 수 있다.

 

ex) 안티 패턴 피하기

 

 


3. 단일 var 패턴 (유용)

함수의 상단에 var 선언을 한 번만 쓰는 패턴은 유용하고 시도해 볼 만하다.

책 에서는 다음과 같은 이점이 있다고 소개한다.

  • 함수에서 필요로 하는 모든 지역 변수를 한군데서 찾을 수 있다.
  • 변수를 선언하기 전에 사용할 때 발생하는 로직상의 오류를 막아준다. [호이스팅(hoisting)과 같은]
  • 변수를 먼저 선언한 후에 사용해야 한다는 사실을 상기시키기 때문에 전역 변수를 최소화하는 데 도움이 된다.
  • 코드량이 줄어든다. (작성량과 전송량 모두 줄어든다)

코드는 아래와 같이 표현한다.

 

ex) 단일 var 패턴의 예

 

var 선언을 하나만 쓰고 쉼표를 통해 여러 변수들을 선언했다.

자바스크립트는 C와 Java와 같은 언어처럼 정적 타이핑(static type)이 아닌 동적 타이핑(dynamic type)이다. int와 char와 같이 변수의 용도에 따라 타입(type)을 미리 명시해주는 것이 아닌, var 변수에 어떤 값을 할당하든 실행 시에 자바스크립트 엔진에서 자동으로 타입(type)을 구분해준다.

이런 성격으로 인해 개발자가 매우 편리하게 코드를 작성할 수 있지만, 나중에 코드가 매우 방대해지고 용어의 뜻이 불분명할 때는 변수의 용도를 확인하기가 어려워지며 오류 또한 발생하기 쉽다.

그러므로 위와 같이 변수를 선언할 때 초기 값을 주어 초기화하는 것 역시 좋은 습관이다. 문법 오류를 막을 수 있고 코드 가독성도 향상된다.

또한 자바스크립트는 "호이스팅(hoisting, 끌어올리기)"이라는 동작 방식이 있다. 실행 문맥(execution context) 글을 보면 자세히 알 수 있는데, 함수 범위 내에 흩어져 있는 변수는 값이 할당되기 전에 모두 함수 상단으로 끌어올려져 undefined 형태로 선언된다. 이러한 특성은 로직상의 오류를 범하기 쉽기 때문에, 함수 상단에 하나의 var 선언문을 사용하여 변수들을 모아놓는 패턴을 사용하는 것이 좋다.

 

DOM(Document Object Model) 참조를 다루는 것도 좋은 예다.
다음 예제와 같이 DOM 참조를 할당한 지역 변수들을 하나의 선언문에 모아놓는다.

 

ex)

 

'JavaScript' 카테고리의 다른 글

자바스크립트 : for, for-in 패턴  (0) 2018.01.22

+ Recent posts