- 40+ actions.ts 파일을 fetchWrapper 패턴으로 마이그레이션 - 토큰 리프레시 캐싱 로직 추가 (refresh-token.ts) - ApiErrorContext 추가로 전역 에러 처리 개선 - HR EmployeeForm 컴포넌트 개선 - 참조함(ReferenceBox) 기능 수정 - juil 테스트 URL 페이지 추가 - claudedocs 문서 업데이트 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8.2 KiB
8.2 KiB
Fetch Wrapper Migration Checklist
생성일: 2025-12-30
목적: 모든 Server Actions의 API 통신을 serverFetch로 중앙화
목적 및 배경
왜 fetch-wrapper를 도입했는가?
-
중앙화된 인증 처리
- 401 에러(세션 만료) 발생 시 → 로그인 페이지 리다이렉트
- 모든 API 호출에서 일관된 인증 검증
-
개발 규칙 표준화
- 새 작업자도
serverFetch사용하면 자동으로 인증 검증 적용 - 개별 파일마다 인증 로직 구현 불필요
- 새 작업자도
-
유지보수성 향상
- 인증 로직 변경 시
fetch-wrapper.ts한 파일만 수정 - 403, 네트워크 에러 등 공통 에러 처리도 중앙화
- 인증 로직 변경 시
마이그레이션 패턴
Before (기존 패턴)
import { cookies } from 'next/headers';
async function getApiHeaders(): Promise<HeadersInit> {
const cookieStore = await cookies();
const token = cookieStore.get('access_token')?.value;
return {
'Authorization': token ? `Bearer ${token}` : '',
// ...
};
}
export async function getSomething() {
const headers = await getApiHeaders();
const response = await fetch(url, { headers });
// 401 처리 없음!
}
After (새 패턴)
import { serverFetch } from '@/lib/api/fetch-wrapper';
export async function getSomething() {
const { response, error } = await serverFetch(url, { method: 'GET' });
if (error) {
// 401/403/네트워크 에러 자동 처리됨
return { success: false, error: error.message };
}
const data = await response.json();
// ...
}
마이그레이션 체크리스트
Accounting 도메인 (12 files) ✅ 완료
SalesManagement/actions.tsVendorManagement/actions.tsPurchaseManagement/actions.tsDepositManagement/actions.tsWithdrawalManagement/actions.tsVendorLedger/actions.tsReceivablesStatus/actions.tsExpectedExpenseManagement/actions.tsCardTransactionInquiry/actions.tsDailyReport/actions.tsBadDebtCollection/actions.tsBankTransactionInquiry/actions.ts
HR 도메인 (6 files) ✅ 완료
EmployeeManagement/actions.ts✅ (이미 마이그레이션됨)VacationManagement/actions.ts✅SalaryManagement/actions.ts✅CardManagement/actions.ts✅DepartmentManagement/actions.ts✅AttendanceManagement/actions.ts✅
Approval 도메인 (4 files) ✅ 완료
ApprovalBox/actions.tsDraftBox/actions.tsReferenceBox/actions.tsDocumentCreate/actions.ts(파일 업로드는 직접 fetch 유지)
Production 도메인 (4 files) ✅ 완료
WorkerScreen/actions.tsWorkOrders/actions.tsWorkResults/actions.tsProductionDashboard/actions.ts
Settings 도메인 (10 files) ✅ 완료
WorkScheduleManagement/actions.tsSubscriptionManagement/actions.tsPopupManagement/actions.tsPaymentHistoryManagement/actions.tsLeavePolicyManagement/actions.tsNotificationSettings/actions.tsAttendanceSettingsManagement/actions.tsCompanyInfoManagement/actions.tsAccountInfoManagement/actions.tsAccountManagement/actions.ts
기타 도메인 (12 files) ✅ 완료
process-management/actions.tsoutbound/ShipmentManagement/actions.tsmaterial/StockStatus/actions.tsmaterial/ReceivingManagement/actions.tscustomer-center/shared/actions.tsboard/actions.tsreports/actions.tsquotes/actions.tsboard/BoardManagement/actions.tsattendance/actions.tspricing/actions.tsquality/InspectionManagement/actions.ts
진행 상황
| 도메인 | 파일 수 | 완료 | 상태 |
|---|---|---|---|
| Accounting | 12 | 12 | ✅ 완료 |
| HR | 6 | 6 | ✅ 완료 |
| Approval | 4 | 4 | ✅ 완료 |
| Production | 4 | 4 | ✅ 완료 |
| Settings | 10 | 10 | ✅ 완료 |
| 기타 | 12 | 12 | ✅ 완료 |
| 총계 | 48 | 48 | 100% ✅ |
완료된 파일 (완전 마이그레이션)
Accounting 도메인 (12/12)
SalesManagement/actions.tsVendorManagement/actions.tsPurchaseManagement/actions.tsDepositManagement/actions.tsWithdrawalManagement/actions.tsVendorLedger/actions.tsReceivablesStatus/actions.tsExpectedExpenseManagement/actions.tsCardTransactionInquiry/actions.tsDailyReport/actions.tsBadDebtCollection/actions.tsBankTransactionInquiry/actions.ts
HR 도메인 (6/6)
EmployeeManagement/actions.ts(이미 마이그레이션됨)VacationManagement/actions.tsSalaryManagement/actions.tsCardManagement/actions.tsDepartmentManagement/actions.tsAttendanceManagement/actions.ts
Approval 도메인 (4/4)
ApprovalBox/actions.tsDraftBox/actions.tsReferenceBox/actions.tsDocumentCreate/actions.ts(파일 업로드는 직접 fetch 유지)
Production 도메인 (4/4)
WorkerScreen/actions.tsWorkOrders/actions.tsWorkResults/actions.tsProductionDashboard/actions.ts
Settings 도메인 (10/10)
WorkScheduleManagement/actions.tsSubscriptionManagement/actions.tsPopupManagement/actions.tsPaymentHistoryManagement/actions.tsLeavePolicyManagement/actions.tsNotificationSettings/actions.tsAttendanceSettingsManagement/actions.tsCompanyInfoManagement/actions.tsAccountInfoManagement/actions.tsAccountManagement/actions.ts
기타 도메인 (12/12) ✅ 완료
process-management/actions.tsoutbound/ShipmentManagement/actions.tsmaterial/StockStatus/actions.tsmaterial/ReceivingManagement/actions.tscustomer-center/shared/actions.tsboard/actions.tsreports/actions.tsquotes/actions.tsboard/BoardManagement/actions.tsattendance/actions.tspricing/actions.tsquality/InspectionManagement/actions.ts
참조 파일
- fetch-wrapper:
src/lib/api/fetch-wrapper.ts - errors:
src/lib/api/errors.ts - 완료된 예시:
src/components/accounting/BillManagement/actions.ts(참고용)
주의사항
- 기존
getApiHeaders()함수 제거 -serverFetch가 헤더 자동 생성 import { cookies } from 'next/headers'제거 - wrapper에서 처리- 에러 응답 구조 맞추기 -
{ success: false, error: string }형태 유지 - 빌드 테스트 필수 - 마이그레이션 후
npm run build확인
🔜 추가 작업 (마이그레이션 완료 후)
Phase 2: 리프레시 토큰 자동 갱신 적용
현재 문제:
- access_token 만료 시 (약 2시간) 바로 로그인 리다이렉트됨
- refresh_token (7일)을 사용한 자동 갱신 로직이 호출되지 않음
- 결과: 40분~2시간 후 세션 만료 → 재로그인 필요
목표:
- 401 발생 시 → 리프레시 토큰으로 갱신 시도 → 성공 시 재시도
- 7일간 세션 유지 (refresh_token 만료 시에만 재로그인)
적용 범위:
| 영역 | 적용 위치 | 작업 |
|---|---|---|
| Server Actions | fetch-wrapper.ts |
401 시 리프레시 후 재시도 로직 추가 |
| 품목관리 | ItemListClient.tsx 등 |
클라이언트 fetch에 리프레시 로직 추가 |
| 품목기준관리 | 관련 컴포넌트들 | 클라이언트 fetch에 리프레시 로직 추가 |
관련 파일:
src/lib/auth/token-refresh.ts- 리프레시 함수 (이미 존재)src/app/api/auth/refresh/route.ts- 리프레시 API (이미 존재)
예상 구현:
// fetch-wrapper.ts 401 처리 부분
if (response.status === 401 && !options?.skipAuthCheck) {
// 1. 리프레시 토큰으로 갱신 시도
const refreshResult = await refreshTokenServer(refreshToken);
if (refreshResult.success) {
// 2. 새 토큰으로 원래 요청 재시도
return serverFetch(url, { ...options, skipAuthCheck: true });
}
// 3. 리프레시도 실패하면 로그인 리다이렉트
redirect('/login');
}