Spring REST Docs 와 Swagger
API 문서
우리 회사는 보통 word 로 API 문서를 만들었다. 수정사항 업데이트 하기가 매우 귀찮았고 까먹을 때가 많았다.
Spring REST Docs
- RESTful (자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것 ) 서비스에 대한 문서 생성을 도와준다.
- 테스트를 통해 API 문서를 만듬
- HTML, PDF 문서로 생성가능 Hosting 도 가능
- 변경에 따른 최신화 보장
Swagger
- 문서에 대한 명세 보다는 API를 쉽게 호출해 볼수 있는 것에 초점
- 테스트 코드가 없어도 문서화 가능 (Controller에 Annotation만 붙이면됨)
- API 테스트 UI 제공
OpenAPI Spec
- Rest API 에 대한 설명, 생성, 사용 및 시각화 하기 위한 인터페이스 파일 사용
- YAML 로 작성하면 이를 Swagger HTML로 바꿔주는 Spec
사용법
아래 Entity를 이용해서 Controller에 CURD를 작성했다.
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String account;
private String email;
private String phoneNumber;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
build.gradle
아래 공식 문서를 참조 한다. 그런데 나의 환경에서는 마지막 단계인 통합 Document 구성이 안되었다….. 글 마지막에 troubleshoot 방법으로 해결 했다.
Test Code
아래 위치에 java 파일을 생성 한다.

