상태 관리
상태 관리 (State Management)
SSR 환경에서 상태를 다루는 건 까다로워요. 클라이언트에서 만든 ref 값이 서버 렌더링 과정에서 사라지거나, 반대로 서버와 클라이언트가 각각 다른 값을 갖게 되기 쉽거든요. Nuxt는 useState 컴포저블로 반응형이면서 SSR 친화적인 공유 상태를 만들게 해 줘요.
출처: 공식문서
본문
useState는 SSR 친화적인 ref 대체재예요. 서버 렌더링을 거친 뒤에도 값이 보존되고(클라이언트 하이드레이션 중), 같은 key를 쓰는 모든 컴포넌트에서 값이 공유돼요.
useState 안의 데이터는 JSON으로 직렬화되기 때문에, 클래스·함수·심볼처럼 직렬화할 수 없는 것들이 들어가지 않게 주의해야 해요.
Best Practices
<script setup>이나 setup() 함수 밖에서 const state = ref()를 정의하지 마세요. 예를 들어 export myState = ref({})처럼 쓰면 서버에서 요청 간 상태가 공유되어 메모리 누수로 이어질 수 있어요. 대신 const useX = () => useState('x') 형태로 쓰는 게 좋아요.
예시
기본 사용법
컴포넌트 로컬 카운터 상태를 쓰는 예시예요. 어느 컴포넌트든 useState('counter')를 쓰면 같은 반응형 상태를 공유해요.
<!-- app/app.vue -->
<script setup lang="ts">
const counter = useState('counter', () => Math.round(Math.random() * 1000))
</script>
<template>
<div>
Counter: {{ counter }}
<button @click="counter++">
+
</button>
<button @click="counter--">
-
</button>
</div>
</template>
캐시된 상태를 전역으로 무효화하려면 clearNuxtState 유틸을 쓰면 돼요.
초기화하기
대부분 상태를 비동기로 해석되는 데이터로 초기화하고 싶을 거예요. 그럴 땐 app.vue 컴포넌트와 callOnce 유틸을 조합해요.
<!-- app/app.vue -->
<script setup lang="ts">
const websiteConfig = useState('config')
await callOnce(async () => {
websiteConfig.value = await $fetch('https://my-cms.com/api/website-config')
})
</script>
이건 Nuxt 2의 nuxtServerInit 액션과 비슷한 역할을 해요. 페이지를 렌더링하기 전에 서버 쪽에서 스토어의 초기 상태를 채워두는 거죠.
Pinia와 함께 쓰기
전역 스토어를 만들어 앱 전체에서 쓰고 싶다면 Pinia 모듈을 활용해요. npx nuxt module add pinia로 모듈을 설치한 뒤 사용하면 돼요.
// app/stores/website.ts
export const useWebsiteStore = defineStore('websiteStore', {
state: () => ({
name: '',
description: '',
}),
actions: {
async fetch () {
const infos = await $fetch('https://api.nuxt.com/modules/pinia')
this.name = infos.name
this.description = infos.description
},
},
})
공유 상태
자동 임포트되는 컴포저블을 활용하면 전역 타입 안전 상태를 정의하고 앱 어디서든 불러와 쓸 수 있어요.
// composables/states.ts
export const useColor = () => useState<string>('color', () => 'pink')
<!-- app/app.vue -->
<script setup lang="ts">
const color = useColor() // useState('color') 와 동일
</script>
<template>
<p>Current color: {{ color }}</p>
</template>
서드파티 라이브러리
Nuxt는 예전에 전역 상태 관리를 위해 Vuex에 의존했었어요. Nuxt 2에서 올라오는 중이라면 마이그레이션 가이드를 참고하세요. Nuxt는 상태 관리에 대해 특정 방식을 강요하지 않아서, 필요에 맞는 해결책을 고르면 돼요. 대표적인 통합은 다음과 같아요.
- Pinia — Vue 공식 권장
- Harlem — 불변(immutable) 전역 상태 관리
- XState — 상태 로직 시각화·테스트 도구와 함께 쓰는 상태 머신 방식
더 알아보기
useState,callOnce,clearNuxtState각각의 세부 옵션은 API 문서를 참고하세요- Nuxt에서 전역 상태와 SSR을 다루는 더 깊은 내용은 Examples > State Management에서 다뤄요