목차
"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
2) Spring REST Docs
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
'Language > Back End' 카테고리의 다른 글
Maven이 아닌 Gradle을 사용하자! (0) | 2023.11.23 |
---|---|
[Java OOP] Getter와 Setter사용을 지양해야 하는 이유가 뭘까? (0) | 2023.10.06 |
[Rest Docs] Spring Boot API 문서 자동화 설정 (0) | 2023.09.18 |
[Swagger UI] Spring Boot API 문서 자동화 설정 및 사용 예제 (0) | 2023.09.11 |
Java ] iframe 탭 로그인 세션 공유 (0) | 2023.02.20 |