Vue 시작 및 사용해보기

0

Vue.js란?

Vue는 홈페이지의 소개에 따르면, 사용자 인터페이스를 만들기 위한 프로그레시브 프레임워크입니다. 즉 점진적으로 채택할 수 있도록 설계되어 있는 프레임워크라는 뜻인데, Vue의 핵심 라이브러리는 Vue로 구현한 뷰 레이어만 적용할 수 있기 때문에 다른 라이브러리나 기존 프로젝트와의 통합이 매우 쉽고, 여러 현대적인 개발 도구와 Vue를 지원하는 라이브러리를 함께 사용하면 정교한 싱글 페이지 어플리케이션도 쉽게 구현할 수 있습니다.

Vue는 다른 프레임워크와 자주 비교되어 지는데, Vue의 홈페이지에는 React, Angular, MobX, Polymer 등의 다른 프레임워크와 비교한 결과를 안내하고 있습니다. Vue와 다른 프레임워크 사이에서 고민을 하고 있다면 해당 페이지를 참고해 보면 도움이 될 것 같네요.

Vue 설치하기

Vue의 공식 가이드에는 HTML과 CSS, JavaScript에 대한 중간 수준 이상의 지식이 필요하다고 안내되어 있습니다. Vue는 다른 프레임워크에 비해 학습곡선이 낮은 편이지만, HTML과 CSS, Javascript가 익숙하지 않다면 각각의 언어에 대해 학습하고 이해해야 할 필요가 있습니다.

Vue Devtools

Vue Devtools는 크롬 브라우저에서 설치할 수 있는 확장 프로그램인데, Vue로 앱을 개발할 때, 보다 사용자 친화적인 인터페이스로 앱을 검사하고 디버깅 할 수 있습니다.

Vue.js devtools 페이지에 접속한 후 상단의 Add to Chrome 버튼을 눌러 설치하면 됩니다.

Vue.js devtools Extensions

스크립트로 직접 추가하기

Vue는 자바스크립트로 구현된 프레임워크이기 때문에, Vue 코어 스크립트를 다운로드 받아 script 태그를 추가해 주기만 하면 됩니다. Vue를 script로 추가하면 전역 변수로 등록되는데 필요한 위치에서 언제든지 불러와 사용할 수 있습니다.

Vue는 개발 버전상용 버전로 제공되는데, 앱을 개발 중인 상황이라면 모든 오류 메시지와 디버그 모드를 사용할 수 있는 개발 버전을 사용하는 것이 좋습니다.

CDN으로 사용하기

Vue는 프로토 타이핑이나 단순 학습 목적을 위해 최신 버전을 쉽게 사용해 볼 수 있도록 CDN으로도 스크립트를 제공하고 있습니다.

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

만약 특정 버전의 빌드 파일을 사용해야 하는 경우라면 아래와 같이 특정 버전의 빌드 파일을 추가할 수도 있습니다.

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>

만약 최신 자바스크립트의 ES 모듈을 사용할 수 있는 환경이라면 아래와 같이 ES 모듈 호환 빌드 파일을 사용할 수 있습니다.

<script type="module">
  import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.esm.browser.js'
</script>

NPM으로 사용하기

Vue 제작 팀은 대규모 애플리케이션을 구축하는 경우에는 NPM을 설치하도록 권장하고 있습니다. NPM은 일반적으로 Webpack이나 Browserify와 같은 모듈 번들러와 함께 통합해서 사용할 수 있습니다.

Vue는 모듈 번들러와 함께 사용할 수 있는 싱글 파일 컴포넌트 도구도 제공해 주고 있는데, NPM으로 Vue를 설치하려면 우선 Node.js를 설치하고, 아래의 명령어로 vue를 설치하면 됩니다.

npm install vue

이 명령어로 Vue를 설치하고 나면 다음과 같이 Vue를 실행할 수 있는 최소한의 환경으로 구성된 package-lock.json 파일이 생성되고, 관련된 모듈들이 설치됩니다.

NPM으로 설치한 Vue 폴더 구조

