Article

Laravel API 문서화: OpenAPI로 우아하게 Swagger 구현하기

전통적 Swagger 주석의 문제점

laravel-swagger 이미지

laravel-swagger 이미지

laravel-swagger 이미지

laravel-swagger 이미지

laravel-swagger 이미지

laravel-swagger 이미지

laravel-swagger 이미지

laravel-swagger 이미지

PHP에서 기존 Swagger 주석은 코드 자체보다 훨씬 깁니다. 작은 API 하나 작성하는데 수십 줄의 주석이 필요하고, 중복 코드가 많아 유지보수가 어렵습니다.

/**
 * @OA\Post(
 *     path="/users",
 *     @OA\RequestBody(
 *         required=true,
 *         @OA\JsonContent(
 *             required={"name","email"},
 *             @OA\Property(property="name", type="string"),
 *             @OA\Property(property="email", type="string", format="email"),
 *         ),
 *     ),
 *     @OA\Response(response=200, description="User created"),
 * )
 */

해결책: PHP 8 Attributes + vyuldashev/laravel-openapi

PHP 8의 Attributes를 활용하면 선언형으로 API를 정의하고, 코드의 가독성과 유지보수성을 크게 향상시킬 수 있습니다.

패키지 설치

1단계: vyuldashev/laravel-openapi 설치

composer require vyuldashev/laravel-openapi

php artisan vendor:publish --provider="Spatie\LaravelData\LaravelDataServiceProvider" --tag="data-config"

php artisan openapi:generate

역할: OpenAPI JSON 스펙 생성

2단계: darkaonline/l5-swagger 설치

composer require "darkaonline/l5-swagger"

php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"

역할: 생성된 JSON을 Swagger UI로 시각화

기본 사용법

Controller 정의

<?php

namespace App\Http\Controllers;

use Vyuldashev\LaravelOpenApi\Attributes as OpenApi;

#[OpenApi\PathItem]
class TestController extends Controller
{
    #[OpenApi\Operation(tags: ['tests'])]
    public function index()
    {
        return ['type' => 'test', 'list' => []];
    }

    #[OpenApi\Operation(tags: ['tests'])]
    public function show($id)
    {
        // 구현
    }

    #[OpenApi\Operation(tags: ['tests'])]
    public function store(TestData $dto)
    {
        return $dto;
    }
}

Routes 정의

Route::get('test', [TestController::class, 'index']);
Route::get('test/{id}', [TestController::class, 'show']);
Route::post('test', [TestController::class, 'store']);

JSON 생성 및 확인

php artisan openapi:generate > storage/api-docs/api-docs.json

브라우저에서 접속:

http://example.test/api/documentation

고급 기능

1. 태그 관리

config/openapi.php에서 정의:

'tags' => [
    [
        'name' => 'tests',
        'description' => '테스트 관련 API',
    ],
    [
        'name' => 'users',
        'description' => '사용자 관련 API',
    ],
],

2. Parameter 정의

php artisan openapi:make-parameters TestList
namespace App\OpenApi\Parameters;

use GoldSpecDigital\ObjectOrientedOAS\Objects\Parameter;
use GoldSpecDigital\ObjectOrientedOAS\Objects\Schema;
use Vyuldashev\LaravelOpenApi\Factories\ParametersFactory;

class TestListParameters extends ParametersFactory
{
    public function build(): array
    {
        return [
            Parameter::query()
                ->name('name')
                ->description('(required) 검색 이름')
                ->required()
                ->schema(Schema::string()),

            Parameter::query()
                ->name('page')
                ->description('(optional) 페이지 번호')
                ->required(false)
                ->schema(Schema::integer()),
        ];
    }
}

Controller에 적용:

#[OpenApi\Operation(tags: ['tests'])]
#[OpenApi\Parameters(factory: TestListParameters::class)]
public function index()
{
    // 구현
}

3. Schema 재사용

php artisan openapi:make-schema Test
namespace App\OpenApi\Schemas;

use GoldSpecDigital\ObjectOrientedOAS\Contracts\SchemaContract;
use GoldSpecDigital\ObjectOrientedOAS\Objects\Schema;
use Vyuldashev\LaravelOpenApi\Contracts\Reusable;
use Vyuldashev\LaravelOpenApi\Factories\SchemaFactory;

class TestSchema extends SchemaFactory implements Reusable
{
    public function build(): SchemaContract
    {
        return Schema::object()->properties(
            Schema::integer('id')->example(1)->title('ID'),
            Schema::string('name')->example('Test 1')->title('이름'),
        )->required('id', 'name');
    }
}

RequestBody에서 재사용:

MediaType::json()->schema(TestSchema::ref())

핵심 장점

장점설명
재사용성Schema를 여러 곳에서 활용 가능
유지보수성클래스 기반 관리로 리팩토링 용이
타입 안정성IDE 자동완성 지원
가독성복잡한 주석 완전 제거

배포 자동화

CI/CD 파이프라인에 포함:

# JSON 생성
php artisan openapi:generate --write-path storage/api-docs/api-docs.json

마치며

vyuldashev/laravel-openapi를 사용하면 복잡한 Swagger 주석 없이 우아하고 유지보수하기 쉬운 API 문서를 작성할 수 있습니다.

특히 다음 상황에서 진가가 드러납니다:

  • 같은 schema를 여러 곳에서 사용
  • API 엔드포인트가 많고 복잡
  • 팀 단위 협업에서 일관된 문서화 필요
  • 정기적인 API 스펙 업데이트 필요

모던 PHP의 Attributes와 객체지향 설계로 API 문서화를 재정의할 수 있습니다.

댓글