Nuxt 라이프사이클

Nuxt Lifecycle

Nuxt.js

Vue.js를 사용해 웹 어플리케이션 개발할때 라이프사이클에 대한 공부를 제대로 시작하지 고생한 경험이 있는데 Nuxt는 그런 과정을 밟지 않기위해 라이프사이클부터 차근차근 공부해보자. 일단 공식문서 번역과 아래 Nuxt Lifecycle HOOKS 이미지에 대한 내용에 대해 공부해보자.

Nuxt Lifecycle

Nuxt Lifecycle

여러분이 어떤 도구(tool)를 사용하든 그 도구의 서두(the hood)에 대해 잘 이해하고 있을때 더 자신있음을 느낄 것입니다. Nuxt.js도 해당됩니다. 이 챕터에서는 여러분에게 프레임워크의 실행순서와 어떻게 함께 작동하는지 서로 다른 부분에 대한 수준 높은 개요를 제공할 것입니다.

Nuxt.js 라이프사이클은 빌드 단계 이후에 무엇이 발생되는지, 여러분의 어플리케이션이 어디서 번들되고(bundled), 청크되고(chunked), 최소화(minified) 되는지 설명합니다. 이 단계 이후에 발생하는 것은 여러분이 서버사이드 렌더링(server-side rendering) 활성화 여부에 따라 다릅니다. 만약 여러분이 서버사이드 렌더링 사용한다면, 추가적으로 여러분이 선택한 서버사이드 렌더링의 유형에 따라 달라집니다.

Dynamic SSR (nuxt start) 또는 Static Site Generation (nuxt generate).

Lifecycle

Server

SSR을 위해서 아래의 단계가 여러분의 어플리케이션에서 모든 초기요청(request) 동안에 실행될 것입니다.

  • 서버 시작 The server starts (nuxt start)

정적 사이트 생성모드를 사용하면, 서버 단계에서는 오직 빌드타임에만 실행되나 모든 페이지에 대해 단 한번만 실행될 것입니다.

  • 생성 프로세스 시작 (nuxt generate)
  • Nuxt hooks
  • serverMiddleware
  • Server-side Nuxt 플러그인(plugins)
    • nuxt.config.js에 정의된 순서대로 (in order as defined in nuxt.config.js)
  • nuxtServerInit
    • 만약 Vuex store를 설정했다면 서버 사이드에서 요청되는 첫번째 생명주기 훅(lifecycle hook)이다
    • 스토어(store)를 미리 채우기(pre-populate) 위해 서버 사이드에서 Vuex 호출한다.
    • 첫번째 인자(argument)는 Vuex context, 두번째 인자는 Nuxt.js context 입니다.
      • 서버 사이드에서 연속적인 스토어 액션(action)을 위해 오직 “entry point”에서 다른 액션을 Dispatch 합니다.
    • 오직 store/index.js에 정의할 수 있습니다.
  • 미들웨어 (Middleware 또는 Route Middleware)
    • 페이지 컴포넌트가 렌더링되기 전에 호출됩니다.
    • 조건을 설정하거나 체크할수도 있으며 페이지를 리다이렉트(redirect)하는데 사용할 수 있습니다.
    • 전역 미들웨어(Global middleware) - 모든 라우트에 영향을 끼치며, route.config.js에 정의합니다.
    • 레이아웃 미들웨어(Layout middleware) - 라우트 그룹에 영향을 끼치며, layout에 정의합니다.
    • 페이지 미들웨어(Page middleware) - 싱글 라우트에 영향을 끼치며, page component에 정의합니다.
  • validate
    • 동적 라우트 파라미터(dynamic route parameter)를 검증하는데 유용합니다.
    • 페이지 컴포넌트가 렌더링 되기 전에 호출됩니다.
  • asyncData
    • 페이지 컴포넌트가 로딩되기 전에 매번 호출됩니다.
    • 컴포넌트 data 프로퍼티와 병합(merge)됩니다.
  • beforeCreate (Vue 라이크사이클 메서드)
    • Vue 인스턴트(instance)가 초기화(initialized) 될때 호출됩니다.
  • created (Vue 라이크사이클 메서드)
  • The new fetch (top to bottom, siblings = parallel)
  • 상태의 일렬화(Serialization of state) (render:routeContext Nuxt.js hook)
  • HTML을 렌더링 할때 일어난다. (render:route Nuxt.js hook)
  • render:routeDone 훅: HTML 파일을 브라우저로 보낼때 일어난다.
  • generate:before Nuxt.js hook
  • HTML 파일들을 생성한다.
    • Full static generation
      • e.g. 정적 페이로드(static payloads)를 추출한다.
  • generate:page (HTML 편집가능(editable))
  • generate:routeCreated (Route가 생성된다.)
  • generate:done 훅: 모든 HTML 파일들이 생성될때 일어난다.

