IAS - Swagger를 사용한 API 명세서 작성

IKNOW·2024년 3월 5일
0

See space

목록 보기
7/9

이전 프로젝트까지는 문서화를 Notion을 사용해 아래와 같은 방식으로 진행했습니다.

노션은 굉장히 깔끔하고, 텍스트나 이미지, 링크, 코드 스니펫등의 다양한 형식으로 작성할수 있으며, 네트워크로 공유가 간단하기 때문에 협업에 용이하다는 장점이 있습니다.

다만 저는 API변경시 수동으로 문서를 업데이트 해야하기 때문에 개발시 깜빡 할 수 있다는 단점이 너무 크게 다가와서 문서화 솔루션을 변경하기로 하였습니다.

먼저 고려된 솔루션은 Spring Rest Docs입니다.

Spring Rest Docs는 테스트 기반의 API 문서화 도구이며, 실제 테스트 코드를 기반으로 문서를 생성하기 때문에 API 문서와 코드 사이의 불일치를 최소화 할 수 있다는 장점이 있습니다.

다만, 현재 프로젝트는 Fast API 와 Node.js를 포함한 MSA로 설계하였기 때문에 API 문서가 분산되는 것은 바람직 하지 않다고 여겨져서 적용하지 못했습니다. (써보고 싶은 마음이 있기 때문에, 현재 시작하는 팀 프로젝트에선 Spring Rest Docs를 사용해 문서를 작성하자고 제안해 두었습니다.)

다음으로는 실제로 프로젝트에 적용한 Swagger입니다.

가장 널리 사용되는 문서화 도구이며, 자동으로 API 문서를 생성하고, 다양한 언어/ 프레임워크를 지원한다는 장점이 있습니다.
다만, 세부적인 설명이나 복잡한 구조를 표현하기 까다롭다는 단점이 있으며, 어노테이션 기반으로 작동하기 때문에 코드 가독성이 떨어진다는 단점이 있습니다.

아래에서는 실제로 제가 적용한 설정을 기반으로 설명하겠습니다.

설정

build.gradle - 의존성을 추가합니다.

implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'

api-docs에 대한 경로를 설정하고, swagger-ui를 false로 설정합니다.

springdoc:
  api-docs:
    path: /account/api-docs
  swagger-ui:
    enabled: false

저는 MSA 로 프로젝트를 설계하였기 때문에 스프링에서 swagger를 사용하는게 아닌, Swagger-ui를 docker로 올리고 거기서 각 서비스로 api 명세를 요청할 예정이기 때문에 swagger-ui를 false로 설정하였습니다.

만약 모놀리식 애플리케이션으로 프로젝트를 설계하였다면, 따로 Swagger-ui를 설정하지 않는 것이 관리에 있어서 편할 것 같습니다.

//DocsConfig.java
@Configuration
@OpenAPIDefinition
@RequiredArgsConstructor
public class DocsConfig {

    @Bean
    public OpenAPI openAPI() {
        OpenAPI openAPI = new OpenAPI();
        openAPI.info(new Info().title("Authentication Server").description("Account 도메인과 인증을 담당하는 서버입니다.").version("1.0"));

        openAPI.setComponents(new Components());
        return openAPI;
    }
}

Configuration을 통해 간단한 설정을 설정해 줍니다.

여기까지 하면 매우 간단한 설정만으로 Swagger를 설정을 끝낼 수 있습니다.

다음으로는 swagger-ui docker를 올려야 합니다.

version: "3.7"
services:
  swagger:
    image: swaggerapi/swagger-ui
    container_name: swg-ss-container
    ports:
      - "9018:8080"
    environment:
      - URLS_PRIMATY_NAME=agent
      - "URLS=[{ url: 'http://localhost:7777/account/api-docs', name: 'authentication-server' }]"
      - SUPPORTED_SUBMIT_METHODS=['GET']
    volumes:
      - ./docs:/usr/share/nginx/html/docs

docker-compose up 을 사용하면 쉽게 swagger-ui를 docker로 실행할 수 있으며, 할당한 포트를 통해
api 명세를 확인 할 수 있습니다.

요청 응답 정의

swagger는 요청받는 클래스, 응답 받는 클래스를 기준으로 api명세를 적어주기 때문에 실제 요청/응답으로 설정된 자바 클래스와 실제 필요한 데이터가 다른경우 api명세를 명확히 파악하기 힘들어집니다.

예시로 회원가입의 경우 email과 passward 정보만 받으면 가입 할수 있지만 저는 AccountDTO 형태로 요청을 받도록 작성하였기 때문에 실제 요청에 필요 없는 AccountDTO 정보가 노출됩니다.

그래서 저는 요청과 응답 스키마를 정의하고 해당 스키마를 swagger 에 등록하였습니다.

예시로 요청 스키마는 다음과 같이 정의 하였습니다.

@Component
@Getter
@RequiredArgsConstructor
public class AccountRequest {

    public Schema JoinAccount() {
        Schema request = new Schema<Map<String, Object>>()
                .type("object")
                .contentMediaType("application/json")
                .name("join request")
                .addProperty("email", new StringSchema().example("test@gmail.com"))
                .addProperty("password", new StringSchema().example("P4SSW0RD"));
        request.setRequired(List.of("email", "password"));

        openAPI.getComponents().addSchemas("JoinAccountRequest", request);
        return request;
    }
}

email과 password로 명시하였으며, 필수요소라고 지정하였습니다.

이렇게 지정한 이후 컨트롤러에 어노테이션으로 스키마를 설정해야 합니다.

    @Operation(summary = "회원 가입", description = "회원 가입을 수행합니다.")
    @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(ref = "JoinAccountRequest")))
    @ApiResponses(value = {
            @ApiResponse(responseCode = "201", description = "회원 가입 성공", content = @Content(mediaType = "application/json", schema = @Schema(ref = "joinSuccessResponse"))),
            @ApiResponse(responseCode = "400", description = "이메일 형식 오류", content = @Content(mediaType = "application/json", schema = @Schema(ref = "invalidEmailResponse"))),
            @ApiResponse(responseCode = "409", description = "이메일 중복", content = @Content(mediaType = "application/json", schema = @Schema(ref = "emailDuplicatedResponse")))
    })
    @PostMapping("/join")
    public ResponseEntity<MessageResponseBody> join(@RequestBody LocalAccountDTO request) {
        accountService.createAccount(request);
        return ResponseEntity.created(URI.create("/account/login")).body(new MessageResponseBody("회원 가입 성공.", "success"));
    }

Response는 위와 같이 ApiResponse를 사용해 스키마를 설정해 주면 됩니다.

요청 스키마가 제대로 설정된 것을 확인 할 수 있습니다.

오늘은 이렇게 api명세를 작성하기 위한 용도의 swagger를 설정하고, 스키마를 정의하여 사용해 봤습니다.

노션과 비교해서 사용해본 결과,
api가 자동 생성된다는 점 best,
한 곳에서 확인 할수 있다는 점 good,
ui설정 필요없이 미려하다는 점 good.

다양한 형식(로직을 설명할 수 있는 이미지, mermaid 다이어 그램등.)을 지원하지 않는다 bad.
프로덕션 코드에 문서화에 필요한 코드가 첨부된다 worst.

정도로 정리 할 수 있었습니다.

profile
조금씩,하지만,자주

0개의 댓글

관련 채용 정보