반응형
간단한 Rest Docs 작성 예시
- [build.graddle.kt]
plugin {
id("com.epages.restdocs-api-spec") version "0.17.1"
}
configure<com.epages.restdocs.apispec.gradle.OpenApi3Extension> {
setServer("http://localhost:9999")
title = "Rest API 문서"
description = "Rest API 문서"
version = "0.1.0"
format = "yaml"
outputDirectory = "build/docs"
outputFileNamePrefix = "rest_docs"
}
val asciidoctorExtensions: Configuration by configurations.creating
dependencies {
testImplementation("com.epages:restdocs-api-spec-mockmvc:0.17.1")
}
- [공통 Rest Docs setup 클래스]: 컨트롤러 테스트에서 Docs 관련 객체 생성 코드를 빼 준다.
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.extension.Extensions
import org.mockito.junit.jupiter.MockitoExtension
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.restdocs.RestDocumentationExtension
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.result.MockMvcResultHandlers
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder
import org.springframework.web.filter.CharacterEncodingFilter
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Extensions(
ExtendWith(RestDocumentationExtension::class),
ExtendWith(MockitoExtension::class)
)
@AutoConfigureRestDocs
abstract class RestDocsConfigurer: {
protected lateinit var mockMvc: MockMvc
fun <T> setUp(controller: T, restDocumentProvider: RestDocumentationContextProvider) {
this.mockMvc = MockMvcBuilders.standaloneSetup(controller)
.apply<StandaloneMockMvcBuilder>(MockMvcRestDocumentation.documentationConfiguration(restDocumentProvider))
.alwaysDo<StandaloneMockMvcBuilder>(MockMvcResultHandlers.print())
.addFilter<StandaloneMockMvcBuilder>(CharacterEncodingFilter("UTF-8", true))
.build()
}
}
- 테스트 코드 작성
class CommonControllerUnitTest: RestDocsConfigurer() {
...
@BeforeEach
fun init(restDocumentationContextProvider: RestDocumentationContextProvider) {
super.setUp(CommonController(commonService), restDocumentationContextProvider)
}
@Test
fun `테스트 코드 메서드 시그니처`() {
...
}
}
기존 방식의 문제점
- 서버마다 API 스펙이 다르다.
- 서버마다 Swagger UI를 띄우기 때문에 한 곳에서 관리하는 방법이 필요하다.
- 특히 MSA 환경에서 이러한 문서 관리 자동화가 필요하다.
개선 방법
Rest Docs로 만들어진 yaml 파일은 Swagger UI에서 사용 가능한 점을 확인
Rest Docs는 빌드 시, 관리 파일(yaml)을 사용하여 Docker로 Swagger UI를 만들어주도록 했다.
- ./gradlew openpai3 로 실행 시, 다음과 같이 생성되는 yaml 파일 주시
- Swagger UI를 띄울 때, 환경 변수로 rest docs yaml파일(복수 입력 가능)을 적용해주도록 했다.
- -e URLS: 문서화 할 Yaml 파일들을 등록해준다. 복수로 입력 가능하다
- -v: 현재 Document 파일을 보유하고 있는 폴더를 상대경로($(pwd))로 잡고, "왼쪽(나의 경로):오른쪽(Swager Docker Server 내부 경로)"를 설정해준다.
docker run --name msa-rest-docs-swagger-ui -d -p 80:8080 \
-e URLS_PRIMARY_NAME=MSA_REST_API_Documentation \
-e URLS="[ \
{ url: 'docs/rest_docs.yaml', name: 'Rest API One Server' }]" \
-v "/$(pwd)/:/usr/share/nginx/html/docs/" \
swaggerapi/swagger-ui
결론
- Swagger의 UI적인 장점과 Rest Docs의 코드 활용적이고 비즈니스 로직 격리적인 장점에 대해서는 익히 알고 있었지만, MSA 환경에서 서로 다른 API 문서들을 편리하게 관리할까에 대한 의문으로 시작하게 되었다.
- 앞으로의 과제는 해당 문서 파일(yaml)들을 어느 시점에서 관리해줘야 하는지다.
- 여러 방법이 있겠지만, 내가 적용했던 방법은 CI/CD 툴(젠킨스)에서 해당 서버 빌드 시에 만들어지는 yaml 파일을 Docmentation Repository에 Commit하는 방식으로 진행했다.
사견
- API 문서화와 테스트는 중요하다.
- 종종 엑셀로 하나하나 적어가면서 API 스펙이 변경될 때마다 적어주는데.. 너무 힘들다..
반응형
LIST
'Spring Framework > spring' 카테고리의 다른 글
[SpringBoot] @ComponentScan 동작 원리 (0) | 2024.12.09 |
---|---|
[SpringBoot] SpringBoot는 어떻게 실행될까? (0) | 2024.12.08 |
Spring 컨트롤러 테스트 + Rest Docs에서 시간 개선 (0) | 2023.09.13 |
@RequestBody와 @ModelAttribute (0) | 2020.04.29 |
스프링 tiles(타일즈) 설정하기 (0) | 2019.08.12 |