728x90

목차

     

    "API 문서 자동화를 사용하게 된 이야기"

    회사에서 open API 판매 사이트 구축 프로젝트를 하는 과정에서 동료 개발자가 Swagger UI를 세팅해서 사용하려던 흔적이 있어서 API 문서 자동화 라이브러리의 존재를 알게 되었다. 하지만 동료 개발자는 Swagger는 Java 코드에 어노테이션을 덕지덕지 붙이는 것이 가독성을 떨어트리고 작업량이 늘어난다는 이유로 사용하지 않았다.

    다른 회사에서는 Swagger를 어떻게 사용하는지 궁금해서 검색하다 Spring REST Docs에 존재를 알았다. 하지만 Swagger처럼 UI가 한눈에 들어오지 않았고 결국 둘을 통합하는 버전까지 찾게 되었다.

     

    1. Swagger와 REST docs 각각 세팅 방법

    통합버전을 사용하기 전에 Spring Docs와 Spring REST Docs의 장ㆍ단점을 경험하기위해 각각 사용해 보길 권한다.

    1) SpringDocs : Swagger UI

    https://jfbta.tistory.com/258

     

    [Swagger UI] Spring Boot API 문서 자동화 설정 및 사용 예제

    실무에서 협업을 할 때 API에 대한 문서를 요청받은 적이 있었다. 메모장에 필요한 것만 적어서 전달하였는데 Swagger에 존재를 알았다면 덜 고생했을 것이다. 지금이라도 적용해서 사용 중인 Swagge

    jfbta.tistory.com

    2) Spring REST Docs

    https://jfbta.tistory.com/260

     

    [Rest Docs] Spring Boot API 문서 자동화 설정

    목차 1. REST Docs란? REST API 문서 자동화 도구이다. 테스트 코드 기반으로 Docs를 고려해서 작성하면 자동으로 API문서를 작성해준다. 테스트 코드 기반이기 때문에 필수로 작성해야하며 테스트 코드

    jfbta.tistory.com

     

    2. Swagger와 REST Docs 통합 버전 설정

    Swagger와 Rest Docs 환경설정을 완료한 프로젝트를 깃허브 (https://github.com/Parkjinman/api-docs-auto)에 올려 두었다.

    1) 파일 생성

    통합 버전을 사용하기 위해서는 index.adoc 파일과 swagger-ui 파일이 필요하다.

    ① AsciiDoc 플러그인 설치

    먼저 adoc 파일을 작성하기 전 AsciiDoc플러그인을 설치한다.

    src/docs/asciidoc/index.adoc 파일을 생성 후 아래 내용을 작성해준다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    = 제목
     
    == 섹션 1
     
    이 섹션은 간단한 AsciiDoc 문서의 첫 번째 섹션입니다.
     
    === 하위 섹션 1.1
     
    이 섹션은 하위 섹션으로, 좀 더 구체적인 내용을 담고 있습니다.
     
    * 아이템 1
    * 아이템 2
     
    [목록]
    ----
    1. 순서가 있는 목록 아이템 1
    2. 순서가 있는 목록 아이템 2
    ----
     
    . 이미지 삽입
    image::image.jpg[제목]
     
    == 섹션 2
     
    두 번째 섹션은 다른 내용을 다루고 있습니다.
     
    === 코드 블록
     
    [source,java]
    ----
    public class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    ----
     
    cs

    플러그인을 설치했다면 작성한 내용을 브라우저에서 어떻게 보여주는지 미리 볼 수 있다.

    ② swagger-ui 파일을 프로젝트 루트('/') 경로에 Copy & Paste 한다.

     

    2) build.gradle 설정

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    plugins {
        id 'java'
        id 'org.springframework.boot' version '2.7.15'
        id 'io.spring.dependency-management' version '1.0.15.RELEASE'
    +    id "org.asciidoctor.jvm.convert" version "3.3.2"
    +   id "com.gorylenko.gradle-git-properties" version "2.4.1"
    +   id "com.epages.restdocs-api-spec" version "0.16.2"
    }
     
    group = 'intergration.auto'
    version = '0.0.1-SNAPSHOT'
     
    java {
        sourceCompatibility = '1.8'
    }
     
    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
    +    asciidoctorExt
    }
     
    repositories {
        mavenCentral()
    }
     
    + ext {
    +     set("snippetsDir", file("build/generated-snippets"))
    + }
     
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
        implementation 'org.springframework.boot:spring-boot-starter-web'
        implementation group: 'com.github.gavlyukovskiy', name: 'p6spy-spring-boot-starter', version: '1.8.0'
        implementation("p6spy:p6spy:3.9.1")
     
    +    implementation("org.springdoc:springdoc-openapi-ui:1.6.11")
    +   implementation("org.springdoc:springdoc-openapi-webmvc-core:1.6.11")
     
        compileOnly 'org.projectlombok:lombok'
        runtimeOnly 'org.postgresql:postgresql'
        annotationProcessor 'org.projectlombok:lombok'
     
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
    +    testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")
    +   testImplementation("com.epages:restdocs-api-spec:0.16.2")
    +   testImplementation("com.epages:restdocs-api-spec-mockmvc:0.16.2")
     
    +   asciidoctorExt("org.springframework.restdocs:spring-restdocs-asciidoctor")
    }
     
    tasks.named("test") {
    +   outputs.dir snippetsDir
        useJUnitPlatform()
    }
     
    + tasks.register("restDocsTest", Test) {
    +     outputs.dir snippetsDir
    +     useJUnitPlatform {
    +         includeTags("restDocs")
    +     }
     
    +     finalizedBy "asciidoctor"
    +     finalizedBy "openapi3"
    + }
     
    + tasks.named("asciidoctor") {
    +     dependsOn restDocsTest
     
    +     inputs.dir snippetsDir
    +     configurations "asciidoctorExt"
    +     baseDirFollowsSourceDir()
    + }
     
    + openapi3 {
    +     servers = [
    +             { url = 'http://localhost:9080' },
    +     ]
    +     title = 'spring-rest-docs-guide'
    +     description = 'Spring REST Docs 테스트 생성물 생성시 추가생성되는 OpenAPI 문서이용'
    +     version = "${project.version}"
    +     format = 'yaml'
    + }
     
    + tasks.register("apiBuild", GradleBuild) {
    +     tasks = ["clean""restDocsTest""build"]
    + }
     
    + springBoot {
    +     buildInfo()
    + }
     
    + gitProperties {
    +     dateFormat = "yyyy-MM-dd'T'HH:mm:ss.Zz"
    +     dateFormatTimeZone = "Asia/Seoul"
    +     failOnNoGitDirectory = false
    + }
     
    + bootJar {
    +     from("swagger-ui") {
    +         into "BOOT-INF/classes/static/swagger"
    +     }
    +     from("${asciidoctor.outputDir}") {
    +         into "BOOT-INF/classes/static/docs"
    +     }
    +     from("build/api-spec") {
    +         into "BOOT-INF/classes/static/swagger"
    +     }
     
    +     archiveFileName.set "application.jar"
    + }
     
    cs

     

    3. 통합 버전 사용 방법

    통합 버전을 사용하기 위해 가장 먼저 REST API를 만든 상황에서 테스트코드를 작성해야 한다.

    1) RestController API 샘플 코드

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    package intergration.auto.docs.controller;
     
    import intergration.auto.docs.support.ResponseUtils;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
     
    import javax.servlet.http.HttpServletRequest;
    import java.util.HashMap;
    import java.util.Map;
     
    @RestController
    public class Main {
        @GetMapping("/hello-world")
        public ResponseEntity<Map<String,Object>> helloWorld(
                HttpServletRequest httpServletRequest
        ) {
            Map <String,Object> responseMap = new HashMap<>();
            String message = "hello";
            String code = "ok";
            HttpStatus status = HttpStatus.OK;
     
            responseMap.put("header", ResponseUtils.setHeader(message, code, httpServletRequest));
            return new ResponseEntity<>(responseMap, status);
        }
    }
     
    cs

     

    2) MockMvc Test 샘플코드 작성

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    package intergration.auto.docs.controller;
     
    import com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper;
    import intergration.auto.docs.annotation.RestDocsTest;
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
    import org.springframework.http.MediaType;
    import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
    import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
    import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
     
    @DisplayName("메인 API")
    @WebMvcTest({Main.class})
    @RestDocsTest
    class MainTest {
        @Autowired
        private MockMvc mockMvc;
     
        @Test
        void testMain() throws Exception {
            this.mockMvc.perform(RestDocumentationRequestBuilders.get("/hello-world")
                                .contentType(MediaType.APPLICATION_JSON)
                    )
                    .andDo(MockMvcResultHandlers.print())
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    //REST Docs 용
                    .andDo(MockMvcRestDocumentation.document("version-1"))
                    //OAS 3.0 - Swagger
                    .andDo(MockMvcRestDocumentationWrapper.document("version-2"));
        }
     
    }
    cs

     

    4. 설치 및 확인

    아래 과정을 따라 하기.

    1) 설치 버전

    Java: JDK 1.8.0_281
    Spring Boot: 2.7.15
    Gradle: 7.4.2
    Gradle 8 이상 호환 안됨.
    RestDoc: 0.16.2
    0.17 버전은 java 1.8에서 호환 안됨.
    SpringDoc: 1.6.11

     

    2) 설치 과정

    ① 프로젝트 구성하기(Reload All Gradle Projects)
    ./gradlew clean build

    ② API문서생성
    ./gradlew clean restDocsTest

    ③ 생성문서 확인
     - Spring REST Docs: build/docs/asciidoc/index.html
     - Swagger UI: api-spec/openapi3.yaml

    ④ application.jar 파일 생성
    ./gradlew apiBuild

    ⑤ application.jar 파일 위치로 이동
    cd build/libs

    ⑥ application.jar 파일 실행( * 터미널 관리자 권한 실행 )
    java -jar application.jar

     

    설치 확인

    Spring REST Docs
    http://localhost:9080/docs/index.html

    Spring REST Docs - OpenAPI Specification Integration
    http://localhost:9080/swagger/swagger-ui.html

    Springdoc Swagger-UI
    http://localhost:9080/swagger-ui/index.html

    728x90
    TOP