template: '<div>하위 컴포넌트2 영역입니다. 전달받은 값 : {{ number }}</div>',
created: function() {
var self = this;
eventBus.$on('triggerEventBus', function(value){
self.number += value;
});
},
data: function() {
return {
number : 0
}
}
});
var app = new Vue({
el: '#app'
});
하위 컴포넌트 1에서 하위 컴포넌트 2의 created 에 작성된 function을 통해 data.str의 값을 조작할 수 있습니다.
이렇게 서로 상하관계가 아닌 컴포넌트끼리 통신을 가능하게 해주는 것을 Vue에서는 이벤트 버스라 부릅니다. 이런 방식은 프로그래밍 패러다임 Event-driven Programming이나 Event-driven Architecture에서 보았을 수 있습니다. 해당내용에 대해서는 이번장 설명 상단에 링크를 참조하시길 바랍니다.
Conclusions
Vue의 컴포넌트 간의 통신에 대해 알아보았습니다. Vue에서 지향하고있는 단방향 데이터 흐름이 적합한곳에서는 상하관계로 완전히 분리된 컴포넌트간의 통신은 이벤트 버스를 적절히 사용하면 Vue의 컴포넌트를 완벽하게 사용할 수 있겠습니다.
다음장에서는 Front-end Framework 의 발전에 원동력인 SPA를 가능하게 해주는 Vue 라우터와 HTTP 통신에 대해 설명하도록 하겠습니다.
인스턴스를 생성하기 위해선 new Vue 라는 생성자를 호출해야 합니다. 생성자란 객체를 새로 생성할 때 자주 사용하는 옵션과 기능들을 미리 특정 객체에 저장해 놓고, 새로운 객체를 생성할 때 기존에 포함된 기능과 더불어 기존 기능을 쉽게 확장하여 사용하는 기법입니다.
위 예제에는 생성자의 속성에 el, data와 같이 2개만 사용되었지만, template, methods, created 등 여러 가지 속성이 있습니다. 나머지 속성들은 뒷장에서 각각 설명하겠습니다.
2. 인스턴스의 유효 범위
Vue 인스턴스는 생성 후 HTML의 범위 내에서만 옵션 속성들이 적용됩니다. 이를 인스턴스의 유효 범위라 합니다. 컴포넌트 설명 부분에서 지역 컴포넌트와 전역 컴포넌트의 차이점을 이해하기 위해서도 꼭 알아야 하는 개념이며, 인스턴스의 유효 범위는 el 속성에 의해 정해집니다.
인스턴스가 생성된 후 화면에 적용되는 순서는 아래와 같습니다.
Vue 라이브러리 로딩
인스턴스 객체 생성
특정 화면 element에 인스턴스를 연결
인스턴스의 내용이 element에 적용
적용된 화면이 사용자에게 노출
만약 'Hello Vue.js!' 예제를 아래처럼 수정한다면 어떻게 될까요?
1
2
3
4
<div id="app">
</div>
{{ message }}
인스턴스 유효 범위를 벗어났기 때문에 message는 출력되지 않습니다.
3. 인스턴스 라이프 사이클
앞에 있는 인스턴스 생성 설명 부분에서 인스턴스의 속성 중 created라는 속성이 있습니다. 이처럼 Vue 인스턴스는 인스턴스 생성 중 인스턴스의 상태에 따라 호출할 수 있는 속성들인 라이프 사이클 속성들이 있습니다.
라이프 사이클과 해당 속성의 종류를 알아보겠습니다.
단계
설명
beforeCreate
인스턴스가 생성되고 최초로 실행되는 단계. 이 단계에서는 data 속성과 methods 속성이 아직 인스턴스에 정의되어 잇지 않고, 화면 요소에도 접근할 수 없습니다.
created
data, methods 속성의 정의된 단계. this.data 와 같이 사용할 수 있고 methods를 사용하여 로직을 실행할 수 있습니다. 하지만 아직 화면요소가 적용되기 전이기 때문에 template 속성에 정의된 요소에는 접근할 수 없습니다.
그리고 data, methods 속성에 접근 할 수 있는 첫 단계이기 때문에 서버에 데이터를 요청하여 받아오는 로직을 수행하기 좋습니다. 서버에 데이터를 요청하는 방법은 이후 장에서 설명되겠습니다.
beforeMount
template 속성에 지정한 마크업 속성을 render() 함수로 변환한 후 el 속성에 지정한 화면 요소에 인스턴스를 연결하기 전에 호출되는 단계.
mounted
el 속성에서 지정한 화면 요소에 인스턴스가 연결되고 호출되는 단계. template 속성에 정의된 요소에 접근할 수 있어 화면 요소를 제어하는 로직을 수행하기 좋은 단계입니다.
beforeUpdate
Vue의 특징 중 반응성(Reactivity)이 있습니다. 반응성이란 코드로 인한 데이터의 변화에 따라 화면이 즉각 반응하여 갱신되는 것을 의미합니다. 관찰되고 있는 데이터가 변화되어 화면으로 그려지기 직전에 호출되는 단계입니다.
변경 예정된 데이터의 값에 대한 로직을 수행하기 좋은 단계입니다. 주의할 점은 이 단계에서 값을 변경하는 로직을 넣더라도 화면이 반응하지 않습니다.
update
데이터가 변경된 후 화면에 반영된 후 실행되는 단계. 데이터 변경 후 화면 요소에 대한 제어 로직을 추가하기 좋습니다.
beforeDestroy
Vue 인스턴스가 소멸하기 직전에 단계. 아직 인스턴스에 접근할 수 있기 때문에 Vue 인스턴스의 데이터를 삭제하기 좋은 단계입니다.
destroyed
Vue 인스턴스가 소멸하고 나서 호출되는 단계. 인스턴스에 정의한 모든 속성이 제거되고 하위로 선언한 인스턴스까지 모두 소멸합니다.
Vue.js 는 웹 페이지 화면을 개발하기 위한 Front-end Framework 입니다.
기존 웹 개발자뿐만 아니라 HTML, CSS, Javascript 기초만 아는 웹 개발 입문자 및 컴퓨터 비전공자들도 배우기 쉽게 만들어졌습니다.
뷰는 화면단 라이브러리이자 프레임워크라고도 볼 수 있습니다. 어떤 의미인지 다음 그림으로 알아보겠습니다.
(점진적인 Framework로서의 Vue의 의미)
위 그림은 Vue의 창시자인 에반 유가 2017년 Vue.js 컨퍼런스에서 발표한 내용 중에 있는 그림입니다. Vue 코어 라이브러리는 화면단 데이터 표현에 관한 기능들을 중점적으로 지원하지만 프레임워크의 기능인 라우터, 상태 관리, 테스팅 등을 쉽게 결합할 수 있는 형태로도 제공됩니다. 즉, 라이브러리 역할뿐만 아니라 프레임워크 역할도 할 수 있다는 의미입니다. 그래서 Vue를 점진적인 프레임워크라고 표현합니다.
Angular1은 Framework로서 완전한 기능을 제공하는 MVC 구조로 출발하여 컴포넌트 기반의 Angular2로 진화하였습니다. 이 과정에서 TypeScript, ES6 등 기타 어느 Framework보다 더 많은 학습이 필요하게 됩니다. React 또한 ES6, JSX라는 장벽이 존재하며, 신기술이 끝없이 등장하는 상황에서 웹 개발자에게 주어지는 짐은 점점 더 무거워집니다. 따라서 쉽게 배울 수 있는 Vue의 등장으로 소규모 혹은 신규 프로젝트가 진행되는 곳에서는 Vue의 사용이 많아지고 있습니다.
둘째,React나 Angular에 비해 성능이 우수하고 빠릅니다.
Vue 제작팀에서 React와 Angular를 가지고 같은 테스트 케이스에서 성능을 비교한 결과 뷰가 가장 빠른 것으로 나타났습니다.
셋째,React와 Angular의 장점을 모두 갖고있습니다.
Vue는 구글에서 일하던 직원이 Angular를 더 가볍게 쓰고 싶어서 만든 Framework입니다. Angular의 데이터 바인딩 특성과 React의 가상 돔 기반 랜더링 특징을 모두 가지고 있습니다.
이처럼 다른 Front-end Framework 에 비해 성능이 우수할 뿐만 아니라 가볍고 빠르며, 배우기 쉽다는 점이 앞으로 더 많은 개발자들에 사랑을 받을 것 이라 전망됩니다. 사용자가 많아지면 생성되는 거대한 커뮤니티는 훌륭한 Framework로 이어지는 결과를 볼 수 있습니다.
2. Vue 의 특징
1. UI 화면단 라이브러리
Vue는 UI 화면 개발 방법 중 하나인 MVVM 패턴의 뷰 모델(ViewModel)에 해당하는 화면단 라이브러리입니다.
(MVVM 구조에서의 Vue.js의 위치)
MVVM 패턴이란 화면을 모델 - 뷰 - 뷰모델 로 구조화하여 개발하는 방식을 말합니다. 이러한 방식으로 개발하는 이유는 화면의 요소들을 제어하는 코드와 데이터 제어 로직을 분리하여 코드를 더 직관적이고 유지보수가 편하게 하기 위함입니다.
용어
설명
뷰(View)
사용자에게 보이는 화면
돔(DOM) *Document Object Model
HTML 문서에 들어가는 요소(태그, 클래스, 속성 등)의 정보를 담고 있는 데이터 트리
돔 리스너(DOM Listener)
돔의 변경 내역에 대해 즉각적으로 반응하여 특정 로직을 수행하는 장치
모델(Model)
데이터를 담는 용기, 보통은 서버에서 가져온 데이터를 자바스크립트 객체 형태로 저장
데이터 바인딩(Data Binding)
뷰(View)에 표시되는 내용과 모델의 데이터를 동기화
뷰 모델(ViewModel)
뷰와 모델의 중간 영역, 돔 리스너와 데이터 바인딩을 제공하는 영역
Icon
위키피디아에서는 MVVM 패턴을 아래와 같이 정의 합니다.
"마크업 언어나 GUI 코드를 비즈니스 로직 또는 백엔드 로직과 분리하여 개발하는 소프트웨어 디자인 패턴"
이말을 바꿔 해석해보면 "화면 앞단(Front-end)의 화면 동작과 관련된 로직과 화면 뒷단(Back-end)의 데이터베이스 처리 로직을 분리하여 더 깔끔하게 코드를 구성한다." 라고 할 수 있겠습니다.
웹 초창기에는 이런 Front,Back -end 라는 구분이 없었지만 화면요소에 대한 코드와 데이터베이스에서의 데이터에 대한 조작 등 한파일에 HTML, CSS, Javascript, Java 등 여러 코드가 섞이며 가동성이 현저히 떨어지기 때문에 이러한 문제점을 해결하기 위한 방법으로 MVVM 패턴이 사용되기 시작했습니다. Vue 뿐만아니라 React에서도 해당 패턴을 사용하고있습니다.
2. 컴포넌트 기반 프레임워크
Vue가 가지는 또 하나의 큰 특징은 컴포넌트(Component)기반 프레임워크라는 점입니다.
컴포넌트란 마치 레고 블럭과 같습니다. 레고 블럭을 잘 조합하면 여러가지 원하는 모형을 만들 수 있고 필요할 때 마다 만들어 놓은 레고 블럭들 끼리 조합 할 수 있습니다.
이와 같이 각 영역을 구분지어 관계를 형성해 놓으면 코드를 재사용하기 쉽게 됩니다. 따라서 프레임워크 자체에서 컴포넌트 방식을 추구하면 모두가 정해진 방식대로 컴포넌트를 활용할 수 있으므로 빠르게 개발할 수 있을 뿐만 아니라 남이 작성한 코드를 볼 때도 수월합니다.
3. Conclusions
Vue란 무엇인가에 대해 알아보았습니다.
Vue의 장점, 특징을 알아본 결과 개발자의 의도대로 Front-end Framework 는 매우 필요하지만 진입장벽의 문제로 안그래도 배울것이 많은 개발자들에게 좀더 쉽고 빠르게 사용할 수 있고, 그렇다고 해서 여타 다른 Framework에 뒤쳐지지 않을 Vue 가 과연 거대한 두 산맥(Angular, React)을 상대로 Front-end Framework 시장에서 살아남을 수 있을까요?
다음 장부터 실제 개발환경 구성과 기본예제를 통해 얼마나 강력하고 쉬운지에 대해 직접 체험해 보겠습니다.
마지막으로beforeRouteEnter와beforeRouteLeave를 사용하여 라우트 컴포넌트(라우터 설정으로 전달되는 컴포넌트) 안에 라우트 네비게이션 가드를 직접 정의 할 수 있습니다.
beforeRouteEnter
beforeRouteUpdate(2.2 버전에 추가)
beforeRouteLeave
const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 이 컴포넌트를 렌더링하는 라우트 앞에 호출됩니다. // 이 가드가 호출 될 때 아직 생성되지 않았기 때문에 // `this` 컴포넌트 인스턴스에 접근 할 수 없습니다! }, beforeRouteLeave (to, from, next) { // 이 컴포넌트를 렌더링하는 라우트가 이전으로 네비게이션 될 때 호출됩니다. // `this` 컴포넌트 인스턴스에 접근 할 수 있습니다. } }
beforeRouteEnter가드는 네비게이션이 확인되기 전에 가드가 호출되어서 새로운 엔트리 컴포넌트가 아직 생성되지 않았기 때문에this에 접근하지 못합니다.
그러나 콜백을next에 전달하여 인스턴스에 액세스 할 수 있습니다. 네비게이션이 확인되고 컴포넌트 인스턴스가 콜백에 전달인자로 전달 될 때 콜백이 호출됩니다.
beforeRouteEnter (to, from, next) { next(vm => { // `vm`을 통한 컴포넌트 인스턴스 접근 }) }
beforeRouteLeave안에서this에 직접 접근 할 수 있습니다. leave 가드는 일반적으로 사용자가 저장하지 않은 편집 내용을 두고 실수로 라우트를 떠나는 것을 방지하는데 사용됩니다. 탐색은next(false)를 호출하여 취소할 수 있습니다.
주어진 패턴을 가진 라우트를 동일한 컴포넌트에 매핑해야하는 경우가 자주 있습니다. 예를 들어 모든 사용자에 대해 동일한 레이아웃을 가지지만 하지만 다른 사용자 ID로 렌더링되어야하는User컴포넌트가 있을 수 있습니다.vue-router에서 우리는 경로에서 동적 세그먼트를 사용하여 다음을 할 수 있습니다.
const User = { template: '<div>User</div>' }
const router = new VueRouter({ routes: [ // 동적 세그먼트는 콜론으로 시작합니다. { path: '/user/:id', component: User } ] })
이제/user/foo와/user/bar같은 URL은 모두 같은 경로에 매핑됩니다.
동적 세그먼트는 콜론:으로 표시됩니다. 라우트가 일치하면 동적 세그먼트의 값은 모든 컴포넌트에서this.$route.params로 표시됩니다. 그러므로User의 템플릿을 다음과 같이 갱신하여 현재 사용자 ID를 표현할 수 있습니다 :
const User = { template: '<div>User {{ $route.params.id }}</div>' }
매개 변수와 함께 라우트를 사용할 때 주의 해야할 점은 사용자가/user/foo에서/user/bar로 이동할 때 동일한 컴포넌트 인스턴스가 재사용된다는 것입니다. 두 라우트 모두 동일한 컴포넌트를 렌더링하므로 이전 인스턴스를 삭제 한 다음 새 인스턴스를 만드는 것보다 효율적입니다. 그러나 이는 또한 컴포넌트의 라이프 사이클 훅이 호출되지 않음을 의미합니다.
vue-router는 라우트 매칭 엔진으로path-to-regexp를 사용하기 때문에 선택적 동적 세그먼트, 0개 이상/하나 이상의 요구 사항, 심지어 커스텀 정규식 패턴과 같은 많은 고급 매칭 패턴을 지원합니다. 이 고급 패턴들과vue-router에서 사용하는예제에 대한문서를 확인하십시오.
vue-router를 사용하면 중첩 된 라우트 구성을 사용하여이 관계를 표현하는 것이 매우 간단합니다.
이전 장에서 만든 앱을 생각해보십시오.
<div id="app"> <router-view></router-view> </div>
const User = { template: '<div>User {{ $route.params.id }}</div>' }
const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] })
여기에있는<router-view>는 최상위 outlet입니다. 최상위 경로와 일치하는 컴포넌트를 렌더링합니다. 비슷하게 렌더링 된 컴포넌트는 자신의 중첩 된<router-view>를 포함 할 수도 있습니다. 다음은User컴포넌트의 템플릿 안에 하나를 추가하는 예 입니다.