✨ api 문서화 정리 글
아래의 버전인 상황에서 적용을해본 예제입니다 참고해주세요 :)
- spring boot 3.0
- jdk 17
- gradle 7.5.1
1. Spring REST Docs란
Spring 에서 API 문서를 자동화하는 또 다른 방법은 Spring Rest Docs 입니다.
2. Swagger VS Spring Rest Docs
자바 문서 자동화에는 주로 Swagger 와 Spring Rest Docs 가 사용됩니다.
Spring Rest Docs | Swagger | |
장점 | 제품코드에 영향이 없다 | API를 테스트 해 볼수 있는 화면을 제공한다. |
테스트가 성공해야 문서가 작성된다. | 적용하기 쉽다. | |
단점 | 적용하기 어렵다 | 제품코드에 어노테이션을 추가해야한다. |
제품코드와 동기화가 안될 수 도있다. |
Swagger는 API 동작을 테스트하는 용도에 더 특화되어있다고 합니다.
반면에 Spring Rest Docs 은 깔끔 명료한 문서를 만들 수도 있고, 코드에 추가할것도 없고, 테스트 수행 후 deploy (배포)가 된다는 장점도 있습니다.
3. Spring Rest Docs 사용법
Spring Project version 에 따른 적용방법 가이드
1) 의존성 추가
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.0'
id 'io.spring.dependency-management' version '1.1.0'
// gradle 7.0 이상부터는 jvm 사용
id "org.asciidoctor.jvm.convert" version "3.3.2"
//id "org.asciidoctor.convert" version "1.5.9.2"
}
group = 'com.tht'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
configurations {
asciidoctorExtensions // dependencies 에서 적용한 것 추가
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'com.google.code.gson:gson:2.8.8'
//SpringRest Docs
// restdocs-mockmvc의 testCompile 구성 -> mockMvc를 사용해서 snippets 조각들을 뽑아낼 수 있게 된다.
// MockMvc 대신 WebTestClient을 사용하려면 spring-restdocs-webtestclient 추가
// MockMvc 대신 REST Assured를 사용하려면 spring-restdocs-restassured 를 추가
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' //(5)
// build/generated-snippets 에 생긴 .adoc 조각들을 프로젝트 내의 .adoc 파일에서 읽어들일 수 있도록 연동해줍니다.
// 이 덕분에 .adoc 파일에서 operation 같은 매크로를 사용하여 스니펫 조각들을 연동할 수 있는 것입니다.
// 그리고 최종적으로 .adoc 파일을 HTML로 만들어 export 해줍니다.
asciidoctor 'org.springframework.restdocs:spring-restdocs-asciidoctor:2.0.4.RELEASE'
}
ext {
snippetsDir = file('build/generated-snippets')
}
test {
// 위에서 작성한 snippetsDir 디렉토리를 test의 output으로 구성하는 설정 -> 스니펫 조각들이 build/generated-snippets로 출력
outputs.dir snippetsDir
useJUnitPlatform()
//filter {
// includeTestsMatching "com.sparta.springcore.controller.*"
//}
}
asciidoctor {
dependsOn test
configurations 'asciidoctorExtensions' // 위에서 작성한 configuration 적용
inputs.dir snippetsDir
}
//build시 문서 실시간 동기화
bootJar {
dependsOn asciidoctor
from ("${asciidoctor.outputDir}") {
into 'static/docs'
}
}
// static/docs 폴더 비우기
asciidoctor.doFirst {
delete file('src/main/resources/static/docs/')
}
task copyDocument(type: Copy) {
dependsOn asciidoctor
from file("build/docs/asciidoc/")
into file("src/main/resources/static/docs")
}
build {
dependsOn copyDocument
}
// ✨참고사항 //
// 공식 문서에서는 위의 ascidoctor.doFirst부터 아래 내용은 없고 이와 같은 내용만 있습니다.
// 이렇게 하면 jar로 만들어 질때 옮겨지는 것으로 IDE로 돌릴 때는 build 폴더에서만 확인이 가능합니다.
// 위 방법을 사용하면 IDE에서도 static으로 옮겨진 것을 확인할 수 있습니다.
// 위에 방법을 사용하든 아래 방법을 사용하든 편한 선택지를 사용하시면 됩니다.
bootJar {
dependsOn asciidoctor //(3)
from ("${asciidoctor.outputDir}/html5") { //(4)
into "/static/docs"
}
}
Spring Rest Docs는 Asciidoctor 툴을 사용한다. plain text로 작성한 문서를 특별한 문법에 맞춰(mark down과 유사) page 문서로 만들어준다.
(1) AsciiDoc 파일을 컨버팅하고 Build 폴더에 복사하기 위한 플러그인입니다.
(2) gradle build 시 test -> asciidoctor 순으로 수행됩니다.
(3) gradle build 시 asciidoctor -> bootJar 순으로 수행됩니다.
(4) gradle build 시 ./build/asciidoc/html5/ 에 html 파일이 생깁니다.
이것을 jar 안에 /static/docs/ 폴더에 복사가 됩니다.
(5) mockmvc 를 restdocs 에 사용할수 있게 하는 라이브러리입니다.
- 위와 같이 세팅하게 되면 ./gradlew build 진행시 test -> asciidoctor -> copyDocument -> build 순서로 진행되게 됩니다.
정확한 설정은 공식문서를 참고하시는 것을 권장합니다.
👏🏻 만약 build/asciidoc/html5/에 html파일을 src/main/resources/static/doc 복사해주고 싶으시다면 아래 설정을 추가해 주시면 됩니다.
task copyDocument(type: Copy) {
dependsOn asciidoctor
from file("build/asciidoc/html5/")
into file("src/main/resources/static/docs")
}
build {
dependsOn copyDocument
}
2) Spring Test properties
- Spring Rest Docs는 실행하기전에 테스트를 먼저 돌리기 때문에, 테스트 코드를 작성해줘야만합니다. (무족권)
- 테스트할 때 사용할 properties를 만들어주자
application-test.properties
//properties
spring.jpa.show-sql=true
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:springcoredb
jwt.secret=javainuse
//yaml
spring:
h2:
console:
enabled: true
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password:
테스트용이기 때문에 인메모리 디비인 h2를 사용한다.
dependencies {
//h2
implementation 'com.h2database:h2'
}
스프링 시큐리티를 사용하고 있다면 RestDocs url을 풀어준다.
.antMatchers("/docs/**").permitAll()
3) Test Controller 만들기
1. 간단한 컨트롤러 만들기
@RestController
public class RestDocsController {
@GetMapping("rest-docs")
public ResponseEntity<String> getRestDocsHello() {
return ResponseEntity.ok("Let's Start Spring Rest Docs");
}
}
2. 테스트코드 작성하기
1️⃣ 1번 방법
@WebMvcTest(RestDocsController.class)
class RestDocsControllerTest {
private MockMvc mockMvc;
@BeforeEach
public void setUp(WebApplicationContext webApplicationContext,
RestDocumentationContextProvider restDocumentation) {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.apply(documentationConfiguration(restDocumentation))
.build();
}
- webAppContextSetup()만 쓴다면 여러분들이 아시는 Mock을 사용하기 위한 일반적인 MockMvc의 setting이지만
- apply(documentationConfiguration(restDocumentation))를 추가함으로써 문서화를 할 수 있는거라고 합니다.
2️⃣ 2번 방법
@AutoConfigureMockMvc // -> webAppContextSetup(webApplicationContext)
@AutoConfigureRestDocs // -> apply(documentationConfiguration(restDocumentation))
@WebMvcTest(RestDocsController.class)
class RestDocsControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
@DisplayName("Spring Rest Docs Test")
void restDocsTest() throws Exception {
String text = "parameter test";
ResultActions resultActions = mockMvc.perform(
//RestDocs를 사용하기 위해서는 RestDocumentationRequestBuilders 의 get을 사용해야함
RestDocumentationRequestBuilders.get("/rest-docs/{text}", text)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
).andDo( // rest docs 문서 작성 시작
MockMvcRestDocumentation.document("guide-rest-docs", // 문서 조각 디렉토리 명
RequestDocumentation.pathParameters( //path 파라미터 정보 입력
RequestDocumentation.parameterWithName("text").description("파라미터 1")
)
)
);
resultActions.andExpect(MockMvcResultMatchers.status().isOk());
}
}
- 이렇게 해주시면 위의 복잡한 설정을 어노테이션이 대신 해줄 수 있습니다.
- 자세히 알고 싶으신 분들은 @AutoConfigureMockMvc와 @AutoConfigureRestDocs를 참고하시기 바랍니다.
- 평소에 Controller test 의 request 는 MockMvcRequestBuilders 를 사용했는데 Spring Rest Docs 를 사용해주기 위해서는 RestDocumetationRequestBuilders 를 사용해야 되더군요
2️⃣ parmeter 값을 세팅해주는 방법 (출처)
@Test
public void member_get() throws Exception {
// 조회 API -> 대상의 데이터가 있어야 합니다.
mockMvc.perform(
get("/api/members/{id}", 1L)
.contentType(MediaType.APPLICATION_JSON)
)
.andExpect(status().isOk())
.andDo( // rest docs 문서 작성 시작
document("member-get", // 문서 조각 디렉토리 명
PayloadDocumentation.responseFields(
PayloadDocumentation.fieldWithPath("id").description("게시글 ID"),
PayloadDocumentation.fieldWithPath("title").description("게시글 제목"),
PayloadDocumentation.fieldWithPath("content").description("게시글 내용")
)
)
)
);
}
이렇게하고 build(test)를 돌리면 gradle 에서 설정한경로( build/generated-snippets 폴더) 에 테스트에서 작성한 docs가 조각들이 생성되어 있습니다.
기본적으로 다음과 같은 조각들이 default로 생성됙, 이 조각들로 문서를 작성합니다.
- curl-request.adoc
- http-request.adoc
- httpie-request.adoc
- http-response.adoc
- request body
- response body
4) Rest Docs 문서 작성하기
위에 만들어진 파일들은 test 가 돌아가면서 생성된 adoc 문서 조각 파일이지 아직 문서가 아닙니다.
차차 문서로 만들어봅시당
1. index.adoc 파일 만들기
- .adocs 파일을 이용해서, 흩어져잇는 문서 조각들을 문서화 시킬 수 있습니다.
- 그 전에, 폴더를 만들어봅시다.
- main/resources/static/docs 디렉토리를 만들어줍니다. 앞서 gradle 설정에 의해 이곳으로 html 파일이 복사되어 이곳으로 옮겨집니다.
- 그리고 src/docs/asciidoc 디렉토리를 만들고 안에 index.adoc 파일을 만들어줍니다.
- Index.adoc 파일을 만드니, 인텔리제이에서 플러그인을 추천해줍니다. 까니까 readme 처럼 옆에 미리보기가 지원되더군요
2. index.adoc 파일 작성하기
- adocs 문서파일을 작성해봅시당
- adocs 파일을 작성하고, 다시 빌드를 해주면 main/resources/static/docs 폴더에 index.html 파일이 만들어지게 됩니다.
= REST Docs 문서 만들기 (글의 제목)
backtony.github.io(부제)
:doctype: book
:icons: font
:source-highlighter: highlightjs // 문서에 표기되는 코드들의 하이라이팅을 highlightjs를 사용
:toc: left // toc (Table Of Contents)를 문서의 좌측에 두기
:toclevels: 2
:sectlinks:
[[Rest-Docs-test-API]]
== Rest 테스트
operation::guide-rest-docs[snippets='http-request,path-parameters,http-response']
[[기타-API]]
== 기타 API
- :source-highlighter: highlightjs
- 문서에 표기되는 코드들의 하이라이팅을 highlightjs를 사용합니다.
- :toc: left
- toc (Table Of Contents)를 문서의 좌측에 둡니다.
- =, ==, ===
- Markdown의 #, <h1>, <h2>, <h3> 와 같은 역할을 합니다.
- [[텍스트]]
- 해당 텍스트에 링크를 겁니다.
- operation::디렉토리명[snippets=’원하는 조각들’]
- 문서로 사용할 조각들을 명시해줍니다.
- 🔥 각 상황에 따라 문서화할 조각들이 달라지므로 자세히 봐주세요
- include::{snippets}/member-get/XXX.adoc[]
- opertaion의 경우 한번에 원하는 조각들을 넣을 수 있었는데 include는 특정 adoc을 지정하여 넣을 수 있습니다.
추가적으로 다른 Asciidoc 사용법은 [링크]를 참고하시면 도움이 될 것 같습니다.
➡️ 이렇게 .adoc 파일을 작성하게 되면, build 시 gradle 설정에따라 .adoc 문서를 .build 안에 html 파일로 만들어줍니다. (이 글 처럼 copy docs를 설정하였다면 "resources/static/docs/" 안에 파일이 생성되어있습니다
*참고
'Spring > Spring Boot' 카테고리의 다른 글
ResponseEntity란 - 개념, 구조, 사용법, 사용하는 이유 (4) | 2022.01.16 |
---|---|
[Spring] spring boot - 외부 Rest API json으로 받아오기(JAVA) (2) | 2022.01.15 |
[Spring] API 문서 자동화 1 - Swagger (0) | 2021.12.29 |
JPA pageable 페이징 정렬, 외부 참조 엔티티 리스트 개수로 정렬할때 - @Formula (0) | 2021.12.29 |
[Spring] JPA의 이해(JPA, Hibernate) (0) | 2021.12.29 |