반응형

필요 라이브러리 설치
시스템 구조에서 MobX + React Context 기반 store 설계를 위해 필요한 라이브러리 설치:
npm install mobx mobx-react-lite
npm install react react-dom
npm install typescript @types/react @types/react-dom
Vite 기반 프로젝트라면:
npm create vite@latest my-app --template react-ts
대규모 ERP 시스템에서 모듈별 store 구조를 다음처럼 나누었을 때:
root
├─ cmn (공통 store)
├─ mdm (Master Data Management store)
└─ sys (System별 store)
1) TypeScript 제네릭을 이용한 반환 타입 자동 추론
아래 타입 정의는 useStore('mdm') 호출 시 자동으로 타입이 결정되게 하는 구조입니다:
type TUseStoreReturnType<T extends TUseStoreType> =
T extends 'cmn' ? TCmnStores :
T extends 'sys' ? TSysStores :
T extends 'all' ? TCmnStores & TSysStores :
T extends 'root' ? RootRefacStore :
never;
예)
const cmnStore = useStore("cmn"); // => type TCmnStores
const sysStore = useStore("sys"); // => type TSysStores
2) React Context 사용
스토어를 전역적으로 접근하기 위해 Context 사용
const rootRefacStore = useContext(RootRefacStoreContext);
3) CMN, SYS 스토어 분리 + 병합
case 'all':
return { ...cmd, ...sys };
ERP 시스템에서 여러 도메인의 스토어 사용이 용이함.
4) root 반환
root 전체 스토어를 그대로 받고 싶을 때:
case 'root':
return rootRefacStore;
1장. ERP Front 구조 이해
- React + MobX + Context 기반 Store Layer
- Root → cmn → (mdm / sys) store 설계 이유
- React Context로 모듈 간 의존성 끊고 유지보수성 향상
2장. useStore 훅의 역할
- ERP 시스템에서 store 접근을 중앙 관리
- 입력값에 따라 반환 store가 자동 결정
- TypeScript 제네릭으로 타입 안정성 보장
3장. 타입 시스템 설명
TUseStoreType
type TUseStoreType = 'cmn' | 'sys' | 'all' | 'root';
TUseStoreReturnType
입력값에 따라 반환 타입이 달라지는 형태:
T extends 'cmn' → TCmnStores
T extends 'sys' → TSysStores
T extends 'all' → TCmnStores & TSysStores
T extends 'root' → RootRefacStore
4장. 실제 동작 과정
- Context에서 Root Store 가져옴
- 사용자가 'cmn' 또는 'sys' 전달
- switch-case로 적절한 store 반환
- TypeScript가 자동으로 타입을 결정
- 컴포넌트에서 매우 안전하게 store 접근 가능
5장. 예제: CMN 화면에서 store 사용
import { observer } from "mobx-react-lite";
import { useStore } from "../../common/hooks/useStore";
export const MdmUserList = observer(() => {
const mdm = useStore("mdm");
return (
<div>
사용자 수: {mdm.userStore.count}
</div>
);
});
6장. 예제: SYS + CMN 모두 사용하는 화면
const Dashboard = observer(() => {
const stores = useStore("all");
return (
<>
<div>공통코드: {stores.codeStore.total}</div>
<div>시스템 알림: {stores.sysAlertStore.total}</div>
</>
);
});
7장. Root Store 전체 사용 예제
const App = () => {
const root = useStore("root");
return (
<div>
Loaded modules: {root.loadedModules.join(", ")}
</div>
);
};
실전 예제용 완성 코드
Root Store Context
import { createContext } from "react";
import { RootRefacStore } from "./RootRefacStore";
export const RootRefacStoreContext = createContext<RootRefacStore | null>(null);
RootRefacStore 예시
export class RootRefacStore {
mdm: TCmnStores;
sys: TSysStores;
constructor() {
this.mdm = new TCmnStores();
this.sys = new TSysStores();
}
}
Provider 설정
export function StoreProvider({ children }) {
const root = new RootRefacStore();
return (
<RootRefacStoreContext.Provider value={root}>
{children}
</RootRefacStoreContext.Provider>
);
}
사용자 정의 훅 최종 정리
export function useStore<T extends TUseStoreType>(
useStoreType: T
): TUseStoreReturnType<T> {
const rootRefacStore = useContext(RootRefacStoreContext);
if (!rootRefacStore) {
throw new Error('rootRefacStore가 생성되지 않았습니다');
}
const { cmn, sys } = rootRefacStore;
switch (useStoreType) {
case 'cmn':
return cmn as TUseStoreReturnType<T>;
case 'sys':
return sys as TUseStoreReturnType<T>;
case 'all':
return { ...cmn, ...sys } as TUseStoreReturnType<T>;
case 'root':
return rootRefacStore as TUseStoreReturnType<T>;
default:
throw new Error('Invalid useStoreType');
}
}
반응형
'교육' 카테고리의 다른 글
| "destroy is not a function" 오류의 정체와 해결 전략 (0) | 2025.11.19 |
|---|---|
| react-helmet의 기본 개념과 사용법 (0) | 2025.11.18 |
| "TypeScript 제네릭 기반 Form 재사용 패턴: React Hook Form과 함께하는 고급 Form 설계" (0) | 2025.11.17 |
| #007 React useMemo : 성능 최적화의 정석 (0) | 2025.11.13 |
| #006 Context Provider (컨텍스트 프로바이더) (0) | 2025.11.13 |