store-data-structures은(는) 무엇을 하나요?
LobeHub Zustand 스토어 데이터 구조 패턴입니다. 스토어 상태, 리스트/세부 정보 분할, 정규화된 맵, 리듀서, messagesMap, topicsMap을 설계하거나 공유 타입 소스를 선택할 때 사용하세요.
주요 개념
-
리스트/세부 정보 분할 (List/Detail Split): 데이터 목록과 개별 항목의 세부 정보를 분리하여 저장합니다. 이를 통해 목록 조회 시 필요한 최소한의 데이터만 가져오고, 세부 정보는 필요할 때 개별적으로 로드할 수 있습니다.
- 예시:
list: Item[],detailMap: Record<Id, Detail>
- 예시:
-
정규화된 맵 (Normalized Map): 중복을 제거하고 ID 기반으로 데이터를 저장하여 빠른 조회와 업데이트를 가능하게 합니다.
- 예시:
entities: Record<Id, Entity>
- 예시:
-
리듀서 (Reducer): 복잡한 상태 업데이트 로직을 순수 함수로 분리하여 스토어의 예측 가능성을 높입니다.
- Zusstand의
set함수와 함께 사용됩니다.
- Zusstand의
-
messagesMap / topicsMap: 채팅 메시지와 주제를 관리하기 위한 특수한 맵 구조입니다. 각각의 키는 세션 ID나 사용자 ID가 될 수 있습니다.
- 예시:
messagesMap: Record<SessionId, Message[]>
- 예시:
사용 예시 (TypeScript)
import { create } from 'zustand';
interface StoreState {
list: string[];
detailMap: Record<string, Detail>;
messagesMap: Record<string, Message[]>;
topicsMap: Record<string, Topic[]>;
setList: (list: string[]) => void;
addDetail: (id: string, detail: Detail) => void;
addMessage: (sessionId: string, message: Message) => void;
}
const useStore = create<StoreState>((set) => ({
list: [],
detailMap: {},
messagesMap: {},
topicsMap: {},
setList: (list) => set({ list }),
addDetail: (id, detail) =>
set((state) => ({
detailMap: { ...state.detailMap, [id]: detail },
})),
addMessage: (sessionId, message) =>
set((state) => ({
messagesMap: {
...state.messagesMap,
[sessionId]: [
...(state.messagesMap[sessionId] || []),
message,
],
},
})),
}));
공유 타입 소스
타입 정의는 src/types 디렉토리에 공유하여 프로젝트 전체에서 일관성을 유지합니다. 예시:
// src/types/store.ts
export interface Detail {
id: string;
name: string;
description?: string;
}
export interface Message {
id: string;
role: 'user' | 'assistant';
content: string;
timestamp: number;
}
export interface Topic {
id: string;
title: string;
messages: Message[];
}