CLI 사용하기

Vue는 단일 페이지 애플리케이션를 빠르게 구축할 수 있는 Vue CLI를 통해, 최신 프론트엔드 워크 플로우를 위해 사전 구성된 빌드 설정을 제공하고 있는데, Vue CLI는 핫 리로드와 저장시 린트 체크 및 프로덕션 준비가 된 빌드 시스템으로, 시작하고 실행하는데는 몇 분 밖에 걸리지 않지만, Node.js와 관련 빌드 도구에 대한 사전 지식이 필요합니다.

Vue CLI 설치하기

Vue CLI는 npm 또는 yarn 명령어로 설치할 수 있습니다.

NPM으로 Vue CLI 설치하기
npm install -g @vue/cli
Yarn으로 Vue CLI 설치하기
yarn global add @vue/cli
Vue CLI 업데이트하기

Vue CLI는 다음의 명령어로 업데이트 할 수 있습니다.

NPM으로 Vue CLI 업데이트하기
npm update -g @vue/cli
Yarn으로 Vue CLI 업데이트하기
yarn global upgrade --latest @vue/cli
Vue CLI로 새 프로젝트 생성하기

Vue CLI로 프로젝트를 생성하는 경우 default(babel, eslint)를 선택하면 가장 기본적인 설정으로 프로젝트가 생성되고, 나중에 언제든지 옵션을 추가할 수 있습니다.

새 프로젝트 생성하기
vue create my-project

프로젝트를 생성한 후에는 다음의 명령어로 로컬 서버를 실행해주면 됩니다.

로컬 서버 실행하기
npm run serve

선언적 렌더링과 디렉티브

Vue는 간단한 템플릿 구문으로 다음과 같이 DOM의 내부에서 데이터를 선언적으로 렌더링 할 수 있는 방법을 제공합니다.

선언적 렌더링
<div id="app">
    {{ message }}
</div>

<script>
var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello, World'
    }
})
</script>

선언적 렌더링은 문자열 템플릿을 렌더링하는 것과 매우 유사하지만, Vue의 내부에서는 실제로 더 많은 작업을 하면서 데이터와 DOM을 연결시켜 반응형인 상태를 유지하게 되는데, 브라우저의 콘솔 창을 열고 app.message = 'HELLO, WORLD'와 같이 다른 값을 설정하면, 화면이 업데이트 된 값으로 변경되는 것을 확인할 수 있습니다.

이렇게 Vue는 #app과 같은 단일 DOM 요소에 연결되어 DOM 요소 자체를 제어하는데, HTML는 엔트리 포인트의 역할만을 하고 다른 모든 작업은 새롭게 생성된 Vue 인스턴스 내에서 발생한다는 특징이 있습니다.

디렉티브

엘리먼트 속성 바인딩
<div id="app-2">
    <span v-bind:title="message">title 속성에 동적 바인딩</span>
</div>

<script>
var app2 = new Vue({
    el: '#app-2',
    data: {
        message: new Date() + '에 로드됨'
    }
})
</script>

위 코드를 실행한 후 콘솔 창을 통해 확인해 보면 엘리먼트의 title 속성에 값이 바인딩 되었다는 것을 알 수 있는데, 여기서 사용된 v-bind라는 속성은 Vue제공하는 특수 속성으로, 디렉티브라고 합니다.

title 속성에 바인딩 된 데이터
title 속성에 바인딩 된 데이터

디렉티브는 Vue에서 제공하는 특수 속성임을 나타내는 v-라는 접두어가 붙는데, 렌더링 된 DOM에는 이 속성이 나타나지 않지만, 해당 엘리먼트는 v-bind에 적용된 특수한 반응형 동작을 하게 됩니다.

앞에서와 같이 브라우저의 콘솔 창을 열고 app2.message = 'New Message'라고 입력하면, 디렉티브가 적용된 엘리먼트의 title 속성이 업데이트 되는 것을 확인할 수 있습니다.

조건문과 반복문

