[Vue.js] 5. 화면을 개발하기 위한 기본 지식과 팁 - 템플릿&프로젝트 구성

𝙃𝙖𝙞𝙡𝙚𝙮·2021년 10월 29일
0

Do it! Vue.js

목록 보기
5/6
post-thumbnail

05-1 뷰 템플릿

뷰 템플릿이란?

HTML, CSS 등의 마크업 속성과 뷰 인스턴스에서 정의한 데이터 및 로직들을 연결하여 사용자가 브라우저에서 볼 수 있는 형태의 HTML로 변환해주는 속성이다.

<script>
  new Vue({
    template : '<p> Hello {{ message }} </p>'
  });
</script>

위와 같이 template 속성에서 정의한 마크업과 데이터는 가상 dom 기반의 render() 함수로 변환되고, 변환된 함수는 최종적으로 사용자가 볼 수 있게 화면을 그리는 역할을 한다.
이외에도 ES6 싱글 파일 컴포넌트 체계의 <template>를 활용하는 방법도 있지만 우선 넘어가도록 한다.

아무튼 템플릿에서 사용하는 뷰의 속성의 종류는 아래와 같다.

  • (1) 데이터 바인딩
  • (2) 자바스크립트 표현식
  • (3) 디렉티브
  • (4) 이벤트 처리
  • (5) 고급 템플릿 기법

데이터 바인딩

데이터 바인딩이란?

HTML 화면 요소를 뷰 인스턴스의 데이터와 연결하는 것을 의미함

주요 문법

  • 콧수염 괄호 {{ }}
    뷰 인스턴스 데이터를 HTML 태그에 연결하는 가장 기본적인 텍스트 삽입 방법
    아래 코드의 data 속성의 message 값이 바뀌면 뷰 반응성에 의해 화면이 자동으로 갱신되며, 만약 뷰 데이터가 변경되어도 값을 바꾸고 싶지 않다면 v-once 속성을 사용하면 된다.
    <div id="app"> <!-- <div id="app" v-once> -->
        {{ message }}
    </div>

    <script>
          new Vue({
            el: '#app',                 
            data : {                    
              message : 'Hello Vue.js!'
            }
          });
      </script>
  • v-bind 속성
    v-bind는 아이디, 클래스, 스타일 등의 HTML 속성 값에 뷰 데이터 값을 연결할 때 사용하는 데이터 연결 방식이다. 형식은 v-bind 속성으로 지정할 HTML 속성이나 props 속성 앞에 접두사로 붙여준다. 아래 코드를 보면 이해가 쉬울 것이다. 특히 styleA 속성은 스타일 값이 적용되면서 바로 화면에 반영되어 나타나게 된다.
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Vue v-bind example</title>
    </head>
    <body>
    <div id="app">
      <p v-bind:id="idA">아이디 바인딩</p>        <!-- v-bind:는 :로 간소화 할 수 있다. -->
      <p v-bind:class="classA">클래스 바인딩</p>  <!-- ex) :class="classA" -->
      <p v-bind:style="styleA">스타일 바인딩</p>  <!-- ex) :style="styleA" -->
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      new Vue({
        el: '#app',
        data : {
          idA: 10,
          classA: 'container',
          styleA: 'color: blue'
        }
      });
    </script>
    </body>
    </html>

자바스크립트 표현식

뷰 템플릿에서도 자바스크립트 표현식을 아래와 같이 사용할 수 있다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue JS example</title>
</head>
<body>
<div id="app">
  <div v-bind:id="app">
    <p>{{ message }}</p>
    <p>{{ message + "!!!!" }}</p>
    <p>{{ message.split('').reverse().join('') }}</p> <!-- 자바스크립트 내장 API 사용 가능 -->
  </div>

</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  new Vue({
    el: '#app',
    data : {
      message: 'Hello Vue.js!'
    }
  });
</script>
</body>
</html>

하지만 사용에서 주의점도 존재한다. 크게 두가지로 아래와 같다.

