Spring REST Docs + ɑ 도입기

 

- 부제 : 테스트를 통과하면 문서가 생성되는 서비스가 있다?! -

 

들어가며

이 글에서는 Spring REST Docs, openapi3, swaggerUI를 다룰 것이다.

각각에 대해 자세히 다루지는 않겠지만, 세 가지의 서비스를 한번에 적용하는 글이 많지 않아 직접 정리해볼 생각이다.

 

왜 Spring REST Docs일까?

swagger

Documentation, 하면 swagger를 떠올리는 사람들이 많을 것 같다.

첫 프로젝트를 할 때에는 그것조차 몰라서 google spread sheet로 API 명세서를 정리하곤 했다.

그러다 API 테스트까지 해볼 수 있는 툴(이게 swagger였다.)이 있다는 걸 알게 됐지만, 사용하고 싶지는 않았다.

 

annotations

컨트롤러에 많은 annotation을 붙여야 했기 때문인데,

문서화를 위해 소스코드에 무언가를 추가한다는 게 싫었다.

@ApiOperation(value = "", notes = "")
@ApiResponses({
    @ApiResponse(code = 200, message = "OK"),
    @ApiResponse(code = 500, message = "INTERNAL SERVER ERROR"),
    @ApiResponse(code = 404, message = "NOT FOUND")
})
@PostMapping("/board")
public Response writeBoard() {
// ...
}

이 경우만 봐도, 200, 500, 404 세 가지 케이스를 기술하기 위해

컨트롤러에 로직 실행과는 관련없는 annotation이 다섯 줄이나 붙었다. (line 2-6)

하나의 컨트롤러 클래스에 메서드가 한 개라면 그럭저럭 괜찮겠지만, CRUD를 위한 4개의 메서드가 있다면?

Operation annotation은 제외하더라도 4X5, 20줄의 annotation 뭉텅이가 있는 것이다.

 

예쁜 IDE, 특히 깔끔한 코드를 좋아하는 나로서는 다른 방법을 찾을 수 밖에 없었다.

하지만 swagger를 사용하면 클라이언트 개발자 분들이 포스트맨으로 테스트하지 않고,

API 문서 내에서 테스트해 볼 수 있다는 장점이 있었는데...

 

Spring REST Docs?