@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
@SpringBootTest
public class UserApiDoc {
//org.springframework.test.web.servlet
private MockMvc mockMvc;
@BeforeEach
public void setup(WebApplicationContext context, RestDocumentationContextProvider restDocumentation){
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(documentationConfiguration(restDocumentation)) // documentationConfiguration 가 resDocumentation 의 인스턴스를 얻게 해줌
.build();
System.out.println("before ~~~~~~~~~");
}
@Test
//org.springframework.restdocs.request.RequestDocumentation
//org.springframework.restdocs.payload.PayloadDocumentation
public void testRead() throws Exception{
this.mockMvc.perform(get("/api/user/{id}", 1L))
.andDo(print())
.andDo(document("user",
pathParameters(
parameterWithName("id").description("user id")
),
responseFields(
fieldWithPath("resultCode").description("response code"),
fieldWithPath("data.id").description("id"),
fieldWithPath("data.account").description("account"),
fieldWithPath("data.email").description("email"),
fieldWithPath("data.phoneNumber").description("phone number"),
fieldWithPath("data.createdAt").description("create"),
fieldWithPath("data.updatedAt").description("modify")
)
));
}
}
JUnit5 기반으로 작성. 스프링 부트 기반 테스트를 위해 @SpringBootTest(어플을 띄움)를 Class에 선언해 주고 테스트 수행전에 mockMvc를 설정해준다. 그리고 테스트에서 API 전송후 그 Result를 저장한다.
성공하면 build/generated-snippets/{user}/*.adoc 형태로 저장 된다. 다음으로 asciidoc 파일을 만들어 발생한 asciidoc을 html로 변환 한다.

user.adoc
:snippets: build/generated-snippets
= RESTful Notes API Guide
:doctype: user
:icons: font
:source-highLighter: highlightjs
:toc: left
:toclevels: 4
:sectnums:
:sectlinks:
:sectanchors:
[[api]]
== User Api
include::{snippets}/user/curl-request.adoc[]
include::{snippets}/user/http-request.adoc[]
include::{snippets}/user/path-parameters.adoc[]
include::{snippets}/user/http-response.adoc[]
include::{snippets}/user/response-fields.adoc[]그
이렇게 한 뒤 Build를 하게 되면 build/docs/asciidoc 에 user.html 파일이 생성된다. 이를 was 에서 접근할 수 있도록 resource 폴더에 옮기려면 아래 처럼 build.gradle 파일을 수정 한다.
bootJar {
dependsOn asciidoctor
// from ("build/docs/asciidoc") {
// into 'static/docs'
// }
copy {
from "${asciidoctor.outputDir}"
into "src/main/resources/static/docs/"
}
}
한번 더 build를 하면 src/main/resources/static/docs/user.html 파일이 생성된 것을 알 수 있고 localhost:8080/docs/user.html로 접근시 화면을 볼 수 있다.
restdocs-api-spec
Swagger에서 돌릴 수 OpenAPI Spec 으로 구성된 yaml 파일을 자동으로 생성해주는 Open Source
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.1.md#oasDocument
build.gradle
plugins {
...
id 'com.epages.restdocs-api-spec' version '0.11.4'
}
dependencies {
...
testImplementation 'com.epages:restdocs-api-spec-mockmvc:0.11.4' //2.2
}
// open api 3 spec 사용시
openapi3 {
server = 'http://localhost:8080'
title = 'User API'
description = 'User Api Description'
// tagDescriptionsPropertiesFile = 'src/docs/tag-descriptions.yaml'
version = '0.1.0'
format = 'yaml'
copy {
from "build/api-spec"
into "src/main/resources/static/docs/"
}
}
//from : https://github.com/ePages-de/restdocs-api-spec#gradle
Test Code
//import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document;
//import static com.epages.restdocs.apispec.ResourceDocumentation.resource;
//import com.epages.restdocs.apispec.ResourceSnippetParameters;
public void testRead() throws Exception{
this.mockMvc.perform(get("/api/user/{id}", 1))
.andDo(print())
.andDo(document("user",
pathParameters(
parameterWithName("id").description("user id")
),
responseFields(
fieldWithPath("resultCode").description("response code"),
fieldWithPath("data.id").description("id"),
fieldWithPath("data.account").description("account"),
fieldWithPath("data.email").description("email"),
fieldWithPath("data.phoneNumber").description("phone number"),
fieldWithPath("data.createdAt").description("create"),
fieldWithPath("data.updatedAt").description("modify 시간")
)
));
this.mockMvc.perform(get("/api/user/{id}", 1))
.andDo(document("user",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
resource(
ResourceSnippetParameters.builder().description("User Information CURD").summary("User Information")
.pathParameters(
parameterWithName("id").description("user id")
)
.responseFields(
fieldWithPath("resultCode").description("response code"),
fieldWithPath("data.id").description("id"),
fieldWithPath("data.account").description("account"),
fieldWithPath("data.email").description("email"),
fieldWithPath("data.phoneNumber").description("phone number"),
fieldWithPath("data.createdAt").description("create"),
fieldWithPath("data.updatedAt").description("modify 시간")
).build()
)
));
}
테스트 코드 실행 후 gradle openapi3 하게 되면 yaml 파일이 만들어 진다.
Swagger를 Docker에 올려 해당 yaml 파일을 호스팅 하고 싶다면 아래 명령으로 docker를 실행 시킨다.
docker run -p 80:8080 -e URLS="[{url: 'http://localhost:8080/docs/openapi3.yaml', name: 'user'}, {url: 'https://petstore.swagger.io/v2/swagger.json', name: 'sample'}]" -v /tmp/swagger:/usr/share/nginx/docs/ swaggerapi/swagger-ui
Application 에서 CORS 헤더를 주기 위해 WebConfig 라는 java 파일을 만들고 아래와 같이 코딩한다.
package org.yg.practice.flyway.configs;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer{
@Override
public void addCorsMappings(CorsRegistry registry){
System.out.println("add mapping ~!");
registry.addMapping("/**");
}
}
그 후 localhost로 접속 시 Swagger UI를 볼 수 있다.
참고
fast campus
Trouble Shoot
Spring Rest Docs 공식 사이트 가이드 대로 Gradle 세팅을 진행 했는데 asciidoctor 에서 에러가 발생하면서 build가 되지 않았다. 그래서 아래 URL을 참고하여 문제를 해결 했다.
https://github.com/spring-projects/spring-restdocs/issues/680
build.gradle
plugins {
...
//id "org.asciidoctor.convert" version "1.5.9.2"
id 'org.asciidoctor.jvm.convert' version '3.2.0'
}
configurations {
asciidoctorExt
}
dependencies {
...
asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor'
...
}
asciidoctor {
configurations 'asciidoctorExt'
...
}
다른 부분은 공식 문서와 같게 하니 잘 동작 했다.
블로그 구독하기 !!



