Vue.js mounted created 차이 | 예제를 통해 쉽게 이해하자 (Difference between the created and mounted lifecycle)

남양주개발자

·

2021. 11. 2. 21:34

728x90
반응형

Vue.js mounted created 차이 예시를 통해 쉽게 이해하자 (Difference between the created and mounted lifecycle)

Vue.js를 처음 접하면 Vue의 라이프사이클이 생소하기 때문에 created, mounted가 무엇인지 구별이 안될 수 있습니다. 각 라이프사이클 훅에서 어떤 일이 일어나고, 우리가 어떻게 사용하는지에 대해서 다뤄보도록 하겠습니다. 그리고 Vue.js를 통해 개발하는 개발자라면 아래 첨부한 라이프사이클 다이어그램은 꼭 인지하고 있을 필요가 있습니다.

라이프사이클 훅(Lifecycle hooks)이란?

각 컴포넌트는 생성될 때 일련의 초기화 단계를 거칩니다. 예를들어 데이터 관찰, 템플릿 컴파일, 인스턴스를 DOM에 마운트, 데이터 변경 시 DOM을 업데이트해야합니다. 그 과정에서 라이프사이클 훅이라 불리우는 함수도 실행하여, 사용자가 특정 단계에서 자신의 코드를 추가할 수 있는 기회를 제공합니다.

라이프사이클 다이어그램

다음은 인스턴스 수명 주기에 대한 다이어그램입니다. 지금 진행 중인 모든 것을 완전히 이해할 필요는 없지만 더 많이 배우고 구축함에 따라 유용한 참고 자료가 될 것입니다.

Vue.js 라이프사이클(Lifecycle) 다이어그램

created()

인스턴스가 생성된 후 동기적으로 호출됩니다. 이 단계에서 인스턴스는 data 관찰, computed 속성, methods, watch/이벤트 콜백 등의 설정이 준비되었음을 의미하는 옵션 처리를 완료합니다. 그러나 마운트 단계(mounted)가 시작되지 않았으며, $el 속성을 사용할 수 없습니다. 쉽게 말해 DOM을 제외한 초기 데이터 설정이 완료된 상태입니다. (DOM 세팅이 안되었기 때문에 element에 접근할 수 없습니다.)

created 라이프사이클 예시

created()에서는 컴포넌트의 데이터와 이벤트에 엑세스할 수 있습니다. 따라서 count 값을 아래와 같이 수정할 수 있습니다. 컴포넌트 초기에 외부에서 부여받은 설정에 의해 기본 값 변경이 필요하다면 이 단계에서 변경하는 것이 적절합니다.

<template>
  <div id="app">
    {{ count }}
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      count: 1,
    };
  },
  created() {
    this.count = 5;
  },
};
</script>

비동기 호출(async/await, promise) 구문을 통해 API 데이터를 가져올 필요가 있다면 mounted 라이프사이클을 활용하세요. Vue 라이프사이클은 비동기 흐름을 기다리지 않습니다. 아래 이미지는 created 라이프사이클에서 강제로 딜레이를 걸어서 5초를 지연시킨 후 데이터를 변경한 예시입니다. 우측 콘솔창을 보면 async/await 비동기 호출 구문을 무시하고 Vue 라이프사이클이 진행된 것을 확인할 수 있습니다.

Vue 라이프사이클 비동기 호출 구문 추가 예시

비동기(async) 데이터를 받은 후 필연적으로 화면이 변경되고, 다양한 추가 작업이 필요할 것입니다. 로직을 단순화하여 버그가 일어날 상황을 줄이세요.

mounted() (DOM Insertion)

인스턴스가 마운트된 후 호출되며, 여기서 Vue.createApp({}).mount()로 전달된 엘리먼트는 새로 생성된 vm.$el로 대체됩니다. 루트 인스턴스가 문서 내의 엘리먼트에 마운트되어 있으면, mounted가 호출될 때 vm.$el도 문서에 포함(in-document)됩니다. DOM이 생성되긴 했지만 mounted는 모든 자식 컴포넌트가 마운트되었음을 보장하지 않습니다. 그렇기 때문에 전체 화면내용이 렌더링될 때까지 기다리려면, mounted 내에서 vm.$nextTick를 사용합니다.

mounted 라이프사이클 예시

Vue.js에서 isApp 데이터가 true일 경우 DOM을 노출시키는 로직이 있다고 가정해봅시다. 초기값은 false로 컴포넌트 생성시점에는 isApp 값이 false이기 때문에 DOM이 생성되지 않지만, mounted 라이프사이클 시점에 isApp 데이터의 값을 true로 변경함으로써 DOM 노출 조건을 만족시켰습니다. 그리고 바로 하단에서 $refs API를 활용해서 ref 값이 target인 DOM을 접근하려고 했으나 undefined로 DOM을 찾을 수 없는 경우가 발생합니다.

<template>
  <div id="app">
    <div v-if="isApp">
      <div ref="target">hello</div>
    </div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      isApp: false,
    };
  },
  async mounted() {
    this.isApp = true;
    console.log(this.$refs["target"]); // 갱신안됨ㅠ
  },
};
</script>

undefined를 리턴하는 모습

이런 문제점을 해결하기 위해 사용하는 API가 바로 nextTick입니다. 바로 nextTick을 활용해볼까요? mounted 라이프사이클 안에 this.$nextTick 구문을 추가합니다. nextTick API의 인자로 콜백함수(calllback function)를 넣어주고 여기서 DOM 참조값을 확인합니다.

<script>
export default {
  ...
  mounted() {
    this.isApp = true;
    // nextTick 추가!
    this.$nextTick(() => {
      console.log(this.$refs["target"]); // 갱신됨!
    });
  },
};
</script>

nextTick 콜백함수에서 console.log를 통해 참조값을 확인하면 정상적으로 DOM 참조를 할 수 있음을 확인할 수 있습니다.

target ref의 DOM을 참조하는 모습

728x90
반응형
그리드형

이 포스팅은 쿠팡파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

💖 저자에게 암호화폐로 후원하기 💖

아이콘을 클릭하면 지갑 주소가자동으로 복사됩니다