RestAssured + RestDocs 문서화

nuyh99·2023년 8월 31일
0

배경

프론트엔드와 노션의 API 명세를 통해 협업하고 있었습니다.
어느날 백엔드측에서 API를 수정하고 노션의 명세를 최신화하지 않았습니다.

그 결과…
프론트엔드 극대노

따라서 신뢰도 있는 API 문서화가 필요했습니다.

  1. Swagger
  2. RestDocs
  3. Springdoc

위의 선택지들이 있었고, 저희는 2번을 선택하기로 했습니다.
이유는 테스트 코드가 아닌 프로덕션 코드에 어노테이션을 붙이기 싫었기 때문입니다.

하지만 RestDocs로 만든 adoc, AsciiDocter로 만든 html 파일은 정말 못생겼습니다.

Swagger UI 등의 예쁜 문서화를 위해서는 OAS 규격을 따르는 yaml 파일이 필요했고, 저희는 RestDocs-Api-Spec 이라는 오픈 소스를 사용하기로 결정했습니다.

지금부터 간단하게 문서화를 시작해보겠습니다!!
예시 환경은 JDK17, Spring Boot 3.1.2 버전입니다.

문서화할 API

@PostMapping("/members")
public ResponseEntity<MemberResponse> create(@RequestBody final MemberRequest memberRequest) {
    MemberResponse saved = memberService.save(memberRequest);
    
    return ResponseEntity.ok(saved);
}

단순히 Member 엔티티를 생성하고 그 결과를 응답하는 API 입니다.

Request

단순히 바디에 name을 보냅니다.

Response

생성된 자원을 응답합니다.

RestAssured Test

@Test
@DisplayName("Member 생성 테스트")
void save() {
    MemberRequest request = new MemberRequest("연어");

    given().log().all()
            .contentType(ContentType.JSON)
            .body(request)
            .when()
            .post("/members")
            .then().log().all()
            .statusCode(200);
}

위와 같이 간단한 테스트를 작성했습니다.

RestDocs + OAS 적용

Spring REST Docs공식 깃허브를 보면서 따라해보겠습니다.

plugins {
    id 'com.epages.restdocs-api-spec' version '0.18.2'
}

우선 build.gradle의 플러그인 목록에 추가합니다.

testImplementation 'com.epages:restdocs-api-spec-mockmvc:0.18.2'
testImplementation 'com.epages:restdocs-api-spec-restassured:0.18.2'
testImplementation 'org.springframework.restdocs:spring-restdocs-restassured'

저희는 RestAssured로 테스트를 작성할 것이므로 위의 의존성을 추가합니다.
RestAssured를 쓰는데 MockMvc는 왜 추가하냐구요?
저게 없으면 나중에 문서화를 하기 위한 RestAssuredRestDocumentationWrapper 클래스를 사용할 수가 없습니다.

만약 MockMvc를 사용한다면

testImplementation 'com.epages:restdocs-api-spec-mockmvc:0.18.2'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'

이런 식으로 변경합니다.

openapi3 {
    server = 'https://localhost:8080'
    title = '간단한 API'
    description = '회원 저장 API 입니다.'
    version = '0.1.0'
    format = 'yaml'
}

그리고 위처럼 openapi3 라는 작업을 추가합니다.
./gradlew openapi3를 통해 문서화를 하기 위함입니다.

tasks.named('test') {
    outputs.dir file('build/generated-snippets')
    useJUnitPlatform()
}

마지막으로 기존의 test 작업에 위와 같이 outputs.dir을 추가해줍니다.
해당 디렉토리에 adoc 파일들을 생성한다는 뜻입니다.

이제 기존의 RestAssured 테스트를 고쳐봅시다.

@ExtendWith(RestDocumentationExtension.class)
class MemberControllerTest{

RestDocs를 사용해야 하므로 @ExtendWith를 붙여줍니다.

private RequestSpecification spec;

@BeforeEach
void setUp(RestDocumentationContextProvider provider) {
    this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(provider))
            .build();
    RestAssured.port = port;
}

필드에 RequestSpecification을 참조해주고, @BeforeEach에서 provider를 주입 받아서 스펙을 생성해줍니다.
코드를 보면 아시겠지만, RestDocs는 필터를 사용해서 문서화를 하는 방식으로 동작합니다.

@Test
@DisplayName("Member 생성 테스트")
void save() {
    MemberRequest request = new MemberRequest("연어");

    given(spec).log().all()
            .filter(RestAssuredRestDocumentationWrapper.document(
                    "멤버 저장 API"
            ))
            .contentType(ContentType.JSON)
            .body(request)
            .when()
            .post("/members")
            .then().log().all()
            .statusCode(200);
}

위와 같이 기존 테스트에 filter() 항목을 추가해주고 돌리면 adoc 파일로 만들어지게 됩니다.
요청 파라미터, 응답 파라미터에 대한 설명도 추가해볼까요??

@Test
@DisplayName("Member 생성 테스트")
void save() {
    MemberRequest request = new MemberRequest("연어");

    given(spec).log().all()
            .filter(document(
                    "멤버 저장 API",
                    requestFields(
                            fieldWithPath("name").description("이름")),
                    responseFields(
                            fieldWithPath("id").description("회원 PK"),
                            fieldWithPath("name").description("이름")
                    )
            ))
            .contentType(ContentType.JSON)
            .body(request)
            .when()
            .post("/members")
            .then().log().all()
            .statusCode(200);
}

위와 같이 수정하고 테스트를 돌려봅니다.

adoc 파일들이 잘 생성된 것을 확인할 수 있습니다.
이제 남은 것은 이 파일들로 OAS 명세를 따르는 yaml 파일을 만드는 것입니다.

OAS yaml 파일 만들기

위에서 build.gradle에 추가해줬던 openapi3 기억하시나요?
RestAssured와 RestDocs로 만든 adoc 문서들로 OAS 3.0 스펙을 따르는 yaml 파일을 만들어봅시다.

단순히 프로젝트 디렉토리에서 ./gradlew openapi3를 실행시켜보면,

이런 식으로 yaml 파일이 만들어졌습니다!!

이 파일만 있다면 OAS를 따르는 어떤 UI로도 HTML의 형태로 서빙할 수 있습니다.

실제 저희 요즘카페 프로젝트의 API 문서입니다.
StopLight라는 OAS 툴을 사용해서 위와 같이 YAML -> HTML 형태로 제공하고 있습니다.

끝!!!!!!!!!!!!

profile
渽晛

0개의 댓글