[Spring Rest Docs] API 문서화 도구

in_ho_·2023년 11월 12일
0
post-thumbnail

1. Spring Rest Docs, Swagger

  • 개발을 할 때 엔드포인트, 요청 방법, 응답 방법을 전달하는 방식에 이점을 얻기 위해 Spring Rest Docs와 Swagger라이브러리를 사용합니다.

  • Spring Rest Docs는 테스트 코드를 기반으로 문서화를 진행하기 때문에 코드를 수정하지 않아도 된다는 이점이 있습니다.

  • 또한 테스트 코드가 통과되어야만 문서화가 진행되므로 신뢰할 수 있는 문서입니다.

  • MSA 환경에서 두 라이브러리 중 어떤 방식으로 사용해도, 각자의 스프링 서버에 접근해서 확인해야 하기 때문에 원활하지 않을 수 있습니다.

  • MSA 환경에서 각 서버의 Spring Rest Docs를 추출하여 Swagger UI 서버로 보내 API 문서를 통합하는 방식을 사용할 것입니다.

2. restdocs-api-spec

  • Spring MSA 각 컴포넌트에 spring-rest-docs를 이용하여 API 문서화를 진행한 후, 통합적으로 API 문서를 관리하기 위한 라이브러리는 아래와 같습니다.

2-1. Gradle

2-2. Maven

3. 각 서버에 Spring Rest Docs 사용

  • 먼저 Spring Rest Docs를 사용하여 각 서버를 문서화하도록 하겠습니다.

3-1. Spring Rest Docs 의존성 추가

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.17'
    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
    id "org.asciidoctor.jvm.convert" version "3.3.2" /* spring-rest-docs 추가 */
}

group = '...'
version = '...'

java {
    sourceCompatibility = '17'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

ext {
    set('springCloudVersion', "2021.0.8")
    snippetsDir = file('build/generated-snippets')  /* spring-rest-docs 추가 */
}

asciidoctor {  /* spring-rest-docs 추가 */
    dependsOn test
    attributes 'snippets': snippetsDir
    inputs.dir snippetsDir
}

asciidoctor.doFirst {  /* spring-rest-docs 추가 */
    println("Delete present asciidoctor.")
    delete file('src/main/resources/static/docs')
}

bootJar {  /* spring-rest-docs 추가 */
    dependsOn asciidoctor
    copy {
        from "${asciidoctor.outputDir}"
        into 'src/main/resources/static/docs'
    }
}

dependencies {
    /* spring-data-jpa */ implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    /* spring-security */ implementation 'org.springframework.boot:spring-boot-starter-security'
    /* jwt */ implementation 'io.jsonwebtoken:jjwt:0.9.1'
    /* spring-validation */ implementation 'org.springframework.boot:spring-boot-starter-validation'
    /* spring-web */ implementation 'org.springframework.boot:spring-boot-starter-web'

    /* eureka-client */ implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'


    /* mariadb-client */ runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
    /* spring-configuration-processor */ annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    /* restdocs-mockmvc */ testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'  /* spring-rest-docs 추가 */
    /* spring-test */ testImplementation 'org.springframework.boot:spring-boot-starter-test'
    /* spring-security */ testImplementation 'org.springframework.security:spring-security-test'
    /* coolsms*/ implementation 'net.nurigo:javaSDK:2.2'

    /* lombok */
    annotationProcessor 'org.projectlombok:lombok'
    compileOnly 'org.projectlombok:lombok'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

tasks.named('test') {
    outputs.dir snippetsDir  /* spring-rest-docs 추가 */
    useJUnitPlatform()
}
  • 위의 코드에서 / spring-rest-docs 추가 /라는 주석을 사용한 부분을 추가하면 된다.

3-2. Spring Security 예외 설정

  • Spring Security를 사용하는 프로젝트라면 경로 예외를 해주어야 합니다.
.and()
.authorizeRequests()
.antMatchers("/docs/*).permitAll()

3-3. Test 코드 구현

@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestDocs
class CertificationControllerTest {

    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private ObjectMapper objectMapper;
    private final static Logger log = LoggerFactory.getLogger(CertificationControllerTest.class);

    @Test
    @DisplayName("Bean 주입 체크")
    void isCheckOfBean() {
        log.info("=====================================================");
        log.info("mockMvc Dependency Injection : {}", mockMvc);
        log.info("objectMapper Dependency Injection : {}", objectMapper);
        log.info("=====================================================");
    }

    @Test
    @DisplayName("유레카 서버 연결 확인")
    void connectedTest() throws Exception {
        Map<String, String> input = new HashMap<>();
        mockMvc.perform(RestDocumentationRequestBuilders.get("/certification/connected")
                        .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andDo(print())
                .andDo(document("connected-test",
//                        requestFields(),
                        responseFields(
                                fieldWithPath("isConnected").description("유레카 서버 연결 여부")
                        )
                ))
                .andExpect(jsonPath("$.isConnected").value(is(true)));
    }
}

3-5. adoc 파일 생성

  • src/docs/asciidoc 폴더 하위에 아래 파일을 생성한다.

3-5-1. connected.adoc

[[connected]]
== 유레카 서버 연결 여부
유레카 서버와 연결이 정상적으로 되고 있는지 여부를 확인한다.

====== 요청 형식
include::{snippets}/connected-test/http-request.adoc[]
// include::{snippets}/connected-test/request-fields.adoc[]
====== Request Body
include::{snippets}/connected-test/request-body.adoc[]
====== 응답 형식
include::{snippets}/connected-test/http-response.adoc[]
include::{snippets}/connected-test/response-fields.adoc[]
====== Response Body
include::{snippets}/connected-test/response-body.adoc[]
====== Try with curl
include::{snippets}/connected-test/curl-request.adoc[]

3-5-2. index.adoc

= RESTful Notes API Guide
:doctype: book
:icons: font
:source-highlighter: highlightjs
:toc: left
:toclevels: 4
:sectnums:
:sectlinks:
:sectanchors:

== My Api Docs
API 명세서 index.html이다. gradle예제
include::src/docs/asciidoc/connected.adoc[]

인텔리제이에서 에러를 보여주겠지만 신경 쓰지 말도록 하자

3-6. bootJar

  • Gradle 명령어인 bootJar를 사용하여 build하도록 한다.
  • 위와 같은 파일이 생성된 것을 확인할 수 있습니다.

3-7. 요청 학인

4. Spring Cloud Gateway 연결

  • 2에서 말한 openapi spec을 사용하여 Swagger UI 서버로 보내 API 문서를 통합하여 관리할 것입니다.

4-1. 의존성 추가

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

dependencies {
	...
    /* open-api spec */testImplementation 'com.epages:restdocs-api-spec-mockmvc:0.16.2'
}

4-2. 작성한 테스트 코드에서 Import문 수정

  • 기존의 MockMvcRestDocumentation.document를 MockMvcRestDocumentationWrapper.document로 수정
import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document;

TODO 후에 이어서 작성

Reference

https://velog.io/@suhongkim98/spring-REST-Docs%EB%A1%9C-API-%EB%AC%B8%EC%84%9C-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0

0개의 댓글