Client

여러분이 Nuxt.js의 어떤 모드를 선택하든, 이 부분은 라이프사이클 중에 완전히 브라우저에서 실행된다.

  • HTML 파일을 받는다(Receives).
  • assets 로딩하기 (e.g. JavaScript)
  • Vue Hydration
  • 미들웨어 (Middleware 또는 Route Middleware)
    • 페이지 컴포넌트가 렌더링되기 전에 호출됩니다.
    • 조건을 설정하거나 체크할수도 있으며 페이지를 리다이렉트(redirect)하는데 사용할 수 있습니다.
    • 전역 미들웨어(Global middleware) - 모든 라우트에 영향을 끼치며, route.config.js에 정의합니다.
    • 레이아웃 미들웨어(Layout middleware) - 라우트 그룹에 영향을 끼치며, layout에 정의합니다.
    • 페이지 미들웨어(Page middleware) - 싱글 라우트에 영향을 끼치며, page component에 정의합니다.
  • 클라이언트 사이드(client-side) Nuxt.js 플러그인
    • nuxt.config.js에 정의된 순서대로 (in order as defined in nuxt.config.js)
  • asyncData (비동기, blocking)
    • 페이지 컴포넌트가 로딩되기 전에 매번 호출됩니다.
    • 컴포넌트 data 프로퍼티와 병합(merge)됩니다.
  • beforeCreate (Vue 라이크사이클 메서드)
    • Vue 인스턴트(instance)가 초기화(initialized) 될때 호출됩니다.
  • created (Vue 라이크사이클 메서드)
  • The new fetch (top to bottom, siblings = parallel) (동기, non-blocking)
  • beforeMount (Vue 라이크사이클 메서드)
  • mounted (Vue 라이크사이클 메서드)

클라이언트 사이드 부분과 동일하게 브라우저에서 모든것이 발생하지만 오직 <NuxtLink>를 통해 네비게이팅 될때만 발생합니다.

<NuxtLink> 에 대한 더 자세한 정보는 컴포넌트 챕터에서 확인하세요

  • middleware (비동기, blocking)
  • 전역 미들웨어(Global middleware)
  • 레이아웃 미들웨어(Layout middleware)
  • 라우트 미들웨어(Route middleware)
  • asyncData (비동기, blocking)
  • asyncData (비동기, blocking) [또는 완전히 정적 페이로드(static payload)가 로딩된 후]
  • beforeCreate & created (Vue 라이크사이클 메서드)
  • fetch (동기, non-blocking)
  • beforeMount & mounted

중간 정리

Nuxt의 라이프사이클은 전체적으로 서버와 클라이언트 사이드 부분으로 나뉘는 것을 알 수 있으며 각 부분에서 공통으로 실행되는 과정과 아닌 과정이 있음을 확인할 수 있었습니다. 또한, 정적 (Static) 어플리케이션를 만드느냐 SSR(Server-Side Rendering) 또는 유니버설(universal) 어플리케이션을 만드느냐에 따라 과정이 달라질 수 있다.

추가 공부

라이프사이클에 대해 공부 및 정리하면서 봤던 내용들에 대해 정리해보자.

