Vue의 라이프 사이클 (React와는 다른 맛!)

HyunHo Lee·2022년 11월 6일
1

프론트

목록 보기
44/57
post-thumbnail

Vue 라이프 사이클?

새로운 라이브러리나 프레임워크를 학습하는 방법은 사람마다 다르다. 나는 React에 대한 공부를 막 시작했을 때, 인터넷 강의를 보면서 사용법을 익혔다.

그리고 자신이 보유한 배경 지식에 따라서도 학습 방법은 달라진다. 나는 Vue를 처음 공부할 때, 처음 React를 공부할 때와는 다르게 인터넷 강의를 봐야겠다는 생각은 하지 않았다. 공식문서를 읽으며 직접 이것저것 만들어보는게 Best라는 것을 알고있기 때문이다. Vue를 사용하기로 결정하면서 가장 먼저 들었던 생각은 "React는 라이프 사이클이 있어 참 편했는데 당연히 Vue에도 있겠지?" 이었다. 당연하게 Vue의 라이프 사이클도 존재했고, 이 외의 기능들을 하나하나 찾아보니 역시 React나 Vue는 프론트엔드 개발자에게 도구일 뿐이라는 사실을 다시 한 번 깨달았다. (JS와 TS 공부를 열심히 하자..!)

어쨋든!! 새로운 스킬에 라이프 사이클이 존재한다면, 모두 꼼꼼하게 살펴보는 것을 추천한다. 그래야 상황에 맞는 라이프 사이클 훅을 사용하여 버그를 방지하거나 효율적인 선택을 할 수 있기 때문이다.


공식 문서를 항상 확인하자

vue.js 공식 문서를 보면 그림으로 한 번에 정리를 해주고 있다. 사실 너무 잘 나와있어서 설명할게 없지만 우리는 개발자답게 코드로 알아보자. 라이프 사이클에 관련된 훅들을 살펴보면서 이 그림과 비교해보면 이해가 더 수월할 것이다.

tip) React의 라이프 사이클을 공부해보면 class 형을 가장 먼저 보게 될 것이다. 그리고 훅(useEffect)을 이용해서 대체할 수 있고, React 생태계에서는 훅 기반을 많이 사용하고 있다. 이런 것처럼 vue도 최신 문법에서는 라이프 사이클 훅의 네이밍이 조금 다르다는 것을 인지하자.


기본 틀

<template>
  <div class="life-cycle">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  data(){
    return{
      msg: "A"
    }
  },
  // 라이프 사이클 훅들을 추가할 예정...
}
</script>

vue 컴포넌트의 가장 기본적인 틀을 이용해서 라이프 사이클을 알아볼 것이다.

UI에는 현재 A가 출력되고 있다.


beforeCreate

  beforeCreate() {
    console.log("beforeCreate");
    this.msg = "B";
  },

beforeCreate는 vue 인스턴스가 초기화 되고, 가장 먼저 실행되는 훅이다. 아직은 data나 methods 속성이 인스턴스에 저장되어 있지 않으므로 여기서는 접근할 수 없다. this.msg = "B"data로 선언한 state를 변경하는 코드를 작성했다.

UI를 확인해보면 그대로 A가 출력되는 것을 볼 수 있다. 콘솔을 확인해보면 beforeCreate가 출력되고, 에러가 발생하지는 않았다. 즉, 그냥 msg state에 접근이 안된 것이다.


created

  beforeCreate() {
    // ...
  },
  created() {
    console.log("created");
    this.msg = "B";
  },

라이프 사이클 훅들을 설명하면서 위와 같이 훅들을 쭉 붙여 나갈 것이다. 이번에는created훅을 알아보자. 여기 부터는 data의 변화에 따라 대응할 수 있게 반응형으로 추적할 수 있게 된다. 그리고 methods, computed, watch 등에 접근할 수 있다.

msg state를 변경할 수 있어 UI는 B를 출력하게 된다. 아직 인스턴스가 화면에 부착되기 전 이므로 template속성에 정의된 DOM Element로는 접근할 수 없다. 보통 API Endpoint에서 데이터를 받아 state에 초기화하는 경우나 이벤트 리스너를 등록할 때 많이 사용하는 라이프 사이클 훅이다.


beforeMount

  beforeMount() {
    console.log("beforeMount");
    this.msg = "B";
  },

render()함수가 호출되기 직전(DOM에 인스턴스가 부착하기 직전)에 추가하고 싶은 로직이 있다면 이 훅에서 작성하면 된다. (Virtual DOM이 생성되어 있지만 실제 DOM에 부착하지 않은 상태)

