Files
sam-docs/dev/guides/swagger-guide.md
권혁성 db63fcff85 refactor: [docs] 팀별 폴더 구조 재편 (공유/개발/프론트/기획)
- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동)
- 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/)
- 기획팀 폴더 requests/ 생성
- plans/ → dev/dev_plans/ 이름 변경
- README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용)
- resources.md 신규 (노션 링크용, assets/brochure 이관 예정)
- CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동
- 전체 참조 경로 업데이트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:46:03 +09:00

5.7 KiB

Swagger 문서화 가이드

업데이트: 2025-12-26


개요

라이브러리: l5-swagger 9.0

Swagger 구조

파일 위치

  • 경로: app/Swagger/v1/
  • 파일명: {Resource}Api.php (예: CategoryApi.php, ClientApi.php, ProductApi.php)

원칙

  • Controller Clean: Controllers contain ONLY business logic, NO Swagger annotations
  • Separate Files: Swagger annotations are written in separate PHP class files

Swagger 파일 구조

기본 템플릿

<?php
namespace App\Swagger\v1;

/**
 * @OA\Tag(name="Resource", description="리소스 관리")
 *
 * @OA\Schema(
 *     schema="Resource",
 *     @OA\Property(property="id", type="integer"),
 *     @OA\Property(property="name", type="string"),
 *     ...
 * )
 *
 * @OA\Schema(
 *     schema="ResourcePagination",
 *     allOf={
 *         @OA\Schema(ref="#/components/schemas/PaginationMeta"),
 *         @OA\Schema(
 *             @OA\Property(
 *                 property="data",
 *                 type="array",
 *                 @OA\Items(ref="#/components/schemas/Resource")
 *             )
 *         )
 *     }
 * )
 *
 * @OA\Schema(
 *     schema="ResourceCreateRequest",
 *     required={"name"},
 *     @OA\Property(property="name", type="string"),
 *     ...
 * )
 *
 * @OA\Schema(
 *     schema="ResourceUpdateRequest",
 *     @OA\Property(property="name", type="string"),
 *     ...
 * )
 */
class ResourceApi
{
    /**
     * @OA\Get(
     *     path="/api/v1/resources",
     *     tags={"Resource"},
     *     summary="리소스 목록 조회",
     *     security={{"ApiKeyAuth": {}, "BearerAuth": {}}},
     *     @OA\Parameter(
     *         name="page",
     *         in="query",
     *         @OA\Schema(type="integer", default=1)
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="성공",
     *         @OA\JsonContent(ref="#/components/schemas/ResourcePagination")
     *     )
     * )
     */
    public function index() {}

    /**
     * @OA\Post(
     *     path="/api/v1/resources",
     *     tags={"Resource"},
     *     summary="리소스 생성",
     *     security={{"ApiKeyAuth": {}, "BearerAuth": {}}},
     *     @OA\RequestBody(
     *         required=true,
     *         @OA\JsonContent(ref="#/components/schemas/ResourceCreateRequest")
     *     ),
     *     @OA\Response(
     *         response=201,
     *         description="생성 성공",
     *         @OA\JsonContent(ref="#/components/schemas/Resource")
     *     )
     * )
     */
    public function store() {}

    /**
     * @OA\Get(
     *     path="/api/v1/resources/{id}",
     *     tags={"Resource"},
     *     summary="리소스 상세 조회",
     *     security={{"ApiKeyAuth": {}, "BearerAuth": {}}},
     *     @OA\Parameter(
     *         name="id",
     *         in="path",
     *         required=true,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="성공",
     *         @OA\JsonContent(ref="#/components/schemas/Resource")
     *     )
     * )
     */
    public function show() {}

    /**
     * @OA\Put(
     *     path="/api/v1/resources/{id}",
     *     tags={"Resource"},
     *     summary="리소스 수정",
     *     security={{"ApiKeyAuth": {}, "BearerAuth": {}}},
     *     @OA\Parameter(
     *         name="id",
     *         in="path",
     *         required=true,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\RequestBody(
     *         required=true,
     *         @OA\JsonContent(ref="#/components/schemas/ResourceUpdateRequest")
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="수정 성공",
     *         @OA\JsonContent(ref="#/components/schemas/Resource")
     *     )
     * )
     */
    public function update() {}

    /**
     * @OA\Delete(
     *     path="/api/v1/resources/{id}",
     *     tags={"Resource"},
     *     summary="리소스 삭제",
     *     security={{"ApiKeyAuth": {}, "BearerAuth": {}}},
     *     @OA\Parameter(
     *         name="id",
     *         in="path",
     *         required=true,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="삭제 성공"
     *     )
     * )
     */
    public function destroy() {}
}

필수 규칙

1. Tags

  • Resource-based (User, Auth, Product, BOM, Client...)
  • 리소스별 논리적 그룹핑

2. Security

security={{"ApiKeyAuth": {}, "BearerAuth": {}}}
  • 모든 엔드포인트에 필수

3. Schemas

  • Resource model: 응답 데이터 구조
  • Pagination: 페이지네이션 응답 (PaginationMeta 재사용)
  • CreateRequest: 생성 요청 스키마
  • UpdateRequest: 수정 요청 스키마

4. Parameters

  • Path/Query/Body parameters 명확히 정의
  • 예시 값 제공 (example 속성)

5. 중복 방지

  • No duplicate schemas: 공통 스키마는 재사용
  • nullable/oneOf 정확한 구분

Swagger 재생성

php artisan l5-swagger:generate

실행 시점:

  • Swagger 파일 생성/수정 후
  • API 엔드포인트 변경 후

접근 방법


체크리스트

✓ Swagger 파일 위치: app/Swagger/v1/{Resource}Api.php
✓ Controller에 Swagger 주석 없음
✓ Resource 태그 적용
✓ ApiKeyAuth + BearerAuth 스키마
✓ 스키마 재사용 (중복 없음)
✓ 예시 값 제공
✓ php artisan l5-swagger:generate 실행

관련 문서


최종 업데이트: 2025-12-26