개발을 할 때 엔드포인트, 요청 방법, 응답 방법을 전달하는 방식에 이점을 얻기 위해 Spring Rest Docs와 Swagger라이브러리를 사용합니다.
Spring Rest Docs는 테스트 코드를 기반으로 문서화를 진행하기 때문에 코드를 수정하지 않아도 된다는 이점이 있습니다.
또한 테스트 코드가 통과되어야만 문서화가 진행되므로 신뢰할 수 있는 문서입니다.
MSA 환경에서 두 라이브러리 중 어떤 방식으로 사용해도, 각자의 스프링 서버에 접근해서 확인해야 하기 때문에 원활하지 않을 수 있습니다.
MSA 환경에서 각 서버의 Spring Rest Docs를 추출하여 Swagger UI 서버로 보내 API 문서를 통합하는 방식을 사용할 것입니다.
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()
}
.and()
.authorizeRequests()
.antMatchers("/docs/*).permitAll()
@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)));
}
}
[[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[]
= 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[]
인텔리제이에서 에러를 보여주겠지만 신경 쓰지 말도록 하자
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'
}
import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document;
TODO 후에 이어서 작성