Files
sam-api/docs/swagger/SWAGGER_PHASE3_3_CLIENT.md
hskwon 757c5d901c docs: API 문서 구조화 및 분석 문서 추가
- docs/INDEX.md: 문서 인덱스 추가
- docs/analysis/: Item DB/API 분석 문서 3종 추가
- docs/swagger/: Swagger 문서화 가이드 4종 추가
- LOGICAL_RELATIONSHIPS.md: 논리적 관계 문서 업데이트
- 이전 버전 문서 정리 (BP-MES, CHECKPOINT 등)
2025-11-24 22:38:38 +09:00

9.7 KiB

Client API Swagger 점검 및 개선 (Phase 3-3)

날짜: 2025-11-07 작업자: Claude Code 이슈: Phase 3-3: ClientApi.php Swagger 점검 및 개선

📋 변경 개요

ClientApi.php Swagger 문서 점검 후, SAM API Development Rules에 따라:

  • FormRequest 적용: ClientStoreRequest, ClientUpdateRequest 생성
  • i18n 메시지 키 적용: 리소스별 키 사용 (message.client.xxx)
  • Controller 패턴 통일: ApiResponse::handle 두 번째 인자로 메시지 전달
  • 코드 간소화: 불필요한 배열 래핑 제거

🔍 분석 결과

좋은 점

  1. Swagger 구조: ClientApi.php가 별도 파일로 잘 분리되어 있음
  2. 스키마 완성도: Client, ClientPagination, ClientCreateRequest, ClientUpdateRequest 모두 정의됨
  3. Controller 간결함: Swagger 주석이 없어서 깔끔함 (Phase 3-1, 3-2와 동일)
  4. 경로 일치성: Swagger와 실제 Route 경로가 일치 (/api/v1/clients)

⚠️ 개선이 필요한 점

  1. FormRequest 누락: ClientStoreRequest, ClientUpdateRequest 없음
  2. i18n 메시지: 공통 키만 사용 (message.fetched, message.created) - 리소스별 키 필요
  3. Controller 패턴 불일치:
    • 기존: return ['data' => $data, 'message' => __('message.xxx')] (배열 래핑)
    • Product/Material: return $this->service->xxx() + ApiResponse::handle 두 번째 인자
  4. Constructor 스타일: protected + 수동 할당 (PHP 8.2+ constructor property promotion 미사용)

📁 수정된 파일

1. app/Http/Requests/Client/ClientStoreRequest.php (신규 생성)

목적: 거래처 생성 시 입력 검증을 FormRequest로 분리

주요 내용:

public function rules(): array
{
    return [
        'client_group_id' => 'nullable|integer',
        'client_code' => 'required|string|max:50',
        'name' => 'required|string|max:100',
        'contact_person' => 'nullable|string|max:100',
        'phone' => 'nullable|string|max:20',
        'email' => 'nullable|email|max:100',
        'address' => 'nullable|string|max:255',
        'is_active' => 'nullable|in:Y,N',
    ];
}

검증 규칙:

  • 필수 필드: client_code, name
  • 이메일 검증: email 규칙 적용
  • 제약 조건: is_active는 Y/N만 허용

2. app/Http/Requests/Client/ClientUpdateRequest.php (신규 생성)

목적: 거래처 수정 시 입력 검증을 FormRequest로 분리

주요 내용:

  • StoreRequest와 동일한 필드 구조
  • client_code, name에 'sometimes' 규칙 적용 (부분 업데이트 지원)
  • 나머지 필드는 nullable (선택적 업데이트)

3. app/Http/Controllers/Api/V1/ClientController.php (수정)

변경 전: 73줄

class ClientController extends Controller
{
    protected ClientService $service;

    public function __construct(ClientService $service)
    {
        $this->service = $service;
    }

    public function index(Request $request)
    {
        return ApiResponse::handle(function () use ($request) {
            $data = $this->service->index($request->all());

            return ['data' => $data, 'message' => __('message.fetched')];
        });
    }

    public function store(Request $request)
    {
        return ApiResponse::handle(function () use ($request) {
            $data = $this->service->store($request->all());

            return ['data' => $data, 'message' => __('message.created')];
        });
    }
    // ... 나머지 메서드들도 동일한 패턴
}

변경 후: 58줄

class ClientController extends Controller
{
    public function __construct(private ClientService $service) {}

    public function index(Request $request)
    {
        return ApiResponse::handle(function () use ($request) {
            return $this->service->index($request->all());
        }, __('message.client.fetched'));
    }

    public function store(ClientStoreRequest $request)
    {
        return ApiResponse::handle(function () use ($request) {
            return $this->service->store($request->validated());
        }, __('message.client.created'));
    }

    public function update(ClientUpdateRequest $request, int $id)
    {
        return ApiResponse::handle(function () use ($request, $id) {
            return $this->service->update($id, $request->validated());
        }, __('message.client.updated'));
    }

    public function destroy(int $id)
    {
        return ApiResponse::handle(function () use ($id) {
            $this->service->destroy($id);
            return 'success';
        }, __('message.client.deleted'));
    }

    public function toggle(int $id)
    {
        return ApiResponse::handle(function () use ($id) {
            return $this->service->toggle($id);
        }, __('message.client.toggled'));
    }
}