첫째, 자바스크립트의 선언문과 분기 구문은 사용할 수 없다.
둘째, 복잡한 연산은 인스턴스 안에서 처리하고 화면에는 간단한 연산 결과만 표시해야 한다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue JS example</title>
</head>
<body>
  <div id="app">
    <!-- 코드 실행 시,  (x) 항목은 주석처리 후 실행해야 됨 -->
    {{ var a = 10; }}           <!-- (x) 선언문은 사용 불가능 -->
    {{ if(true) {return 100} }} <!-- (x) 분기 구문은 사용 불가능  -->
    {{ true ? 100 : 0 }}        <!-- (o) 삼항 연산자는 사용 가능  -->

    {{ message.split('').reverse().join('') }} <!-- (x) 복잡한 연산은 인스턴스 안에서 수행  -->
    {{ reversedMessage }} <!-- (o) 스크립트 computed 속성으로 계산 후 최종 값만 표현  -->

  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data : {
        message: 'Hello Vue.js!'
      },
      computed: { // 데이터 속성을 자동으로 계산해주는 속성
        reversedMessage : function() {
          return this.message.split('').reverse().join('');
        }
      }
    });
  </script>
</body>
</html>

위 코드를 실행하면 아래의 복잡한 연산부분들은 감이 올 것이다. 사실 복잡한 연산을 인스턴스에서 수행한다고 해서 별도 오류가 생기진 않는다. 하지만, computed 속성을 수행하면 코드의 가독성을 높이는 것 뿐만 아니라, computed 속성의 캐싱 효과를 얻을 수 있다. 여기서 말하는 캐싱효과란, 반복적인 연산에 대해 미리 계산 후 저장하여, 필요할 때 바로 불러오는 것으로 이에 대한 효과는 뒤에서 자세히 살펴본다.

디렉티브

뷰 디렉티브(Directive)란 HTML 태그 안에 v-접두사를 가지는 모든 속성을 의미한다. 즉, 화면의 요소를 더 쉽게 조작하기 위해 사용하는 기능으로, 뷰 데이터 값이 변경되었을 때, 화면의 요소들이 Reactive하게 반응하여 변경된 데이터 값에 따라 갱신된다.

<a v-if="flag">두잇 Vue.js</a>

위 코드의 <a>는 뷰 인스턴스 데이터 속성에 정의된 flag 값이 참(true)이면 보일 것이고, 거짓(false)이면 보이지 않을 것이다.

디렉티브 이름역할
v-if지정한 뷰 데이터 값의 참/거짓 여부에 따라 해당 HTML 태그를 화면에 표시하거나 표시하지 않음
v-for 지정한 뷰 데이터의 개수만큼 HTML 태그를 반복 출력함
v-showv-if와 유사하게 데이터 진위 여부에 따라 HTML 태그를 화면에 표시하거나 하지 않음. 다만 v-show는 css 효과에 한함
v-bindHTML 태그의 기본 속성과 뷰 데이터 속성을 연결함
v-on화면 요소의 이벤트를 감지하여 처리할 때 사용함
v-model폼(form)에 주로 사용되며, 폼에 입력한 값을 뷰 인스턴스의 데이터와 즉시 동기화 함. 화면에 입력된 값을 저장하여 서버에 보내거나, watch와 같은 고급 속성을 이용하여 추가 로직을 수행할 수 있음. <input>, <select>, <textarea> 태그에만 사용할 수 있음
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue Template - Directives </title>
</head>
<body>
  <div id="app">
    <a v-if="flag">두잇 Vue.js</a>
    <ul>
      <li v-for="system in systems">{{ system }}</li>
    </ul>
    <p v-show="flag">두잇 Vue.js</p>
    <h5 v-bind:id="uid">뷰 입문서</h5> <!-- <h5 id=10>로 화면에 표시됨 -->
    <button v-on:click="popupAlert">경고 창 버튼</button>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data : {
        flag: true,
        systems: ['android', 'ios', 'window'],
        uid: 10
      },
      methods: {
        popupAlert: function() {
          return alert('경고 창 표시');
        }
      }
    });
  </script>

</body>
</html>

이벤트 처리