Vue는 v-bind 외에도 v-if, v-for와 같은 다양한 디렉티브를 통해 엘리먼트를 제어할 수 있는데, 조건에 따른 동작을 제어하고 싶은 경우에는 v-if라는 디렉티브를 사용하면 엘리먼트의 동작을 쉽게 제어할 수 있습니다.

v-if

조건에 따라 엘리먼트 제어하기
<div id="app-3">
    <p v-if="seen">This element is shown.</p>
</div>

<script>
var app3 = new Vue({
    el: '#app-3',
    data: {
        seen: true
    }
})
</script>

위 코드는 app3.seen의 상태 설정에 따라 엘리먼트가 보여지거나, 보여지지 않도록 제어하는 코드인데, 브라우저의 콘솔 창에서 app3.seen = false와 같이 상태를 변경해 보면 엘리먼트가 사라지는 것을 확인할 수 있습니다.

여기서 v-ifv-for와 같은 디렉티브는 텍스트와 속성뿐만 아니라 DOM의 구조에도 데이터를 바인딩 할 수 있음을 보여주는데, 이 때 엘리먼트가 Vue에 삽입, 업데이트, 제거될 때 자동으로 트랜지션 효과를 적용할 수 있는 강력한 전환 효과 시스템도 사용할 수 있습니다.

v-for

만약 여러 개의 반복 작업이 필요한 경우라면 v-for 디렉티브를 사용하면 되는데, v-for 디렉티브는 배열의 데이터를 바인딩하여 리스트의 목록을 표시하도록 만들 수 있습니다.

엘리먼트 반복하기
<div id="app-4">
    <ol>
        <li v-for="item in lists">
            {{ item.text }}
        </li>
    </ol>
</div>

<script>
var app4 = new Vue({
el: '#app-4',
data: {
    lists: [
        { text: 'List 01' },
        { text: 'List 02' },
        { text: 'List 03' }
    ]
}
})
</script>

v-for 역시 브라우저의 콘솔 창에서 app4.lists.push({text: 'List 04'})와 같이 리스트를 동적으로 추가할 수 있습니다.

사용자 입력 핸들링

v-onv-model은 사용자와 앱의 상호작용을 위해 사용하는 디렉티브로 v-on은 Vue 인스턴스에서 메소드를 호출하는 이벤트 리스너와를 연결하고, v-model은 사용자의 입력과 앱 상태를 양방향으로 바인딩합니다.

v-on

v-on 디렉티브로 Vue 인스턴스에서 메소드를 호출하는 이벤트 리스너를 연결하는 방법은 DOM을 건드리지 않고 앱의 상태만을 업데이트 하는데, 모든 DOM 조작은 Vue에 의해 처리됩니다.

이벤트 연결하기
<div id="app-5">
    <p>{{ message }}</p>
    <button v-on:click="reverseMessage">거꾸로</button>
</div>

<script>
var app5 = new Vue({
    el: '#app-5',
    data: {
        message: 'Hello, World!'
    },
    methods: {
        reverseMessage: function () {
            this.message = this.message.split('').reverse().join('')
        }
    }
})
</script>

v-model

Vue는 양식에 대한 입력과 앱 상태를 양방향으로 바인딩하는 v-model 디렉티브를 제공하는데, 이 디렉티브를 사용하면 다음의 예제와 같이 사용자의 입력을 엘리먼트에 즉시 반영할 수 있습니다.

데이터 양방향 바인딩하기
<div id="app-6">
    <p>{{ message }}</p>
    <input v-model="message">
</div>

<script>
var app6 = new Vue({
    el: '#app-6',
    data: {
        message: '메세지를 입력해주세요.'
    }
})
</script>

컴포넌트 구성하기

컴포넌트란 작고 독립적이며 재사용할 수 있는 조각들로, 대규모 애플리케이션을 구축할 수 있게 해주는 추상적인 개념입니다. 이 컴포넌트는 Vue의 중요한 개념 중에 하나인데, 거의 모든 유형의 애플리케이션 인터페이스는 컴포넌트 트리로 추상화할 수 있습니다.