어쩌다 보게 됐는지 기억은 잘 나지 않지만 21년 10월 쯤 이 글을 봤다. (https://techblog.woowahan.com/2597/)

북마크 해두고 프로젝트에 꼭 적용해봐야지 싶었는데, 두 번째로 적용해보면서 이제 감을 좀 잡았다.

 

Spring REST Docs는 테스트 코드를 작성할 때 documentation을 같이 하면 문서를 생성해주는 툴이다.

장점은 테스트를 통과해야 문서가 생성된다는 점이고, 단점은 진입장벽이 느껴진다는 것이다.

하지만 위 링크에 있는 swagger, Spring REST Docs 비교표를 보면 알 수 있듯,

'제품코드에 영향이 없다'는 것은 내게 엄청난 장점이었다.

 

테스트를 못하잖아...

다른 사람들은 어떤지 모르지만 Spring REST Docs로 작성한 문서가 내 눈에는 정말 예뻤는데,

그래도 클라이언트에서 API 동작을 직접 테스트해볼 수 없다는 문제는 여전히 남아있었다.

또 열심히 찾다가 이 글을 보게 됐다. (https://blog.jdriven.com/2021/10/generate-swagger-ui-from-spring-rest-docs/)

 

OpenAPI Spec

자 정리하면, 과정은 다음과 같다.

Spring REST Docs로 문서 작성 - OpenAPI Spec으로 변경 - SwaggerUI 적용된 것과 같은 문서 확인

 

이게 어떻게 가능한지 살펴볼까?

 

(나처럼) 테스트코드를 통한 문서화에는 찬성하지만 더 예쁘게 또 테스트가 가능하도록 문서를 만들고 싶은 사람이 있었는데,

그 사람이 만든 게 Spring REST Docs로 작성한 파일을 OpenAPI 스펙으로 바꿔주는 것!

그리고 그렇게 작성된 OpenAPI 파일을 띄워 실행할 수 있는 게 Swagger라는 것이다.

 

이제 왜 필요한지, 어떻게 여기까지 오게 되었는지 알았으니 한번 적용해볼까?

 

적용하는 방법

build.gradle - 플러그인 추가

plugins {
    id 'org.asciidoctor.convert' version '1.5.8'         // (1)
    id 'com.epages.restdocs-api-spec' version '0.11.3'   // (2)
    id 'org.hidetake.swagger.generator' version '2.18.2' // (3)
}

(Groovy가 없어 java로 표시되었지만, 이건 build.gradle 파일이다)

(1) Spring REST Docs 적용을 위해 필요하다.

(2) Spring REST Docs 문서를 OpenAPI 스펙으로 변경하기 위해 필요하다.

(3) swagger처럼 보이도록 변경하기 위해 필요하다.

 

build.gradle - 의존성 추가

dependencies {
    testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' // (1)
    testImplementation 'com.epages:restdocs-api-spec-mockmvc:0.11.3'          // (2)
    asciidoctor 'org.springframework.restdocs:spring-restdocs-asciidoctor'    // (3)
    testImplementation 'org.assertj:assertj-core:3.21.0'                      // (4)
}

(1), (3) Spring REST Docs 적용을 위해 필요하다.

(2) Spring REST Docs 문서를 OpenAPI 스펙으로 변경하기 위해 필요하다.

(4) 이 글과는 큰 관련이 없지만 테스트를 위해 추가했다.

 

build.gradle - openapi3

openapi3 {
    server = 'http://localhost:8080'
    title = '(여러분의 서비스 이름) API'
    description = '(여러분의 서비스 이름) API description'
    version = '0.1.0'
    format = 'yaml'

    copy{
        from "build/api-spec"
        into "src/main/resources/static/docs"
    }
}

OpenAPI 스펙으로의 변경 및 문서 저장을 위한 부분이다.

 

- server : 주소

- title : 문서 이름

- description : 설명

- version : 버전

- format : openapi3.yaml 파일을 생성할 것이므로 'yaml'로 작성한다.

- copy 

: openapi3.yaml 파일은 build/api-spec 경로에 생성되는데, 이것을 src/main/resources/static/docs 경로에 복사한다.

: resources/static 경로에 있는 파일들은 자원이므로 바로 접근 가능하기 때문이다.

 

build.gradle - swaggerSource

swaggerSources {
    register("(여러분의 서비스 이름)").configure {
        setInputFile(file("${project.buildDir}/api-spec/openapi3.yaml"))
    }
}

- register("____")의 ____

: swaggerUI를 만들 때 사용할 폴더 이름 ('swagger-ui-여러분의 서비스 이름' 이렇게 폴더 이름이 지정된다.)

- setInputFile()

: openapi3.yaml 파일을 바탕으로 swaggerUI를 작성해야 하므로 InputFile을 openapi3.yaml 파일로 지정한다.

 

build.gradle - bootJar

bootJar {
    dependsOn asciidoctor

    copy{
        from "build/asciidoc/html5"
        into "src/main/resources/static/docs"
    }

    copy{
        from "build/swagger-ui-(여러분의 서비스 이름)/"
        into "src/main/resources/static/api/"
    }
}

jar 파일에 문서를 포함하기 위한 설정이며 빌드 시 실행된다.

- asciidoctor 과정이 진행된 후에 static/docs로 파일을 복사하고,

- 생성된 swagger-ui-() 폴더 하위의 내용을 src/main/resources/static/api/ 경로로 복사한다. (필요에 따라 수정 가능)

 

이렇게 하면 Spring REST Docs, OpenAPI spec, SwaggerUI를 적용하기 위한 기본 설정은 끝났다.

다음은 테스트 코드를 작성하며 문서화를 위한 코드도 같이 작성하는 건데, 다음 글에서 이어가보겠다.

 

마치며

기본 설정만 끝났을 뿐! 문서는 보지도 못했다.

이렇게 정리된 글을 찾기 어려워 직접 정리해보았는데, 이 글을 통해 많은 사람들이 편리하게 문서화했으면 좋겠다.

 

1) 테스트가 성공해야 문서가 생성된다.

2) 예쁜 문서를 얻을 수 있다.

3) 클라이언트에서 테스트할 수 있다.

 

이 세 가지 장점을 모두 가진 세 툴의 조합이 좋아서 사랑스럽기까지 하다.

다음 글에서 테스트를 통해 어떤 과정으로 문서가 생성되는지, 생성된 문서는 어떤 모습인지 확인해보기로 하자.

'Spring' 카테고리의 다른 글

테스트코드의 필요성  (0) 2022.05.09
@Transactional과 프록시  (0) 2022.03.20