사실 비동기로 데이터를 요청하는 부분은 beforeCreate, created, beforeMount에서 가능하다. 어치피 mounted 이후에 실제 비동기 요청이 처리되기 때문이다. 하지만 대부분의 글을 보면 created에서 비동기 요청 로직을 작성한다. 그 이유는 웹 프로젝트의 특성때문이라고 생각한다. 데이터를 요청하고, 그 값을 state에 초기화 하는 경우에 created를 사용한다고 했다. 이에 반해 beforeMount에서 데이터 요청을 하는 경우는 데이터를 직접 주입하는 상황이다. 웹 프로젝트를 설계하다보면 state에 초기화하는 경우가 매우 많아서 created에 대한 글이 압도적으로 많은 것 같다. 실제로 각각의 상황에 맞게 알맞은 훅을 사용했을 때 효율이 가장 좋다고 한다.

이 외에 beforeMount 훅을 잘 사용하는 예제를 제시하는 Stackoverflow 글이 있도 있다.


mounted

  mounted() {
    console.log("mounted");
    this.msg = "B";
  },

인스턴스가 mount된 후. 즉, 가상 DOM의 내용이 실제 DOM에 부착된 후에 실행된다. this.$el부터 data, methods 등에 접근 가능 하다.

beforeMount에서도 this.$el에 접근이 가능하긴 하지만 여기서의 this.$el과 조금 다르다. (위에서 첨부했던 Stackoverflow)

그림 출처 : 지그재그 블로그

부모 컴포넌트와 자식 컴포넌드가 있는 경우, 부모가 created되고 자식이 created부터 mounted되어야 부모가 mounted가 된다.

mounted() {
  this.$nextTick(function() {
    // 모든 화면이 렌더링된 후 실행
  })
}

하지만 자식 컴포넌트가 서버에서 비동기도 데이터를 받아오는 경우에 부모의 mounted훅이 모든 자식 컴포넌트가 마운트트된 상태를 보장하지 않는다. 이 경우에는 this.$nextTick을 이용해서 처리할 수 있다.

또, 이 훅에서는 재밌는 사실이 있다. this.msg = "B"는 data를 변경하여 DOM에도 그 변화를 적용하고 있다. mounted훅에서 이 코드를 넣으면 update에 연관된 훅을 호출할 수 있다. 바로 알아보자.


beforeUpdate

  beforeUpdate() {
    this.msg = "C";
    console.log("beforeUpdate");
  },

updated훅을 실행하기 전에 beforeUpdate를 수행한다. 컴포넌트에서 사용하는 데이터의 변경이 감지되면, 변화 직전에 호출되는 것이다. 실제로 mounted 이전의 훅에서 msg를 변경하는 코드를 작성하면 UI에는 B가 출력되지만, beforeUpdate훅이 호출되지는 않는다.

또한, 여기서에서는 변경되는 값에 대해 추가적으로 다시 변화시켜도 update관련 라이프 사이클훅을 호출하지 않는다. msg 값을 mounted에서 B로 변경시켜서 beforeUpdate훅이 호출되었다. 그리고 여기서 다시 msg값을 C로 변경시켜 UI는 C가 출력되었다. 그리고 콘솔에서는 beforeUpdate가 한 번 출력되었으므로 재호출 하지 않았다는 것을 알 수 있다.


updated

  updated() {
    console.log("updated");
  },

변경된 데이터가 적용된 가상 DOM을 실제 DOM에 적용된 이후에 호출되는 훅이다. 여기서 데이터를 변경하면 무한 루프가 발생할 수 있으므로 해당 로직이 필요한 경우에는 computedwatch를 이용하자.(왠만하면 그냥 beforeUpdate에서 처리) 그리고 mounted와 마찬가지로 모든 화면이 update된 후를 보장받으려면 this.$nextTick를 사용할 수 있다.


beforeDestroy

  beforeDestroy() {
    console.log("beforeDestroy");
  },

인스턴스가 해체되기 직전에 호출된다. 아직은 모든 요소에 접근 가능하다. 이벤트 리스너 해제 등의 작업을 해주면 된다. (메모리를 위해..!)

codepen에 예시도 있으니 확인해보자. isDelete 값이 false가 되면, 조건부 렌더링이 해제되고 beforeDestroy가 호출 된다.


destroyed

  destroyed() {
    console.log("destroyed");
  },
};

vue 인스턴스가 해체되고 난 이후에 호출된다.


이 외의 라이프 사이클 훅들

우리는 공식 문서 그림에 나와있는 라이프 사이클 훅들에 대해 알아보았다. 하지만 이 외에도 조금 더 있다. 실제로 React도 라이프 사이클에 대해 자세히 보면 많은 훅들이 있는것을 알 수 있다. Vue도 그런 것이다. 공식 문서를 확인해보면 activated, deactivated, beforeUnmount, unmounted, errorCaptured, renderTracked, renderTriggered 라는 훅들이 있다. 이 훅들에 대해서도 알아두어야 찰떡인 상황이 오면 사용할 수 있다. 다음 글에서 알아보자!

profile
함께 일하고 싶은 개발자가 되기 위해 달려나가고 있습니다.

0개의 댓글