1. 활용도가 높고 중요한 몇가지 훅

  • middleware(클라이언트, 서버)
    • 클라이언트와 서버 모두 훅들이 본격적으로 호출되기 전에, 앱을 만드는 과정에서 미리 정의해놓은 미들웨어들이 먼저 동작합니다.
    • 만약 serverMiddlware을 정의했다면 서버 사이드에서만 렌더링 과정에서 일반 미들웨어가 동작하기 전에 먼저 동작합니다.
  • asyncData(서버 or 클라이언트)
    • 서버 혹은 클라이언트 사이드에서 생명주기 통틀어 한번씩만 호출되는 훅입니다.
    • Vue 인스턴스의 생명주기 이전에 먼저 데이터를 가져와서 렌더링을 하고싶은 경우에 사용합니다.
    • 컴포넌트를 로드하기 전에 항상 호출되며, 페이지 컴포넌트의 경우에만 사용할 수 있습니다.
    • asyncData 의 리턴값은 Vue 인스턴스의 data()와 병합됩니다.
  • beforeCreated, created(클라이언트, 서버)
    • 서버에서 새로운 vue 인스턴스를 생성한 뒤 이를 프리랜더링 하기 때문에 Vue 인스턴스가 서버에서 만들어지는 시점에 created와 beforeCreated 훅이 호출됩니다.
    • 또한 클라이언트에서도 인스턴스를 만들고 $mount 메소드가 호출될 때도 따라 호출됩니다.
    • 즉 서버와 클라이언트 사이드 양쪽에서 호출되는 훅입니다.
  • beforeMount 이후의 훅(클라이언트)
    • 클라이언트 사이드에서만, 하이드레이션 이후에 $mount 메소드가 호출될 때 나머지 Vue 생명주기 훅들이 실행됩니다.

출처: 참조 1

2. Nuxt.js 비동기 데이터

Nuxt.js에는 비동기데이터 가져 오기를 위해 설계된 3가지 후크가 있다.

  • nuxtServerInit : 모든 페이지에 호출되는 VueX 저장소를 미리 채우는 데 사용됩니다.
  • fetch : 페이지 내에서 호출 된 데이터로 VueX 저장소를 미리 채우는 데 사용됩니다.
  • asyncData : data 페이지의 객체와 동기 데이터를 병합하는데 사용된다. 비동기 방식으로 미들웨어를 사용할 수도 있습니다. 즉, 미들웨어를 사용하여 VueX 저장소를 채울 수 있습니다.

Nust-SSR

asyncData 메소드

서버사이드에서 데이터를 가져와서 렌더링하고 싶을 때, 이때 pages 컴포넌트를 로딩하기 전에 매번 호출되는 asyncData를 사용하면 된다.

  • pages 컴포넌트에서만 지원됩니다.
  • 서버사이드에서 호출되거나 페이지를 이동할 때 호출
  • 컴포넌트가 렌더링 되기 전에 호출
  • context 인자 사용가능
  • nuxt.js가 컴포넌트와 데이터를 자동으로 Merge하는 개념

!! asyncData 안에서 컴포넌트가 생성되기 전에 호출하기 때문에 this를 엑세스할 수 없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
export default {
data () {
return {
title: ''
}
}
asyncData ({ params }) {
return axios.get(`http://localhost:8080/test/1`)
.then((res) => {
// 여기서 this는 컴포넌트 생성 전이기에 'undefined'
return this.title = res.data
})
}
}
</script>

출처: 참조 2

3. asyncData()와 fetch()

  • 두 개의 Hook은 매우 비슷해보이면서 목적은 다름

    • 공통점: 컴포넌트가 로딩되기 전에 매번 호출된다는 점, 첫번째 인자로 컨텍스트 오브젝트를 받음
  • asyncData

    • 페이지가 로딩되기전에 컴포넌트 data를 미리 지정하여 컴포넌트가 생성될 때 병합하는데에 목적
    • 즉 필요한 컴포넌트의 data를 컴포넌트가 랜더링 되기 전에 미리 지정하여 보다 빠르게 구성한다는 데에 목적을 둠
  • fetch

    • 주로 비동기 작업을 작성하게 되면, 컴포넌트가 랜더링 되기전에 이 작업을 기다리게 됨
    • 예를들어 유저정보가 필요한 컴포넌트라면 fetch 부분에 유저정보를 가져오는 API를 호출하여 활용할 수 있음
  • 요약하자면,

    • asyncData는 컴포넌트가 랜더링 되기전에 컴포넌트 데이터를 구성하는데에 목적이 있고,
    • fetch는 컴포넌트가 랜더링 되기전에 비동기로직을 호출하는데에 목적이 있다고 생각합니다!

출처: 참조 4

4. 잘 정리된 Nuxt Lifecucle Hooks

Nuxt Lifecucle Hooks

출처: 참조 5


참조