4 minute read


1. 뷰 인스턴스?

뷰 인스턴스는 뷰로 화면을 개발하기 위해 필수적으로 생성해야 하는 기본 단위이며 모든 Vue 앱은 Vue 함수로 새 Vue 인스턴스를 만드는 것부터 시작한다.

1
2
3
4
5
6
7
//vue 인스턴스 생성
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js'
  }
});

1.2 뷰 인스턴스 생성자

new Vue()로 인스턴스를 생성할 때 Vue를 생성자라고 한다. Vue 생성자는 뷰 라이브러리를로딩하고 나면 접근할 수 있다. 생성자를 사용하는 이유는 뷰로 개발할 때 필요한 기능들을 생성자에 미리 정의해놓고 그 기능을 재정의해서 편리하게 사용하기 위해서이다.

생성자?
객체를 새로 생성할 때 자주 사용하는 옵션과 기능들을 미리 특정 객체에 저장해놓고, 해로 객체를 생성할 때 기존에 포함된 기능과 더불어 기존 기능을 쉽게 확장하여 사용하는 기법

1.3 뷰 인스턴스 옵션

뷰 인스턴스 옵션 속성은 인스턴스를 생성할 때 재정의할 data, el, template 등의 속성을 의미한다.

속성 설명
template 화면에 표시할 HTML, CSS 등의 마크업 요소를 정의하는 속성
methods 화면 로직 제어와 관계된 메스드를 정의하는 속성
created 뷰 인스턴스가 생성되자마자 실행할 로직을 정의할 수 있는 속성
el Vue가 DOM에서 구성 요소의 위치를 추적하는데 사용되는 속성
data 컴포넌트 인스턴스 data 객체에 접근 가능한 속성
options 해당 컴포넌트의 option(data,el …)에 접근할 수 있는 속성

1.4 뷰 인스턴스 유효 범위

뷰 인스턴스를 생성하면 HTML의 특정 범위 안에서만 옵션 속성들이 적용되어 나타나는데, 이를 유효 범위라고 한다.


만약 유효범위를 벗어난다면 뷰에서 인식하지 못하고 값이 치환되지 않은 상태로 출력이 될 것이다.

** 인스턴스 생성 기본 코드 **

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Getting Started</title>
  </head>
  <body>
    <div id="app">
      {{ message }}
    </div>

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



2. 뷰 인스턴스 라이프 사이클

라이프 사이클이란 모바일 앱을 비롯해 일반적으로 애플리케이션이 가지는 생명주기를 뜻한다. Vue.js에서도 라이프 사이클 속성들이 있는데 created, beforeCreate, beforeMount, mounted 등 인스턴스의 변경 및 소멸과 관련되어 총 8개가 있다.



단계를 크게 나눠보면 인스턴스의 생성 - 생성된 인스턴스를 화면에 부착 - 부착된 인스턴스 내용의 갱신 - 인스턴스 제거의 4단계로 볼 수 있다. 각 속성에 대해 하나씩 알아보자.


2.1 beforeCreate

인스턴스가 생성되고 나서 가장 처음 실행되는 단계로 이 단계에서는 data 속성과 methods 속성이 아직 인스턴스에 정의되어 있지 않고, 돔과 같은 화면 요소에도 접근이 불가능 하다.


2.2 created

data 속성과 methods 속성이 정의 된 단계로 data 속성과 methods 속성에 정의된 값에 접근해서 로직을 실행할 수 있다. 따라서, 서버에 데이터를 요청하여 받아오는 로직을 수행하기 좋은 단계이다. 하지만 아직 인스턴스가 화면에 부착되기 전이기 때문에 template 속성에 정의된 돔 요소로 접근은 불가능하다.


2.3 beforeMount

created 단계 이후 template 속성에 지정한 마크업 속성을 render() 함수로 변환 후 el 속성에 지정한 화면요소(돔)에 인스턴스를 부착하기 전에 호출되는 단계로, render() 함수가 호출되기 직전의 로직을 추가하기 좋다.


