Skip to content

Store 설계 규칙

13.2.1. Store 분할 기준

Store는 도메인 단위로 분할합니다. 하나의 Store는 하나의 도메인만 담당해야 합니다.

  • 1 Store = 1 도메인 원칙을 준수합니다.
  • 도메인은 비즈니스 엔티티 또는 기능 영역 기준으로 정의합니다.
  • 하나의 Store가 복수 도메인을 관리하는 것은 금지합니다.
Store담당 도메인포함 상태 예시
useUserStore사용자 인증/프로필로그인 상태, 사용자 정보, 토큰
useProductStore상품상품 목록, 상품 상세, 카테고리
useCartStore장바구니장바구니 항목, 수량, 합계
useNotificationStore알림알림 목록, 읽음 상태
useThemeStore테마/UI 설정다크모드, 언어, 레이아웃

13.2.2. 글로벌 vs 로컬 상태 판단

모든 상태를 Store에 배치하지 않습니다. 다음 판단 기준에 따라 관리 방식을 결정해야 합니다.

판단 기준관리 방식예시
여러 컴포넌트가 공유하는 상태Pinia Store인증 정보, 테마 설정, 권한
단일 컴포넌트에서만 사용하는 상태컴포넌트 로컬 ref폼 입력값, 모달 표시 여부, 토글
서버에서 가져오는 비동기 데이터Composable (useFetch 등)API 응답 데이터, 페이지네이션
여러 페이지에 걸친 임시 상태Pinia Store다단계 폼 위저드의 진행 데이터
URL로 표현 가능한 상태Router (query/params)검색 필터, 정렬 조건, 페이지 번호
  • 판단이 모호한 경우 로컬 상태로 시작하고, 공유 필요성이 확인된 시점에 Store로 승격합니다.

13.2.3. Store 간 의존성

Store 간 의존이 필요한 경우 action 내부에서 다른 Store를 호출합니다.

  • Store 최상위 스코프에서 다른 Store를 호출하지 않습니다.
  • 순환 의존은 금지합니다. A -> B -> A 형태의 참조가 발생하면 공통 Store를 분리합니다.
  • 의존 방향은 상위 도메인에서 하위 도메인으로 단방향을 유지합니다.
typescript
// src/stores/useCartStore.ts
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
import { useUserStore } from './useUserStore'
import type { CartItem } from '@/types/cart'

export const useCartStore = defineStore('cart', () => {
  const items = ref<CartItem[]>([])

  const totalPrice = computed(() =>
    items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
  )

  // action 내부에서 다른 Store를 호출합니다.
  async function checkout() {
    const userStore = useUserStore()

    if (!userStore.isLoggedIn) {
      throw new Error('로그인이 필요합니다.')
    }

    await submitOrder(items.value, userStore.user!.id)
    items.value = []
  }

  return { items, totalPrice, checkout }
})
  • useUserStore()checkout() action 내부에서 호출하는 것이 올바른 패턴입니다.
  • Store 정의 최상위에서 const userStore = useUserStore()를 선언하는 것은 금지합니다.

13.2.4. Store 네이밍

Store의 네이밍은 다음 규칙을 따릅니다.

  • 함수명: use{Domain}Store 패턴을 사용합니다. (예: useAuthStore, useProductStore)
  • defineStore ID: 도메인명을 소문자 케밥 표기로 사용합니다.
  • 파일명: 함수명과 동일하게 use{Domain}Store.ts로 작성합니다.
함수명defineStore ID파일명
useAuthStore'auth'useAuthStore.ts
useProductStore'product'useProductStore.ts
useOrderHistoryStore'order-history'useOrderHistoryStore.ts
typescript
// 파일명: src/stores/useAuthStore.ts
// defineStore ID: 'auth'
// 함수명: useAuthStore

export const useAuthStore = defineStore('auth', () => {
  // ...
})
  • ID는 앱 전체에서 고유해야 합니다. 중복 ID는 런타임 오류를 발생시킵니다.
  • 복합 도메인의 ID는 케밥 케이스를 사용합니다. (예: 'order-history', 'user-preference')

TIENIPIA QUALIFIED STANDARD