Files
sam-react-prod/claudedocs/api/[IMPL-2025-12-30] fetch-wrapper-migration.md
byeongcheolryu d38b1242d7 feat: fetchWrapper 마이그레이션 및 토큰 리프레시 캐싱 구현
- 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>
2025-12-30 17:00:18 +09:00

8.2 KiB

Fetch Wrapper Migration Checklist

생성일: 2025-12-30 목적: 모든 Server Actions의 API 통신을 serverFetch로 중앙화

목적 및 배경

왜 fetch-wrapper를 도입했는가?

  1. 중앙화된 인증 처리

    • 401 에러(세션 만료) 발생 시 → 로그인 페이지 리다이렉트
    • 모든 API 호출에서 일관된 인증 검증
  2. 개발 규칙 표준화

    • 새 작업자도 serverFetch 사용하면 자동으로 인증 검증 적용
    • 개별 파일마다 인증 로직 구현 불필요
  3. 유지보수성 향상

    • 인증 로직 변경 시 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.ts
  • VendorManagement/actions.ts
  • PurchaseManagement/actions.ts
  • DepositManagement/actions.ts
  • WithdrawalManagement/actions.ts
  • VendorLedger/actions.ts
  • ReceivablesStatus/actions.ts
  • ExpectedExpenseManagement/actions.ts
  • CardTransactionInquiry/actions.ts
  • DailyReport/actions.ts
  • BadDebtCollection/actions.ts
  • BankTransactionInquiry/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.ts
  • DraftBox/actions.ts
  • ReferenceBox/actions.ts
  • DocumentCreate/actions.ts (파일 업로드는 직접 fetch 유지)

Production 도메인 (4 files) 완료

  • WorkerScreen/actions.ts
  • WorkOrders/actions.ts
  • WorkResults/actions.ts
  • ProductionDashboard/actions.ts

Settings 도메인 (10 files) 완료

  • WorkScheduleManagement/actions.ts
  • SubscriptionManagement/actions.ts
  • PopupManagement/actions.ts
  • PaymentHistoryManagement/actions.ts
  • LeavePolicyManagement/actions.ts
  • NotificationSettings/actions.ts
  • AttendanceSettingsManagement/actions.ts
  • CompanyInfoManagement/actions.ts
  • AccountInfoManagement/actions.ts
  • AccountManagement/actions.ts

기타 도메인 (12 files) 완료

  • process-management/actions.ts
  • outbound/ShipmentManagement/actions.ts
  • material/StockStatus/actions.ts
  • material/ReceivingManagement/actions.ts
  • customer-center/shared/actions.ts
  • board/actions.ts
  • reports/actions.ts
  • quotes/actions.ts
  • board/BoardManagement/actions.ts
  • attendance/actions.ts
  • pricing/actions.ts
  • quality/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.ts
  • VendorManagement/actions.ts
  • PurchaseManagement/actions.ts
  • DepositManagement/actions.ts
  • WithdrawalManagement/actions.ts
  • VendorLedger/actions.ts
  • ReceivablesStatus/actions.ts
  • ExpectedExpenseManagement/actions.ts
  • CardTransactionInquiry/actions.ts
  • DailyReport/actions.ts
  • BadDebtCollection/actions.ts
  • BankTransactionInquiry/actions.ts

HR 도메인 (6/6)

  • EmployeeManagement/actions.ts (이미 마이그레이션됨)
  • VacationManagement/actions.ts
  • SalaryManagement/actions.ts
  • CardManagement/actions.ts
  • DepartmentManagement/actions.ts
  • AttendanceManagement/actions.ts

Approval 도메인 (4/4)

  • ApprovalBox/actions.ts
  • DraftBox/actions.ts
  • ReferenceBox/actions.ts
  • DocumentCreate/actions.ts (파일 업로드는 직접 fetch 유지)

Production 도메인 (4/4)

  • WorkerScreen/actions.ts
  • WorkOrders/actions.ts
  • WorkResults/actions.ts
  • ProductionDashboard/actions.ts

Settings 도메인 (10/10)

  • WorkScheduleManagement/actions.ts
  • SubscriptionManagement/actions.ts
  • PopupManagement/actions.ts
  • PaymentHistoryManagement/actions.ts
  • LeavePolicyManagement/actions.ts
  • NotificationSettings/actions.ts
  • AttendanceSettingsManagement/actions.ts
  • CompanyInfoManagement/actions.ts
  • AccountInfoManagement/actions.ts
  • AccountManagement/actions.ts

기타 도메인 (12/12) 완료

  • process-management/actions.ts
  • outbound/ShipmentManagement/actions.ts
  • material/StockStatus/actions.ts
  • material/ReceivingManagement/actions.ts
  • customer-center/shared/actions.ts
  • board/actions.ts
  • reports/actions.ts
  • quotes/actions.ts
  • board/BoardManagement/actions.ts
  • attendance/actions.ts
  • pricing/actions.ts
  • quality/InspectionManagement/actions.ts

참조 파일

  • fetch-wrapper: src/lib/api/fetch-wrapper.ts
  • errors: src/lib/api/errors.ts
  • 완료된 예시: src/components/accounting/BillManagement/actions.ts (참고용)

주의사항

  1. 기존 getApiHeaders() 함수 제거 - serverFetch가 헤더 자동 생성
  2. import { cookies } from 'next/headers' 제거 - wrapper에서 처리
  3. 에러 응답 구조 맞추기 - { success: false, error: string } 형태 유지
  4. 빌드 테스트 필수 - 마이그레이션 후 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');
}