2.4 Mounted

el 속성에서 지정한 화면 요소에 인스턴스가 부착되고 나면 호출되는 단계로, template 속성에 정의한 화면 요소(돔)에 접근할 수 있어 화면 요소를 제어하는 로직을 수행하기 좋은 단계이다. 돔에 인스턴스가 부착되자마자 바로 호출되며 라이프 사이클 중 가장 많이 사용하게 된다.


2.5 beforeUpdate

데이터가 변경되면 가상 돔으로 화면을 다시 그리기 전에 다시 호출되는 단계로 el 속성에서 지정한 화면 요소에 인스턴스가 부탁되고 나면 인스턴스에 정의한 속성들이 화면에 치환된다. 이 단계에는 데이터가 변경되는 호출되는 단계로 값을 변경하는 로직을 넣더라도 화면이 다시 그려지지는 않는다.


2.6 updated

데이터가 변경되고 나서 가상 돔으로 다시 화면을 그리고 난 뒤 실행되는 단계로 데이터 변경으로 인한 화면 요소 변경까지 완료된 시점에서 호출되는 단계이다. 따라서, 데이터 변경 후 화면 요소 제어와 관련된 로직을 추가하기 좋다.


2.7 beforeDestory

뷰 인스턴스가 파괴되기 직전에 호출되는 단계로 이 단계에서는 인스턴스 접근이 가능하며 뷰 인스턴스의 데이터를 삭제하기 좋다.


2.8 destoryed

뷰 인스턴스가 완전히 파괴된 후 호출되는 단계이다. 인스턴스에 정의된 모든 속성이 제거되고 하위에 선언된 인스턴스 역시 모두 제거된다.



3. 뷰의 특성

실제로 아래 샘플코드를 실행해보면 beforeCreate 부터 updated 까지 실행되는 것을 볼 수 있다. 원래라면 mounted 까지 실행이 됐겠지만 mounted 에서 메세지를 변경을 했고 그로 인해 beforeUpdate와 Updated가 호출된 것이다.

beforeDestory와 Destoyed는 위에서 정리한 바와 같이 인스턴스가 파괴될 때 호출되는데 “ 1 “와 같이 호출해보면 beforeDestory와 Destoyed가 호출되는 것을 볼 수 있고, mounted 에서 한 것과 동일하게 메세지를 변경해보면 화면의 메세지가 변경되지 않는 것을 확인할 수 있다.

하지만 destoryed는 인스턴스가 파괴될 때 호출된다고 되어 있는데 막상 다음과 같이 “ 2 “ 인스턴스에 접근해보면 접근이 가능할뿐더러 내부 요소들도 지워지지 않은 것을 볼 수 있는데 이는 뷰의 특성 때문이다.

우리가 “ 1 “과 같이 Destroyed를 호출 했지만 파괴된 인스턴스는 v-Dom 영역의 인스턴스이고 실제 DOM 영역에 반영되지 않았기 때문에 인스턴스가 파괴되지 않은 것처럼 보이는 것이다.

V-DOM 영역의 변화를 DOM 영역에 맞춰 적용하게 되면 파괴된 인스턴스가 사라지는 것을 확인할 수 있다.


** Vue.js Life Cycle 확인 예제 **

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<div id="app">
  {{message}}
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  let vueObj = new Vue({
      el : '#app',
      data : {
        message : "vue_lisrCycle",
      },
      beforeCreate : function(){
        console.log("beforeCreate");
      },
      created : function(){
        console.log("created");
      },
      beforeMount : function(){
        console.log("beforeMount");
      },
      mounted : function(){
        console.log("mounted");
        this.message = "Test life Cycle";
      },
      beforeUpdate : function(){
        console.log("beforeUpdate");
      },
      updated : function(){
        console.log("updated");
      },
      beforeDestroy : function(){
        console.log("beforeDestroy");
      },
      destroyed : function(){
        console.log("destroyed");
      }
  });
</script>