- claudedocs 폴더 구조 재정리: archive/sessions, guides/migration·mobile·universal-list, refactoring 분류 - 오래된 세션 컨텍스트/체크리스트 문서 정리 (아카이브 이동 또는 삭제) - AuthContext → authStore(Zustand) 전환 시작, RootProvider 간소화 - GenericCRUDDialog 공통 다이얼로그 컴포넌트 추가 - PermissionDialog 삭제 → GenericCRUDDialog로 대체 - RankDialog/TitleDialog GenericCRUDDialog 기반으로 리팩토링 - toast-utils.ts 삭제 (미사용) - fileDownload.ts 개선, excel-download.ts 정리 - menuStore/themeStore Zustand 셀렉터 최적화 - useColumnSettings/useTableColumnStore 기능 보강 - 세금계산서/견적/작업자화면/결재 등 소규모 개선 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.6 KiB
4.6 KiB
Server Component → Client Component 마이그레이션 계획서
배경
- 문제: Server Component에서 API 호출 시 토큰 갱신(쿠키 수정)이 불가능
- 원인: Next.js 15에서 Server Component 렌더링 중 쿠키 수정 금지
- 영향: 토큰 만료 시 기본값 표시 → 데이터 덮어쓰기 위험
- 결정: 폐쇄형 사이트로 SEO 불필요, Client Component로 전환
변경 대상 (53개 페이지)
Settings (4개)
- settings/notification-settings/page.tsx
- settings/popup-management/page.tsx
- settings/permissions/[id]/page.tsx
- settings/account-info/page.tsx
Accounting (9개)
- accounting/vendors/page.tsx
- accounting/sales/page.tsx
- accounting/deposits/page.tsx
- accounting/bills/page.tsx
- accounting/withdrawals/page.tsx
- accounting/expected-expenses/page.tsx
- accounting/bad-debt-collection/page.tsx
- accounting/bad-debt-collection/[id]/page.tsx
- accounting/bad-debt-collection/[id]/edit/page.tsx
Sales (4개)
- sales/quote-management/page.tsx
- sales/pricing-management/page.tsx
- sales/pricing-management/[id]/edit/page.tsx
- sales/pricing-management/create/page.tsx
Production (3개)
- production/work-orders/[id]/page.tsx
- production/screen-production/page.tsx
- production/screen-production/[id]/page.tsx
Quality (1개)
- quality/inspections/[id]/page.tsx
Master Data (2개)
- master-data/process-management/[id]/page.tsx
- master-data/process-management/[id]/edit/page.tsx
Material (2개)
- material/stock-status/[id]/page.tsx
- material/receiving-management/[id]/page.tsx
Outbound (2개)
- outbound/shipments/[id]/page.tsx
- outbound/shipments/[id]/edit/page.tsx
Construction - Order (8개)
- construction/order/order-management/[id]/page.tsx
- construction/order/order-management/[id]/edit/page.tsx
- construction/order/site-management/[id]/page.tsx
- construction/order/site-management/[id]/edit/page.tsx
- construction/order/structure-review/[id]/page.tsx
- construction/order/structure-review/[id]/edit/page.tsx
- construction/order/base-info/items/[id]/page.tsx
- construction/order/base-info/pricing/[id]/page.tsx
- construction/order/base-info/pricing/[id]/edit/page.tsx
- construction/order/base-info/labor/[id]/page.tsx
Construction - Project/Bidding (8개)
- construction/project/bidding/[id]/page.tsx
- construction/project/bidding/[id]/edit/page.tsx
- construction/project/bidding/site-briefings/[id]/page.tsx
- construction/project/bidding/site-briefings/[id]/edit/page.tsx
- construction/project/bidding/estimates/[id]/page.tsx
- construction/project/bidding/estimates/[id]/edit/page.tsx
- construction/project/bidding/partners/[id]/page.tsx
- construction/project/bidding/partners/[id]/edit/page.tsx
Construction - Project/Contract (4개)
- construction/project/contract/[id]/page.tsx
- construction/project/contract/[id]/edit/page.tsx
- construction/project/contract/handover-report/[id]/page.tsx
- construction/project/contract/handover-report/[id]/edit/page.tsx
Others (4개)
- payment-history/page.tsx
- subscription/page.tsx
- dev/test-urls/page.tsx
- dev/construction-test-urls/page.tsx
변환 패턴
Before (Server Component)
import { Component } from '@/components/...';
import { getData } from '@/components/.../actions';
export default async function Page() {
const result = await getData();
return <Component initialData={result.data} />;
}
After (Client Component)
'use client';
import { useEffect, useState } from 'react';
import { Component } from '@/components/...';
import { getData } from '@/components/.../actions';
import { DEFAULT_DATA } from '@/components/.../types';
export default function Page() {
const [data, setData] = useState(DEFAULT_DATA);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
getData()
.then(result => {
if (result.success) {
setData(result.data);
}
})
.finally(() => setIsLoading(false));
}, []);
if (isLoading) {
return <div>로딩 중...</div>;
}
return <Component initialData={data} />;
}
추가 작업
1. RULES.md 업데이트
- Client Component 사용 원칙 추가
- SEO 불필요 폐쇄형 사이트 명시
2. fetch-wrapper.ts 정리
- skipTokenRefresh 옵션 제거 (불필요해짐)
3. actions.ts 정리
- skipTokenRefresh 관련 코드 제거
진행 상태
- 시작일: 2026-01-09
- 현재 상태: 진행 중