Files
gil-wiki/wiki/nuxt-lifecycle.md
gil 5f664546cf feat: 위키 저장소 초기 커밋
- CLAUDE.md 운영 규칙
- wiki/ 정리된 지식 페이지 (Nuxt + Claude Code)
- raw/ 원본 자료
- reference/ Nuxt 4.x 공식 문서

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 00:31:51 +09:00

4.3 KiB

Nuxt 라이프사이클

카테고리: 핵심 개념 최종 수정: 2026-05-13 관련: nuxt-rendering-modes, nuxt-auto-imports, nuxt-data-fetching

요약

Nuxt 앱은 서버에서 시작해 클라이언트로 이어지는 두 단계 라이프사이클을 갖는다. 어느 코드가 어디서 실행되는지 이해하는 것이 SSR 버그 예방의 핵심이다.


서버 라이프사이클

초기 요청마다 아래 순서로 실행됨.

1. Nitro 서버 플러그인 (서버 시작 시 1회)
2. 서버 미들웨어 (모든 요청마다)
3. 앱 플러그인 (Vue·Nuxt 인스턴스 생성 후)
4. 라우트 검증 (validate)
5. 앱 미들웨어 (global → named → inline)
6. 페이지·컴포넌트 렌더링 + 데이터 패칭
7. HTML 출력

1. Nitro 서버 플러그인 (server/plugins/)

서버 시작 시 1회 실행. 요청마다 실행되지 않음.

  • 앱 전역 에러 캡처
  • Nitro 종료 시 훅 등록
  • 요청 라이프사이클 훅 등록 (응답 수정 등)

⚠️ 주의: 서버리스 환경에서는 매 요청마다 서버가 재부팅되므로 플러그인도 매번 실행됨 (단, awaited되지 않음).

2. 서버 미들웨어 (server/middleware/)

모든 요청에 대해 실행. 인증, 로깅, 요청 변환 등.

⚠️ 주의: 미들웨어에서 값을 반환하면 요청이 종료되고 그 값이 응답으로 전송됨. 의도적인 경우에만 사용할 것.

3. 앱 플러그인 (app/plugins/)

Vue·Nuxt 인스턴스 생성 후 실행. 순서:

  1. 내장 플러그인 (Vue Router, unhead)
  2. 커스텀 플러그인 (suffix 없는 것, .server suffix)

훅: app:created

4. 라우트 검증 (Route Validation)

definePageMetavalidate 메서드 실행.

definePageMeta({
  validate(route) {
    return typeof route.params.id === 'string' && /^\d+$/.test(route.params.id)
    // false 반환 → 404, { status: 403, statusText: 'Forbidden' } 반환 → 커스텀 에러
  },
})

5. 앱 미들웨어

실행 순서: global → named → inline(anonymous)

서버에서 리다이렉트 발생 시 Location: 헤더 전송 → 브라우저가 새 URL로 재요청 → 모든 앱 상태 초기화 (쿠키로 저장한 것 제외).

6. 페이지·컴포넌트 렌더링

useFetch, useAsyncData로 데이터 패칭. DOM 조작 없으므로 onBeforeMount, onMountedVue 라이프사이클 훅은 SSR에서 실행되지 않음.

⚠️ 주의: <script setup> 루트 스코프에 사이드 이펙트(setInterval 등) 넣지 말 것. 언마운트 훅이 서버에서 호출되지 않아 영구적으로 남음. onMounted 안에 넣어야 함.

훅: app:rendered (Vue 렌더링 완료 후), render:html (Nitro가 HTML 최종 처리 전)


클라이언트 라이프사이클

브라우저에서 완전히 실행됨.

1. 앱 플러그인 (suffix 없는 것, .client suffix)
2. 라우트 검증
3. 앱 미들웨어
4. Vue 앱 마운트 + Hydration
5. Vue 라이프사이클 (onMounted 등) 실행
6. 이후 클라이언트 사이드 내비게이션

Hydration

app.mount('#__nuxt') 호출 시 Vue가 서버에서 받은 HTML과 클라이언트의 컴포넌트를 매칭해 이벤트 리스너를 연결.

hydration 오류 방지:

  • 데이터 패칭에 useAsyncData, useFetch 사용 (서버 데이터 재사용)
  • localStorage, window 등 브라우저 전용 API는 onMounted 안에서만 사용
  • import.meta.server, import.meta.client로 환경 분기
// 환경 분기 패턴
if (import.meta.server) {
  // 서버에서만 실행
}
if (import.meta.client) {
  // 클라이언트에서만 실행
}

훅: app:beforeMount (마운트 전), app:mounted (마운트 후)


주요 런타임 훅 요약

실행 시점 환경
app:created Vue·Nuxt 인스턴스 생성 후 서버·클라이언트
app:beforeMount Vue 앱 마운트 전 클라이언트
app:mounted Vue 앱 마운트 후 클라이언트
app:rendered Vue 렌더링 완료 서버
render:html HTML 최종 생성 전 서버 (Nitro)
page:start 페이지 전환 시작 클라이언트
page:finish 페이지 전환 완료 클라이언트

참고 / 출처

  • reference/3.guide/1.concepts/2.nuxt-lifecycle.md