뷰에서는 화면에서 발생한 이벤트를 처리하기 위해 v-on 디렉티브와 methods 속성을 활용한다. 사실 해당 내용은 바로 이전에 수행했던 디렉티브 예시로도 이해가 충분히 되리라 생각한다.
또한 v-on 디렉티브로 method 호출 시, 인자 값을 넘길 수도 있으며, 인자 값을 전달하지 않아도 event 인자를 정의하면 해당 돔 요소의 이벤트 객체에도 접근할 수 있다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue example 05-7 </title>
</head>
<body>
<div id="app">
  <button v-on:click="clickBtn">경고 창 버튼</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  new Vue({
    el: '#app',
    methods: {
      clickBtn :function(event) {
        console.log(event);
      }
    }
  });
</script>

</body>
</html>

고급 템플릿 기법

computed 속성

데이터의 연산들을 정의하는 영역

이전에 복잡한 데이터 연산은 HTML영역이 아닌 computed속성에서 해야 가독성과 캐싱, 두 마리의 토끼를 잡을 수 있다고 설명했었다.

watch 속성

데이터 변화를 감지하여 자동으로 특정 로직을 수행하는 영역

데이터 호출과 같이 시간이 상대적으로 더 많이 소모되는 비동기 처리에 적합하다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue watch example</title>
</head>
<body>
  <div id="app">
    <input v-model="message">
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue.js'
      },
      watch: {
        message: function(data) {
          console.log("message의 값이 바귑니다 : ", data);
        }
      }
    });
  </script>
</body>
</html>

위 코드와 같이, <input> 박스 입력 값을 v-model 디렉티브로 연결하여, 입력 값의 변화가 있을 때마다 watch 속성에서 변화된 로그 값을 출력하게 된다.

05-2 뷰 프로젝트 구성 방법

HTML 파일에서 뷰 코드 작성 시의 한계점

지금까지 HTML 파일로 예시를 들었다. 사실 HTML 내부에서는 구문 강조가 별도로 되지 않기 때문에 태그의 관계나 스타일 적용에 어려움을 겪을 수 있다.
게다가 HTML로 작성을 하다보면, Vue를 Vue 답게 사용할 수 없다. Vue Application은 여러 개의 컴포넌트로 화면을 구성하고, 페이지 사이를 이용할 때는 라우터를 사용해야 한다.

싱글 파일 컴포넌트 체계

.vue 파일로 프로젝트 구조를 구성하는 방식

따라서 Vue Application에서는 싱글 파일 컴포넌트(Single File Components)체계를 활용한다. .vue파일은 아래와 같은 구조를 갖는다.

1. 화면에 표시할 요소들을 정의하는 영역(HTML, Vue데이터 바인딩, ...)
<template>
</template>

2. Vue 컴포넌트 내용을 정의하는 영역(template, data, methods, ...)
<script>
</script>

3. 템플릿에 추가한 HTML 태그의 CSS 스타일을 정의하는 영역
<style>
<style>

뷰 CLI

앞에서 배운 싱글 파일 컴포넌트 체계를 사용하기 위해서는 .vue 파일을 웹 브라우저가 인식할 수 있는 형태의 파일로 변환해주는 웹팩(Webpack)이나 브라우저리파이(Browserify)와 같은 도구가 필요하다.

웹팩(Webapck)이란, 웹 앱의 자원(HTML, CSS, IMG)들을 자바스크립트 모듈로 변환해 하나로 묶어 웹 성능을 향상시켜주는 자바스크립트 모듈 번들러이다.

뷰 CLI 설치

하지만 아무튼 이런 도구들을 하나하나 배우긴 어려우니, 우리는 CLI(Command Line Interface)를 사용하자.

$ npm install vue-cli -global

뷰 CLI 명령어

뷰 개발을 시작할 때, 초기 프로젝트를 쉽게 구성해주는 명령어는 $ vue init이다. 이를 입력할 때 사용하는 프로젝트 템플릿 종류는 다음과 같이 6가지다.

