본문 바로가기
노트/F-lab

Spring REST Docs를 선택한 이유

by soro.k 2023. 4. 8.

들어가기 전에

이번 프로젝트에서는 API 문서 자동화를 위해 Spring Restdocs를 선택했다. Swagger와 Spring REST Docs를 두고 고민했었는데 둘의 차이점은 무엇이고 왜 REST Docs를 선택했는지 기록하고자 한다.

 

Spring REST Docs vs. Swagger

Spring REST Docs Swagger
테스트 코드에 적용한다. Controller/DTO 코드에 적용한다.
테스트 기능은 제공하지 않는다. 문서를 통해 테스트할 수 있다.
문법에 따라 자유롭게 문서를 만들 수 있다. 스타일 가이드라인에 따라 문서를 만들 수 있다.

 

Spring REST Docs

1. 테스트 코드에 적용한다.

테스트 클래스에 REST Docs를 사용할 수 있도록 설정한 후에 아래처럼 작성하면 API 문서를 만들 수 있다.

@Test
@DisplayName("조건에 맞는 모든 필드를 입력받으면 회원가입이 성공한다.")
void when_allFieldsAreEntered_expect_joinToSuccess() throws Exception {
    JoinRequest joinRequest = new JoinRequest(EMAIL, PASSWORD, NAME, ROLE);
    JoinResponse joinResponse = new JoinResponse(EMAIL, NAME, ROLE, ActiveType.ACTIVE);

    given(memberService.join(any())).willReturn(joinResponse);

    ResultActions response = mockMvc.perform(post("/api/v1/members/join")
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsBytes(joinRequest))
        )
        .andDo(print())
        .andDo(document("member-join",
            preprocessRequest(modifyUris()
                .port(9090), prettyPrint()),
            preprocessResponse(prettyPrint()),
            requestFields(
                fieldWithPath("email").type(JsonFieldType.STRING).description("이메일"),
                fieldWithPath("password").type(JsonFieldType.STRING)
                    .description("비밀번호(8자~16자 이하의 영문 대소문자/숫자/특수문자 조합)"),
                fieldWithPath("name").type(JsonFieldType.STRING).description("이름"),
                fieldWithPath("role").type(JsonFieldType.STRING).description("에프랩 내에서의 역할(COACH|MENTEE)")
            ),
            responseFields(
                fieldWithPath("email").type(JsonFieldType.STRING).description("가입된 이메일 정보"),
                fieldWithPath("name").type(JsonFieldType.STRING).description("가입된 이름 정보"),
                fieldWithPath("role").type(JsonFieldType.STRING).description("가입된 역할 정보"),
                fieldWithPath("activeType").type(JsonFieldType.STRING).description("가입된 계정 활성화 정보")
            )));

    response.andExpect(status().isOk());
}

 

2. 테스트 기능은 제공하지 않는다.

생성된 API 문서에서는 Swagger와 달리 테스트를 할 수는 없지만 아래처럼 문서 자체에 초점이 맞춰진 화면을 확인할 수 있다.

 

3. 문법에 따라 자유롭게 문서를 만들 수 있다.

AsciiDocs 문법을 참고해서 자유로운 형식으로 문서를 만들 수 있다. 

ifndef::snippets[]
:snippets: ./build/generated-snippets
endif::[]
= Application Docs
:doctype: book
:icons: font
:source-highlighter: highlightjs
:toc: left
:toclevels: 4
:sectlinks:

== Member API

=== 1. 회원가입

**request_fields**

include::{snippets}/member-join/request-fields.adoc[]

**response_fields**

include::{snippets}/member-join/response-fields.adoc[]

**http_request**

include::{snippets}/member-join/request-body.adoc[]

**http_response**

include::{snippets}/member-join/http-response.adoc[]

---

 

Swagger

1. Controller/DTO 코드에 적용한다.

아래 코드를 보면 Swagger의 어노테이션을 사용해서 문서화를 하는 코드를 확인할 수 있다.

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
@Api(tags = {"01. User API"})
public class UserController {

    private final UserService userService;

    @PostMapping("/create")
    @ApiOperation(value = "회원 등록")
    public ResponseEntity<Void> createUser(@Valid @RequestPart SaveRequest requestDto,
                                           @RequestPart MultipartFile profileImage) {
        userService.save(requestDto, profileImage);

        return CREATED;
    }
}
// nested class
public static class UpdateRequest {

  @ApiParam(value = "글 제목", required = true)
  @NotBlank(message = "제목을 입력해 주세요.")
  private String title;

  @ApiParam(value = "글 내용", required = true)
  @NotBlank(message = "내용을 입력해 주세요.")
  private String content;

  @ApiParam(value = "게시글 이미지 리스트")
  private List<MultipartFile> multipartFiles;

}

 

 

2. 문서를 통해 테스트할 수 있다.

문서를 보면 Try it out이라는 테스트 기능이 제공된다. 

 

버튼을 누르고 파라미터를 입력하면 응답 객체를 확인할 수 있다.

 

3. 스타일 가이드라인에 따라 문서를 만들 수 있다.

Swagger에서는 REST Docs처럼 따로 형식을 바꿀 수 있는 게 아니라 형식은 정해져있고 어노테이션을 사용해서 값을 채워주는 식으로 사용할 수 있다.

 

 

REST Docs를 선택한 이유

사실 이전 프로젝트에서 Swagger를 선택했었다. 테스트 할 수 있는 기능이 있기도 했지만 가장 주된 이유는 익숙하지 않은 테스트 코드를 통해서 문서화를 한다는 게 부담이 되었기 때문이다. 그런데 프론트엔드 개발자 분들과 협업했어야 됐기 때문에 문서화 작업을 나중으로 미룰 수가 없었고 우리가 빠르게 적용할 수 있는 도구를 선택해야 했다. 더불어서 개인적으로 API를 더 명확하게 보여준다고 생각한 Swagger를 선택해서 사용했다. 

 

반대로 이번 프로젝트에서 REST Docs를 선택할 수 있었던 것은 테스트 코드에 있다. 이번 프로젝트에서는 테스트 코드를 제대로 작성하는 방법을 배우고 익숙하게 작성할 수 있도록 습관을 들이고 싶었는데 그렇게 목표를 설정하고 나니까 정말로 두 가지의 선택지를 가질 수 있었다. 이미 Swagger는 경험을 해봤으니 이번에는 REST Docs를 선택해서 기존 코드의 가독성을 더 높이고 테스트 코드를 활용해서 문서화 작업을 하기로 했다. 

 

 

 

마무리

이 글을 작성하면서 또 한번 문서화에 대한 중요성을 느꼈다. 그때 협업했던 개발자 분들이 모두 Swagger를 사용해보지 않으셔서 이해하시는 데 도움이 되시라고 문서화를 해놨었는데 그때 남겨뒀던 스크린샷들을 이 글에 활용할 수 있었다. 지금은 노션에만 간단히 정리해놨는데 조만간 REST Docs 설정에 관련된 글을 작성해야겠다.

 

 

 

'노트 > F-lab' 카테고리의 다른 글

Github Actions: CI/CD 구축 (feat.shell script) - 준비편  (0) 2023.06.04
NCP 서버 생성부터 ssh 접속까지  (2) 2023.05.29
Lombok을 사용하지 말라고?  (1) 2023.03.25
개발 스펙 정하기  (0) 2023.03.20
F-lab 8주차  (0) 2023.03.10