Javascript/NuxtJS

[Nuxt3] 상태 관리

kyoulho 2025. 3. 9. 21:41
728x90

정리

  1. useState()는 간단한 상태 공유에는 적합하지만, 전역 상태 관리에는 한계가 있음
  2. useRequestHeaders()는 서버에서 요청 헤더를 가져오지만, 클라이언트에서는 사용할 수 없음
  3. clearNuxtState()는 useState() 상태를 초기화하지만, 모든 상태를 지우면 성능 저하 가능
  4. 대규모 애플리케이션에서는 Pinia를 사용하여 더 체계적으로 상태를 관리하는 것이 적절함

 

useState() - 상태 공유

useState()는 Nuxt에서 상태를 저장하고 공유하는 함수입니다. Vue의 ref()와 비슷하지만, Nuxt의 전체 애플리케이션에서 SSR(서버 사이드 렌더링) 친화적으로 작동합니다.

SSR 친화적인 상태 관리

Nuxt에서 useState()는 SSR 시점에서 상태를 생성하고, 클라이언트로 하이드레이션(hydration)할 때 동일한 상태를 유지할 수 있도록 설계되었습니다.

  1. 서버 사이드에서 useState()로 정의된 상태는 useNuxtApp().payload.state에 저장됩니다.
  2. 클라이언트가 서버에서 렌더링된 페이지를 받을 때, 해당 상태가 JSON 형태로 직렬화되어 클라이언트 측에서 동일한 상태를 유지합니다.
  3. Nuxt는 페이지가 이동해도 기존 상태를 유지할 수 있도록 useState()의 키를 기반으로 관리합니다.
  4. 따라서 서버에서 생성된 상태가 클라이언트에서 사라지지 않고 유지되므로, SSR에서 상태를 지속적으로 유지하는 데 유용합니다.

사용법

const count = useState<number>('count', () => 0);
  • 첫 번째 매개변수: 상태의 고유 키 (문자열)
  • 두 번째 매개변수: 상태의 초기값을 설정하는 함수 (선택 사항)

useState()의 한계

useState()는 전역 상태 관리 라이브러리가 아닙니다. 즉, 컴포넌트 간 상태 공유는 가능하지만, 대규모 애플리케이션의 전역 상태 관리에는 적합하지 않습니다.

  • 전역적인 구조 부족: 여러 개의 상태를 체계적으로 관리하기 어려움.
  • 액션 및 뮤테이션 미지원: 상태 변경 로직이 분리되지 않아 유지보수가 어려움.
  • 비동기 상태 관리 부족: 복잡한 비동기 작업을 처리하기 어려움.
  • 클래스, 함수, 심볼 등의 직렬화 불가능: 내부적으로 JSON 직렬화를 사용하기 때문.


useRequestHeaders() - 요청 헤더 가져오기

useRequestHeaders()는 서버 사이드에서 요청 헤더에 접근하는 함수입니다. 인증 토큰이나 사용자 정보를 API 요청 시 사용할 때 유용합니다.

사용법

const headers = useRequestHeaders();
const headersWithCookie = useRequestHeaders(['cookie']);
  • 브라우저에서는 빈 객체 {}를 반환합니다.

API 요청과 함께 사용하기

const headers = useRequestHeaders(['authorization']);
const data = await $fetch('/api/protected', { headers });

클라이언트 사이드에서는 동작하지 않음

if (process.client) {
  const headers = useRequestHeaders(); // {} (빈 객체 반환)
}


clearNuxtState() - 상태 초기화

clearNuxtState()는 useState()로 생성된 모든 상태를 초기화합니다. 로그아웃 시 상태를 리셋하거나 특정 조건에서 초기 상태를 유지할 때 유용합니다.

사용법

clearNuxtState();

✅ 특정 상태만 초기화하려면 키를 지정할 수 있습니다.

clearNuxtState(['count', 'user']);

⚠️ 클라이언트에서만 동작하며 SSR 상태에는 영향을 주지 않습니다.

Pinia

Pinia는 Vue의 공식 상태 관리 라이브러리로, useState()보다 더 강력한 전역 상태 관리 기능을 제공합니다.

useState() vs Pinia

기능  useState()  Pinia
컴포넌트 간 공유
SSR 지원
구조화된 상태 관리
상태 변경 액션 지원
비동기 처리
개발자 도구 지원

설치

npm install pinia @pinia/nuxt

pinia

  • Vue의 상태 관리 라이브러리
  • Vue 3 및 Nuxt 3에서 사용할 수 있으며, 상태 저장(store) 및 공유 기능을 제공한다.
  • Nuxt 환경에서 자동으로 플러그인을 등록하지 않습니다.

@pinia/nuxt

  • Nuxt에서 Pinia를 자동으로 등록하고 최적화하는 Nuxt 전용 모듈이다.
  • nuxt.config.ts의 modules에 추가하면 자동으로 Pinia가 Nuxt 플러그인으로 등록된다.
  • SSR (서버사이드 렌더링) 환경에서도 Pinia가 올바르게 작동하도록 설정해준다.

nuxt.config.ts 설정

설치 후 nuxt.config.ts에서 modules에 @pinia/nuxt를 추가해야 합니다.

이렇게 하면 Pinia가 자동으로 Nuxt 플러그인으로 등록되므로, 별도의 createPinia() 설정 없이 사용할 수 있습니다.

export default defineNuxtConfig({
  modules: ['@pinia/nuxt'],
});

스토어 생성

//스토어 생성 (store/counter.ts)

import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    doubleCount: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++;
    },
    async fetchCount() {
      const data = await fetch('/api/count').then(res => res.json());
      this.count = data.count;
    }
  }
});
// 컴포넌트에서 사용하기
<script setup>
import { useCounterStore } from '~/store/counter';

const counter = useCounterStore();
counter.increment();
</script>

Pinia 상태를 localStorage에 저장 (Persist)

기본적으로 Pinia는 상태를 페이지를 새로고침하면 초기화합니다. 상태를 localStorage에 저장하여 유지하려면 pinia-plugin-persistedstate를 추가하면 됩니다.

pnpm install pinia-plugin-persistedstate

nuxt.config.ts에 플러그인 추가

import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
  modules: [
    "@pinia/nuxt",
    "pinia-plugin-persistedstate/nuxt",
  ],
});

store/counter.ts에서 persist 설정 추가

피니아 공식 문서: https://prazdevs.github.io/pinia-plugin-persistedstate/frameworks/nuxt.html

import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  persist: true, // 상태를 쿠키에 저장
});

 

세션스토리지나 로컬 스토리지를 사용할 경우 하이드레이션 미스 매치가 발생한다. 때문에 ClientOnly를 사용해야한다.

  persist: {
    // 로컬 스토리지 사용
    // 하이드레이션 미스 매치 발생
    storage: piniaPluginPersistedstate.localStorage(),
    // 세션 스토리지 사용
    // 하이드레이션 미스 매치 발생
    storage: piniaPluginPersistedstate.sessionStorage(),
  }
728x90

'Javascript > NuxtJS' 카테고리의 다른 글

[Nuxt3] storeToRefs()  (0) 2025.03.12
[Nuxt3] ref()와 computed() 차이점  (0) 2025.03.12
[Nuxt3] 라우트 미들웨어  (0) 2025.03.09
[Nuxt3] 에러 핸들링  (0) 2025.03.09
[Nuxt3] 플러그인  (0) 2025.03.09