Store
내장 store로 전역 UI 상태를 공유합니다.
파일형 내장 Store
- app/stores/<이름>.store.ts의 default export 객체가 같은 이름의 store.<이름>으로 등록됩니다.
- Store는 하위 폴더에서도 재귀적으로 인식합니다. 폴더는 정리 용도이며 파일 이름은 전체 app/stores에서 고유해야 합니다.
- 상태와 상태를 변경하는 함수를 한 파일에 두며 별도 import, reactive나 상태 관리 패키지가 필요하지 않습니다.
- store 파일은 영문 변수 형식의 이름을 사용하고 app/stores 바로 아래에 둡니다.
- 함수는 같은 모듈의 상태를 this로 읽고 변경할 수 있습니다.
- 각 store 모듈의 타입을 자동 생성하므로 Cake20 View TSX에서 자동완성을 제공합니다.
// app/stores/cart.store.ts
type CartItem = {
id: string;
name: string;
price: number;
count: number;
};
export const config = {
// "none": 새로고침까지 | "session": 현재 탭까지 | "local": 브라우저를 닫아도 유지
persist: "local"
} as const;
export default {
items: [] as CartItem[],
add(item: Omit<CartItem, "count">) {
const found = this.items.find((row) => row.id === item.id);
if (found) {
found.count++;
return;
}
this.items.push({ ...item, count: 1 });
},
remove(id: string) {
this.items = this.items.filter((item) => item.id !== id);
},
clear() {
this.items = [];
}
};Cake20 View에서 사용
- store는 모든 Cake20 View 페이지, 레이아웃과 컴포넌트에서 import 없이 사용합니다.
- 상태는 반응형으로 제공되므로 직접 읽거나 함수로 변경하면 화면이 즉시 갱신됩니다.
- 브라우저 UI 전용 인터페이스이므로 API, Task, Job 같은 서버 코드에서는 사용하지 않습니다.
export const computed = {
total: () =>
store.cart.items.reduce(
(sum, item) => sum + item.price * item.count,
0
)
};
export const addCake = () => {
store.cart.add({
id: "strawberry",
name: "딸기 케이크",
price: 32000
});
};
export default () => (
<>
<Button onClick={addCake}>장바구니 담기</Button>
<p>{store.cart.items.length}종 · {computed.total().toLocaleString()}원</p>
</>
);저장 방식
- 현재 store config에서 설정할 수 있는 항목은 persist 하나입니다.
- none은 메모리, session은 sessionStorage, local은 localStorage에 해당 모듈의 상태를 JSON으로 저장합니다.
- config 또는 persist를 생략하면 persist: "none"과 같이 현재 페이지 메모리에만 유지합니다.
- 저장된 값은 시작할 때 default 상태에 병합되므로 파일에 선언한 함수는 유지됩니다.
- local 모듈은 같은 웹사이트의 다른 탭에서 변경되면 자동으로 동기화됩니다.
- 테스트 주소와 운영 주소는 origin이 달라 저장 상태도 서로 섞이지 않습니다.
- 관리자 안의 UI 프리뷰도 웹사이트별 base 경로로 저장 영역을 분리합니다.
- 함수, 순환 참조와 JSON으로 표현할 수 없는 값은 저장 상태로 사용하지 않습니다.
- 인증 토큰, 비밀번호, Secret과 민감정보는 store에 저장하지 않습니다. 로그인은 서버 auth의 HttpOnly 쿠키를 사용합니다.
// 브라우저를 닫았다 열어도 유지
export const config = { persist: "local" } as const;
// 현재 탭을 닫을 때까지 유지
export const config = { persist: "session" } as const;
// 메모리에서만 유지하고 새로고침하면 초기화
export const config = { persist: "none" } as const;
// 한 모듈 또는 모든 모듈을 기본값으로 초기화
store.$reset("cart");
store.$reset();