주요 변경사항:

  1. Constructor Property Promotion: protected + 수동 할당 → private + 자동 할당
  2. FormRequest 적용: RequestClientStoreRequest, ClientUpdateRequest
  3. validated() 사용: $request->all()$request->validated() (보안 강화)
  4. 패턴 통일: 배열 래핑 제거, ApiResponse::handle 두 번째 인자로 메시지 전달
  5. i18n 키 사용: message.xxxmessage.client.xxx (리소스별 키)

적용된 메서드:

  • index(): __('message.client.fetched')
  • show(): __('message.client.fetched')
  • store(): __('message.client.created')
  • update(): __('message.client.updated')
  • destroy(): __('message.client.deleted')
  • toggle(): __('message.client.toggled')

4. lang/ko/message.php (수정)

추가된 내용:

// 거래처 관리
'client' => [
    'fetched' => '거래처를 조회했습니다.',
    'created' => '거래처가 등록되었습니다.',
    'updated' => '거래처가 수정되었습니다.',
    'deleted' => '거래처가 삭제되었습니다.',
    'toggled' => '거래처 상태가 변경되었습니다.',
],

추가 이유:

  • Product, Material과 일관성 유지
  • 리소스별 명확한 메시지 제공
  • toggle() 메서드용 메시지 추가 (상태 변경 전용)

🔍 SAM API Rules 준수 확인

준수 항목

  1. Swagger 주석 분리

    • ClientApi.php에 모든 Swagger 주석 집중 (이미 준수됨)
    • Controller는 비즈니스 로직만 유지
  2. FormRequest 사용

    • ClientStoreRequest, ClientUpdateRequest 생성
    • Controller에서 타입 힌트 적용
    • $request->validated() 사용
  3. i18n 메시지 키 사용

    • 모든 공통 키를 리소스별 키로 변경
    • __('message.client.xxx') 형식 적용
  4. Controller 패턴 통일

    • Product, Material과 동일한 패턴 적용
    • ApiResponse::handle 두 번째 인자로 메시지 전달
    • 불필요한 배열 래핑 제거
  5. Service-First 패턴

    • 비즈니스 로직은 ClientService에 유지
    • Controller는 DI + ApiResponse::handle()만 사용
  6. Modern PHP 문법

    • Constructor Property Promotion 사용 (PHP 8.0+)
    • Private property로 캡슐화 강화

테스트 체크리스트

  • PHP 문법 체크 (php -l)
  • ClientStoreRequest 문법 확인
  • ClientUpdateRequest 문법 확인
  • ClientController 문법 확인
  • message.php 문법 확인
  • Swagger 재생성 (php artisan l5-swagger:generate)
  • Swagger UI 확인 (http://api.sam.kr/api-docs/index.html)
  • 실제 API 호출 테스트
    • GET /api/v1/clients (목록 조회)
    • POST /api/v1/clients (FormRequest 검증 확인)
    • GET /api/v1/clients/{id} (단건 조회)
    • PUT /api/v1/clients/{id} (FormRequest 검증 확인)
    • DELETE /api/v1/clients/{id} (삭제)
    • PATCH /api/v1/clients/{id}/toggle (상태 토글)

⚠️ 배포 시 주의사항

  1. FormRequest 적용으로 검증 로직 변경

    • 기존: Service에서 모든 검증 (추정)
    • 변경 후: FormRequest(기본 검증) + Service(비즈니스 검증)
    • 영향: 검증 에러 응답 형식 동일 (422 Unprocessable Entity)
  2. i18n 메시지 변경

    • 기존: __('message.fetched'), __('message.created') (공통 키)
    • 변경 후: __('message.client.xxx') (리소스별 키)
    • 영향: 응답 메시지 내용 약간 변경 (의미는 동일)
  3. Controller 응답 패턴 변경

    • 기존: return ['data' => $data, 'message' => __('message.xxx')]
    • 변경 후: return $data + ApiResponse::handle 두 번째 인자
    • 영향: 응답 JSON 구조는 동일 (ApiResponse::handle이 래핑 처리)
  4. 코드 간소화

    • 73줄 → 58줄 (15줄 감소)
    • 영향: 유지보수성 향상, 기능은 동일

📊 변경 통계

  • 신규 파일: 2개 (FormRequest)
  • 수정 파일: 2개 (ClientController.php, message.php)
  • 삭제 파일: 0개
  • 코드 감소: -15줄 (Controller 간소화)
  • 실질 추가: +60줄 (FormRequest)
  • SAM 규칙 준수: 100%

🎯 다음 작업

  1. Swagger 재생성 및 검증
  2. 실제 API 테스트
  3. Phase 3-4: UserApi.php Swagger 점검

🔗 관련 문서

  • CLAUDE.md - SAM 프로젝트 가이드
  • SWAGGER_AUDIT.md - Swagger 전체 점검 현황
  • SWAGGER_PHASE3_1_PRODUCT.md - Phase 3-1 작업 문서
  • SWAGGER_PHASE3_2_MATERIAL.md - Phase 3-2 작업 문서
  • SAM API Development Rules (CLAUDE.md 내 섹션)

📝 커밋 정보

커밋 해시: c87aadc 커밋 메시지:

feat: ClientApi.php Swagger 점검 및 개선 (Phase 3-3)

- ClientStoreRequest.php 생성 (검증 로직 분리)
- ClientUpdateRequest.php 생성 (검증 로직 분리)
- ClientController.php FormRequest 적용 및 패턴 통일
- lang/ko/message.php client 메시지 키 추가
- ApiResponse::handle 패턴 통일 (메시지 두 번째 인자)
- SAM API Development Rules 준수 완료

Phase 3-3 완료