- CLAUDE.md 운영 규칙 - wiki/ 정리된 지식 페이지 (Nuxt + Claude Code) - raw/ 원본 자료 - reference/ Nuxt 4.x 공식 문서 Co-authored-by: Cursor <cursoragent@cursor.com>
3.6 KiB
3.6 KiB
Nuxt 상태 관리
카테고리: 핵심 개념 최종 수정: 2026-05-13 관련: nuxt-data-fetching, nuxt-lifecycle
요약
useState는 Nuxt 내장 SSR-친화적 전역 상태다. 컴포넌트 간 key로 상태를 공유하고, 서버에서 설정한 값이 하이드레이션 후 클라이언트에서도 유지된다. 더 복잡한 상태는 Pinia 모듈을 쓴다.
useState
SSR-friendly ref 대체제. 같은 key를 쓰는 컴포넌트가 동일한 반응형 상태를 공유.
// 기본 사용
const counter = useState('counter', () => 0)
// 타입 지정
const user = useState<User | null>('user', () => null)
⚠️ 주의:
<script setup>또는setup()외부에서const state = ref()를 절대 정의하지 말 것. 서버에서 요청 간 상태가 공유되어 메모리 누수 발생.
// ❌ 잘못된 패턴 — 서버에서 요청 간 공유됨
export const myState = ref({})
// ✅ 올바른 패턴
export const useMyState = () => useState('myState', () => ({}))
비동기 초기화
앱 시작 시 서버에서 한 번 데이터를 가져와 상태를 초기화할 때 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>
callOnce는 서버에서 1회, 클라이언트 하이드레이션 시 재실행하지 않음 (Nuxt 2의 nuxtServerInit과 유사).
컴포저블로 공유 상태 패턴
타입-안전한 전역 상태를 컴포저블로 캡슐화:
// composables/states.ts
export const useColor = () => useState<string>('color', () => 'pink')
export const useUser = () => useState<User | null>('user', () => null)
<script setup lang="ts">
const color = useColor() // useState('color')와 동일
</script>
고급 패턴: SSR-친화적 로케일
// composables/locale.ts
export const useLocale = () => useState<string>('locale', () => useDefaultLocale().value)
export const useDefaultLocale = (fallback = 'en-US') => {
const locale = ref(fallback)
if (import.meta.server) {
const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0]
if (reqLocale) locale.value = reqLocale
} else if (import.meta.client) {
const navLang = navigator.language
if (navLang) locale.value = navLang
}
return locale
}
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
},
},
})
<!-- app/app.vue -->
<script setup lang="ts">
const website = useWebsiteStore()
await callOnce(website.fetch) // 서버에서 1회 실행
</script>
useState vs Pinia 선택 기준
useState |
Pinia | |
|---|---|---|
| 복잡도 | 단순 | 복잡한 상태·액션 |
| 타입 안전성 | 기본 | 풍부한 타입 지원 |
| DevTools | ❌ | ✅ (Vue DevTools 통합) |
| 설치 | 내장 | 모듈 설치 필요 |
| 사용 시점 | 간단한 공유 상태 | 스토어 패턴 필요 시 |
상태 유틸
| 유틸 | 용도 |
|---|---|
clearNuxtState(key?) |
특정 key 또는 전체 상태 초기화 |
참고 / 출처
reference/1.getting-started/11.state-management.md