템플릿 종류설명
$ vue init webpack고급 웹팩 기능 (테스팅, 문법 검사 등 지원)
$ vue init webpack-simple웹팩 최소 기능 (빠른 화면 프로타이핑용)
$ vue init browserify고급 브라우저리파이 기능 (테스팅, 문법 검사 등 지원)
$ vue init browserify-simple브라우저리파이 최소 기능(빠른 화면 프로타이핑용)
$ vue init simple최소 뷰 기능만 들어간 HTML 파일 1개 생성
$ vue init pwa웹팩 기반의 프로그레시브 웹 앱

뷰 CLI로 프로젝트 생성하기

$ vue init webpack-simple

$ npm install

위 명령어를 실행하면 vue application을 구동하기 위한 라이브러리를 모두 다운로드하게 된다. 다운로드가 완료되면 아래와 같은 폴더 구조가 생성된다.

(1) node_modules : $ npm insatll로 다운받은 라이브러리가 존재하는 위치
(2) src : .vue파일을 비롯하여 vue app이 동작하는데 필요한 로직이 들어갈 위치
(3) index.html : 뷰로 만든 웹앱의 시작점. $ npm run dev실행 시 로딩되는 파일
(4) package.json : npm 설정 파일. vue app이 동작하는데 필요한 라이브러리들을 정의하는 파일
(5) webpack.config.js : 웹팩 설정파일. 웹팩 빌드를 위해 필요한 로직들을 정의하는 파일

특히 (4) package.json파일 내용은 아래와 같다.

{
  //프로젝트 정보
  "name": "cli-template",
  "description": "A vue.js project",
  "version": "1.0.0",
  "author": "hailey",
  "license": "MIT",
  "private": true,
  
  //npm 실행 명령어
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  },
  
  //뷰, 웹팩 관련 라이브러리
  "dependencies": {
    "vue": "^2.5.11"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ],
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.0",
    "babel-preset-stage-3": "^6.24.1",
    "cross-env": "^5.0.5",
    "css-loader": "^0.28.7",
    "file-loader": "^1.1.4",
    "vue-loader": "^13.0.5",
    "vue-template-compiler": "^2.4.4",
    "webpack": "^3.6.0",
    "webpack-dev-server": "^2.9.1"
  }
}

$ vue init명령어 실행 시에 생성되는 파일로, 프로젝트 정보를 담고 있는 설정 파일임과 동시에 npm 명령어 및 뷰로 app을 제작하는데 필요한 라이브러리 정보를 포함하고 있다.

마지막으로 $ npm run dev를 실행하면 브라우저가 실행되게 된다. 이는 index.html 파일이 보여지게 되는 것이다.

특히 아래 로그를 보면, http://localhos:8080에서 구동되고 있으며, 웹팩 결과값이 /dist/에서 제공되고 있다는 것을 확인할 수 있다.

뷰 로더

웹팩에서 지원하는 라이브러리로 싱글 파일 컴포넌트 체계에서 사용하는 .vue 파일의 내용을 브라우저에서 실행 가능한 웹 페이지의 형태로 변환해준다.

앞선 예에서 simpleProject를 실행했을 때, App.vue파일의 내용이 웹페이지에 표시되는 것을 확인했다. 우리가 $ npm run dev실행 시 App.vue에서 <template>, <script>, <style>의 내용이 각 HTML, JS, CSS 코드로 인식될 수 있도록 뷰 로더가 변환 작업이 수행된다.

웹팩 설정 파일의 뷰 로드 속성 확인

webpack.config.js파일을 보면 다음과 같이 뷰 로더가 적용되어 있다.

module: {
    rules: [
      {
        test: /\.css$/,			//대상파일
        use: [				//사용로더
          'vue-style-loader',
          'css-loader'
        ],
      },

컴포넌트는 체계적인 프로젝트 폴더 구조를 위해 일반적인 방식에 맞춰, /app/components밑에 생성한다면, 그 각각의 컴포넌츠 내 모든 .vue파일에 뷰 로더가 적용될 것이다.

profile
ෆ 𝓋𝒾𝓈 𝓉𝒶 𝓋𝒾𝑒 ෆ

0개의 댓글