Vue 컴포넌트 추상화 개념

Vue에서 컴포넌트는 미리 정의된 옵션을 가진 Vue 인스턴스로, Vue에서 컴포넌트를 등록하는 방법은 다음과 같습니다.

컴포넌트 정의하기
// todo-item이란 이름의 컴포넌트를 정의함
Vue.component('list-item', {
  template: '<li>할일 목록입니다.</li>'
})
var app = new Vue(...)

위와 같이 컴포넌트를 정의하면, 해당 컴포넌트를 다른 컴포넌트의 템플릿에 추가할 수 있습니다.

컴포넌트 추가하기
<ol>
    <list-item></list-item>
</ol>

그런데 앞에서와 같이 단순한 형태로 컴포넌트를 정의하면 똑같은 내용의 엘리먼트만을 렌더링하게 되기 때문에 컴포넌트를 정의할 때 부모 영역의 데이터를 자식 컴포넌트에게 전달할 수 있도록 prop이라는 속성을 제공해 줄 필요가 있습니다.

prop을 추가하여 개선한 컴포넌트 정의
Vue.component('list-item', {
  props: ['label'],
  template: '<li>{{ label.text }}</li>'
})

위와 같이 prop 속성을 추가해주면 list-item 컴포넌트는 "label"로 정의된 prop을 통해 사용자 정의 속성과 같은 것을 입력받을 수 있는데, 다음과 같이 v-bind를 사용하여 각각의 반복되는 list-item을 컴포넌트에 전달할 수 있습니다.

컴포넌트 정의가 개선된 리스트 예제
<div id="app-7">
    <ol>
        <list-item v-for="item in lists" v-bind:label="item" v-bind:key="item.id"></list-item>
    </ol>
</div>

<script>
Vue.component('list-item', {
    props: ['label'],
    template: '<li>{{ label.text }}</li>'
})

var app7 = new Vue({
    el: '#app-7',
    data: {
        lists: [{
                id: 0,
                text: 'List 01'
            },
            {
                id: 1,
                text: 'List 02'
            },
            {
                id: 2,
                text: 'List 03'
            }
        ]
    }
})
</script>

코드에서는 list-item을 HTML의 엘리먼트처럼 사용하고 있는데, 이렇게 정의된 컴포넌트를 사용하면서 v-bind를 통해 컴포넌트의 "label"이라는 속성에 리스트의 각 객체를 전달하고, v-bind:key라는 디렉티브로 lists의 각 객체에 있는 id 값을 전달해 키로 사용하고 있습니다.

이렇게 대규모 애플리케이션에서는 개발을 보다 쉽게 관리 할 수 있도록 전체 앱을 컴포넌트 단위로 나누는 것이 필수적이기 때문에 컴포넌트의 개념을 잘 알아둘 필요가 있습니다. 다음은 앱을 컴포넌트 단위로 나누는 대표적인 구조라고 할 수 있습니다.

앱 개발을 위한 컴포넌트 추상화
<div id="app">
  <app-nav></app-nav>
  <app-view>
    <app-sidebar></app-sidebar>
    <app-content></app-content>
  </app-view>
</div>

사용자 정의 엘리먼트

Vue 컴포넌트는 Web Components Spec의 일부인 사용자 정의 엘리먼트와 유사한데, 다음과 같은 중요한 차이가 있습니다.

  • Web Components Spec은 최종안이 정해졌지만 모든 브라우저들이 기본적으로 구현하고 있는 반면, Vue 컴포넌트는 지원되는 모든 브라우저(IE 9 이상)에서 폴리필 없이도 일관된 방식으로 동작하며, 필요한 경우 기본 사용자 정의 엘리먼트 내에 래핑이 가능하다.
  • Vue 컴포넌트는 컴포넌트간 데이터의 흐름, 사용자 정의 이벤트와 통신, 빌드 도구와의 통합 등 기본 사용자 지정 엘리먼트에서 사용할 수 없었던 중요한 기능을 제공한다.

Leave a Reply