Spring Rest Docs 와 Swagger-UI 연동

Daniel·2023년 8월 3일
1

지난 포스트들의 결과로 Spring Rest Docs 를 적용하였다.
하지만...장점이 있으면 단점도 있는 법 테스트 중심의 API 문서화의 결과로 완성된 API 문서는 기존 계속 사용해왔던 Swagger-UI 처럼 사용자 친화적? 이지 않다.
필자의 개인적인 생각으로는 별로 이쁘지도 않고 API를 호출해 테스트도 할 수 없다.

그래서 위 두 기능을 합칠 순 없을까 하고 구글링을 하던 와중 많은 레퍼런스가 있어 적용해 보려한다.

Spring Rest Docs 로 작성된 문서를 Swagger-UI 가 읽을 수 있도록 해보자

build-gradle 설정하기

  • https://github.com/ePages-de/restdocs-api-spec

  • ePages-de/restdocs-api-spec : Spring Rest Docs 의 테스트코드를 활용해 OpenAPI(Swagger 3.0) 의 결과를 만들어주는 오픈소스 라이브러리 입니다.

  • Spring Rest Docs 의 스펙을 따라가기위해 "MockMvc, WebTestClient, RestAssured" 모두 지원한다고 합니다.

  • 기존의 adocs 문서를 만들기 위한 코드는 삭제 후 진행했습니다.

  • Spring Rest Docs 와 Swagger-UI 연동을 위한 코드만 집중해 작성했습니다.

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.6'
    id 'io.spring.dependency-management' version '1.1.0'
    id "org.asciidoctor.jvm.convert" version "3.3.2"
    id 'com.epages.restdocs-api-spec' version '0.17.1'
    id 'org.hidetake.swagger.generator' version '2.18.2'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
    asciidoctorExt
}

repositories {
    mavenCentral()
}

dependencies {
    
    ...
    
    
    //restdocs-api-spec 의존성 추가
    testImplementation 'com.epages:restdocs-api-spec-mockmvc:0.17.1'
    asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor'
    testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
    testImplementation 'com.squareup.okhttp3:mockwebserver'
   
   ...
   
}

openapi3 {
    server = "http://localhost"
    title = "카카오인증 관리자 서버 API 문서"
    description = "Spring REST Docs with SwaggerUI."
    version = "0.0.1"
    outputFileNamePrefix = 'open-api-3.0.1'
    format = 'json'

    // /static/docs/open-api-3.0.1.json 생성 → jar 파일만 배포할 예정이기에 build 에 출력
    outputDirectory = 'build/resources/main/static/docs'
}


// Task 및 설정 추가
// GenerateSwaggerUI 태스크가, openapi3 task 를 의존하도록 설정
tasks.withType(GenerateSwaggerUI).configureEach {
    dependsOn 'openapi3'

//    기존 파일 삭제했다가, build 에 출력한 json 정적파일 복사 (안해도 됨 → local 확인용)
    delete file('src/main/resources/static/docs/')
    copy {
        from "build/resources/main/static/docs"
        into "src/main/resources/static/docs/"

    }
}

// 테스트를 통해 생성된 snippets 출력 위치 정의
tasks.register("ext") {
    snippetsDir = file('build/generated-snippets')
}

tasks.named('test') {
    useJUnitPlatform()

    // test 스니펫 디렉터리를 출력으로 추가하도록 작업을 구성
    outputs.dir 'snippetsDir'
}

// 기존에 존재하던 docs 삭제
asciidoctor.doFirst {
    delete file('src/main/resources/static/docs')
}

// asciidoctor 작업을 구성
tasks.named("asciidoctor") {
    inputs.dir 'snippetsDir'
    configurations 'asciidoctorExt'
    dependsOn test
}


tasks.named("bootJar") {
    dependsOn asciidoctor
    from("${asciidoctor.outputDir}") {
        into 'static/docs'
    }
    dependsOn(':openapi3')
}

tasks.register('copyDocument', Copy) {
    dependsOn asciidoctor
    from file("$buildDir/docs/asciidoc")
    into file("src/main/resources/static/docs")
}

tasks.named("build") {
    dependsOn copyDocument
}

openapi3 설정

build-gradle 에 설정한 openapi3 설정에 대한 설명을 하고 넘어가겠습니다.
위 설정은 openapi3 로 openapi3 스펙을 만들때 필요한 부가정보들을 설정한 부분이며

openapi3 {
   server = "서버주소(API 호출 테스트 시 이 주소 사용)"
   title = "API 문서 제목"
   description = "API 문서 설명 부분"
   version = "API 문서 버전"
   outputFileNamePrefix = '결과로 나오게 될 fomat형식 파일의 접두사'
   format = 'API 문서 출력 포맷 (default: JSON)'

   // /static/docs/open-api-3.0.1.json 생성 → jar 파일만 배포할 예정이기에 build 에 출력
	outputDirectory = 'format형식으로 변환 된 파일을 저장 할 디렉토리 경로'
}

테스트 코드 변경

세세한 설정들이 몇개 있지만 변경을 최소화 하기 위해 패키지 설정만 바꿔주었다.

  • 기존
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
  • 변경
import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document;
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;

위와같이 변경 후 clean -> build 작업을 하게되면 위에 설정한 경로에 format형식의 파일이 생성된 걸 확인할 수 있을 것 이다.

Swagger-UI 적용하기

의존성을 추가해 적용해보자...!

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

의존성 설정 후 애플리케이션을 실행시켜 "http://localhost:8080/docs/swagger-ui/index.html" 로 접속해 기본 페이지가 렌더링 된다면 성공!

  • 버전 이슈가 좀 있는 것 같아 위 의존성으로 안될 시 implementation 'org.springdoc:springdoc-openapi-ui:1.7.0' 를 사용해보자

하지만 우린 만들어둔 파일이 있다...! 기본 페이지가 아닌 생성한 파일을 읽도록 설정해보자

Swagger default JSON 경로 수정

  • application.yaml 파일에서 간단한 설정을 할 수 있습니다.

  • swagger-ui.url : swagger-ui가 읽은 파일 경로

  • swagger-ui.path : swagger-ui 띄울 url 변경 → 이러면 "http://localhost:8080/docs/swagger" 를 통해 문서를 불러올 수 있습니다.

  • application.yml

springdoc:
    default-consumes-media-type: application/json;charset=UTF-8
    default-produces-media-type: application/json;charset=UTF-8
    swagger-ui:
        url: /docs/open-api-3.0.1.json
        path: /docs/swagger

기본적인 설정은 이제 끝났습니다.
위 설정까지 마친 후 url 접속 시 Spring Rest Docs 로 생성한 문서를 Swagger-UI 를 통해 볼 수 있게 됩니다.

정리

설정이 90% 인 것같은 느낌적인 느낌... 그래도 많이 설정하다보면 익숙해 지겠지...?
현업에서 진행하는 프로젝트에 적용시켜 보았지만 아직 뭔가 부족하다 좀 더 공부하자!

Reference

https://github.com/ePages-de/restdocs-api-spec
https://thalals.tistory.com/433
https://helloworld.kurly.com/blog/spring-rest-docs-guide/

profile
응애 나 애기 개발자

0개의 댓글