# 깔끔한 Pinia 스토어 구조: 검증된 모범 사례
대규모 Vue 프로젝트에서 Pinia 스토어는 종종 거대해져 유지보수가 악몽이 됩니다. 탄탄한 구조가 이를 해결합니다: 액션만을 통한 상태 변경, 설정 문법, 그리고 스토어 내부의 부수 효과 금지. 이렇게 하면 중고급 개발자들에게 예측 가능하고 테스트하기 쉬운 코드를 유지할 수 있습니다.
상태 변경은 액션으로만
컴포넌트에서 직접 상태를 변경하면 책임이 모호해집니다. 문제가 되는 코드 예시:
const docStore = useDocumentStore()
const { client } = storeToRefs(docStore)
client.value = null // 여기저기 흩어진 변경 로직
시간이 지나면서 디버깅이 불가능해집니다. 변경이 컴포넌트 곳곳에 퍼지기 때문입니다. 해결책? 중앙화된 액션:
export const useDocumentStore = defineStore('documents', () => {
const client = ref(null)
const resetClient = () => { client.value = null }
return { client, resetClient }
})
// 컴포넌트에서
docStore.resetClient()
단일 진입점을 통해 검증, 로깅, 분석 등을 쉽게 추가할 수 있고, 코드 곳곳을 건드릴 필요가 없습니다.
옵션 API 대신 설정 스토어
옵션 API는 스토어에서 구식입니다. 설정 스타일(defineStore(() => { ... }))이 제공하는 이점:
this없이 투명한 반응성.- 더 쉬운 테스트.
- 컴포저블과 완벽 통합.
보일러플레이트가 적고, 컴포넌트처럼 자연스러운 반응성. 새 스토어는 무조건 설정 스타일로 전환하세요—차이를 바로 느낄 겁니다.
스토어 안의 감시자 버리기
스토어 내부 감시자는 상태 변경 시 숨겨진 부수 효과를 일으켜 디버깅을 복잡하게 만듭니다. 스토어는 데이터만 보관해야 하며, 이벤트 디스패치는 하지 말아야 합니다.
감시자 대신 컴포넌트나 컴포저블에서 명시적 호출로 대체하세요. 라우트 변경, URL 파싱, 외부 이벤트는 외부에서 처리하고, 준비된 데이터를 액션으로 전달합니다.
플러그인을 통한 영속성
localStorage 동기화는 비즈니스 로직과 섞지 마세요. pinia-plugin-persistedstate나 커스텀 테스트 래퍼를 사용하세요.
액션 안에서 직접 localStorage.setItem은 스토어 순수성을 깨고 리팩토링을 어렵게 만듭니다.
순수 데이터 홀더로서의 스토어
스토어는 데이터 읽기, 저장, 업데이트만 담당합니다. 아래는 빼세요:
- 라우터 구독.
- 토큰 파싱.
- WebSocket 로직.
- 스토어 간 계산.
커밋 전 체크리스트:
- 이 스토어를 상수와 함수 파일로 대체해도 아키텍처가 깨지지 않을까?
- 안 된다면 과부하—로직을 추출하세요.
핵심 요약
- 중앙화된 상태 변경: 직접 ref 접근 대신 액션.
- 설정 문법: 테스트 쉽고,
this없음. - 감시자 금지: 부수 효과 밖으로, 스토어 예측 가능.
- 영속성 분리: 액션 아닌 플러그인.
- 단일 책임: 복잡 로직은 컴포저블로.
이 접근법으로 스토어를 가볍고, 모킹 쉽고, 리팩토링 친화적으로 유지하세요. 프로젝트가 유지보수 가능해지고, 습관이 금세 들립니다.
— Editorial Team
아직 댓글이 없습니다.