ν΄λΌμ΄μΈνΈκ° REST API λ°±μλ μ ν리μΌμ΄μ
μ μμ²μ μ μ‘νκΈ° μν΄μ μμμΌ λλ μμ² μ 보λ₯Ό λ¬Έμλ‘ μ μ 리νλ κ²
( ν΄λΌμ΄μΈνΈ μͺ½μμ μ΄ μ ν리μΌμ΄μ
μ¬μ©μ μν΄ μμ² URL / request body / query parameter λ±μ΄ νμ )
κ°λ°μκ° μ§μ μκΈ°λ‘ μμ±ν μλ μκ³ , μ ν리μΌμ΄μ
λΉλλ₯Ό ν΅ν΄ API λ¬Έμλ₯Ό μλμΌλ‘ μμ±ν μλ μμ
( But, μκΈ°λ‘ μμ±νλ κ²μ μμ£Ό λΉν¨μ¨μ β API λ¬Έμ μλν μ¬μ©)
βοΈ REST API
- HTTP νλ‘ν μ½μ ν΅ν΄ APIλ₯Ό μ€κ³νκΈ° μν μν€ν μ² μ€νμΌ
- CRUD κΈ°λ₯ κ°μ§
[μ°Έκ³ ] https://appmaster.io/ko/blog/rest-apiran-mueosimyeo-dareun-yuhyeonggwa-eoddeohge-dareungayo
β μκΈ°λ‘ μμ±νμ λ μκ°λ λ§μ΄ λ€κ³ μλ¬ λ°μ κ°λ₯μ±μ΄ λμ λΉν¨μ¨μ μ΄κΈ° λλ¬Έμ μλν μ¬μ©
( SwaggerλΌλ API λ¬Έμ μλν μ€ν μμ€ μ¬μ©ν λ°©μ )
μ ν°λ€μ΄μ
κΈ°λ°μ API λ¬Έμν λ°©μ
( μ ν리μΌμ΄μ
μ½λμ λ¬Έμνλ₯Ό μν λ§μ μ λν
μ΄μ
λ€μ΄ ν¬ν¨λ¨ )
κ°λ μ± λ° μ μ§ λ³΄μμ±μ΄ λ¨μ΄μ§
API λ¬Έμμ API μ½λ κ°μ μ 보 λΆμΌμΉ λ¬Έμ λ°μ κ°λ₯
( μ λν
μ΄μ
λ΄μ API μ€ν μ 보λ₯Ό λ¬Έμμ΄λ‘ μ
λ ₯νλ κ²½μ°κ° λ§κΈ° λλ¬Έ )
API ν΄λ‘μ¨μ κΈ°λ₯ νμ© κ°λ₯
( API λ¬Έμ λ΄μμ Execute λ²νΌμ λλ¬ Controllerμ μμ² κ°λ₯ )
[μ°Έκ³ ] https://swagger.io/docs/specification/about/
ν μ€νΈ μ½λ κΈ°λ°μ API λ¬Έμν λ°©μ
μ ν리μΌμ΄μ μ½λμ λ¬Έμνλ₯Ό μν μ 보λ€μ΄ ν¬ν¨λμ§ μμ
ν
μ€νΈ μΌμ΄μ€μ μ€νμ΄ κΌ passed
μ¬μΌ API λ¬Έμκ° μμ±λ¨
β μ ν리μΌμ΄μ
μ μ μλμ΄ μλ API μ€ν μ 보μ API λ¬Έμ μ 보μ λΆμΌμΉλ‘ μΈν΄ λ°μνλ λ¬Έμ λ₯Ό λ°©μ§ κ°λ₯
ν μ€νΈ μΌμ΄μ€λ₯Ό λ°λμ μμ±ν΄μΌν¨
API ν΄λ‘μ¨μ κΈ°λ₯μ μ 곡νμ§ μμ
REST API λ¬Έμλ₯Ό μλμΌλ‘ μμ±ν΄ μ£Όλ Spring νμ νλ‘μ νΈ
Controllerμ μ¬λΌμ΄μ€ ν μ€νΈλ₯Ό ν΅ν΄ ν μ€νΈκ° ν΅κ³Ό λμ΄μΌμ§λ§ API λ¬Έμκ° μ μμ μΌλ‘ λ§λ€μ΄ μ§
[μ°Έκ³ ]
https://intellij-asciidoc-plugin.ahus1.de/docs/users-guide/features/advanced/spring-rest-docs.html
https://docs.spring.io/spring-restdocs/docs/current/reference/html5/#introduction
ν μ€νΈ μ½λ μμ±
ν μ€νΈ νμ€ν¬ (test task) μ€ν
μμ±λ μ¬λΌμ΄μ€ ν
μ€νΈ μ½λλ₯Ό μ€ν
β μΌλ°μ μΌλ‘ Gradleμ λΉλ νμ€ν¬(task)μ€ νλμΈ test taskλ₯Ό μ€ν μμΌμ API λ¬Έμ μ€λν(snippet)μ μΌκ΄ μμ±
ν
μ€νΈ κ²°κ³Όκ° passed
λ©΄ λ€μ μμ
/ failed
λ©΄ ν
μ€νΈ μΌμ΄μ€ μμ ν λ€μ μ€ν
API λ¬Έμ μ€λν(.adoc νμΌ) μμ±
passed
λ©΄ ν
μ€νΈ μ½λμ API μ€ν μ 보 μ½λλ₯Ό κΈ°λ°μΌλ‘ API λ¬Έμ μ€λνμ΄ .adoc
νμ₯μλ₯Ό κ°μ§ νμΌλ‘ μμ±λ¨βοΈ μ€λν (snippet)
- λ¬Έμμ μΌλΆ μ‘°κ°μ μλ―Έ
- ν μ€νΈ μΌμ΄μ€ νλ λΉ νλμ μ€λνμ΄ μμ±
- μ¬λ¬κ°μ μ€λνμ λͺ¨μμ νλμ API λ¬Έμ μμ± κ°λ₯
API λ¬Έμ μμ±
API λ¬Έμλ₯Ό HTMLλ‘ λ³ν
μμ±λ API λ¬Έμλ₯Ό HTML νμΌλ‘ λ³ν
HTMLλ‘ λ³νλ λ¬Έμλ HTML νμΌ μ체λ₯Ό 곡μ ν μλ μκ³ , URLμ ν΅ν΄ ν΄λΉ HTMLμ μ μν΄μ νμΈν μ μμ
1. build.gradle
μ μλμκ°μ΄ μ€μ ν΄μ£Όμ΄μΌ Spring Rest Docsκ° API λ¬Έμ μμ± μμ
μ μ μμ μΌλ‘ μν κ°λ₯
plugins {
id 'org.springframework.boot' version '2.7.1'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id "org.asciidoctor.jvm.convert" version "3.3.2"
// (1) .adoc νμΌ νμ₯μλ₯Ό κ°μ§λ AsciiDoc λ¬Έμλ₯Ό μμ±ν΄μ£Όλ Asciidoctor μ¬μ©νκΈ° μν νλ¬κ·ΈμΈ μΆκ°
id 'java'
}
group = 'com.codestates'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
// (2) ext λ³μμ set() λ©μλλ₯Ό μ΄μ©ν΄μ, API λ¬Έμ μ€λνμ΄ μμ±λ κ²½λ‘ μ§μ
ext {
set('snippetsDir', file("build/generated-snippets"))
}
// (3) AsciiDoctorμμ μ¬μ©λλ μμ‘΄ κ·Έλ£Ή μ§μ
// (:asciidoctor taskκ° μ€νλλ©΄ λ΄λΆμ μΌλ‘ μλμμ μ§μ ν βasciidoctorExtensionsβλΌλ κ·Έλ£Ήμ μ§μ )
configurations {
asciidoctorExtensions
}
dependencies {
// (4) spring-restdocs-core / spring-restdocs-mockmvc μμ‘΄ λΌμ΄λΈλ¬λ¦¬κ° μΆκ°
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
// (5) spring-restdocs-asciidoctor μμ‘΄ λΌμ΄λΈλ¬λ¦¬ μΆκ°
// ((3)μμ μ§μ ν asciidoctorExtensions κ·Έλ£Ήμ μμ‘΄ λΌμ΄λΈλ¬λ¦¬κ° ν¬ν¨λ©)
asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.mapstruct:mapstruct:1.5.1.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.1.Final'
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'com.google.code.gson:gson'
}
// (6) test task μ€ν μ, API λ¬Έμ μμ± μ€λν λλ ν 리 κ²½λ‘ μ€μ
tasks.named('test') {
outputs.dir snippetsDir
useJUnitPlatform()
}
// (7) :asciidoctor task μ€ν μ, Asciidoctor κΈ°λ₯ μ¬μ©μ μν΄ :asciidoctor taskμ asciidoctorExtensions μ€μ
tasks.named('asciidoctor') {
configurations "asciidoctorExtensions"
inputs.dir snippetsDir
dependsOn test
}
// (8) :build task μ€ν μ μ μ€νλλ task
// :copyDocument taskκ° μνλλ©΄ index.html νμΌμ΄ "src/main/resources/static/docs" μ copyλ¨
// copyλ index.html νμΌμ API λ¬Έμλ₯Ό νμΌ ννλ‘ **μΈλΆμ μ 곡νκΈ° μν μ©λ**λ‘ μ¬μ©
task copyDocument(type: Copy) {
dependsOn asciidoctor
// (8-1) :asciidoctor taskκ° μ€νλ νμ taskκ° μ€ν λλλ‘ μμ‘΄μ± μ€μ
from file("${asciidoctor.outputDir}")
// (8-2) "build/docs/asciidoc/" κ²½λ‘μ μμ±λλ index.htmlμ copy
into file("src/main/resources/static/docs")
// (8-3) "src/main/resources/static/docs" κ²½λ‘λ‘ index.htmlμ μΆκ°
}
build {
dependsOn copyDocument
// (9) :build taskκ° μ€νλκΈ° μ μ :copyDocument taskκ° λ¨Όμ μν λλλ‘ ν¨
}
// (10) μ ν리μΌμ΄μ
μ€ν νμΌμ΄ μμ±νλ :bootJar task μ€μ
// ( jar νμΌμ ν¬ν¨ν΄μ μΉ λΈλΌμ°μ μμ API λ¬Έμλ₯Ό νμΈνκΈ° μν μ©λ )
bootJar {
dependsOn copyDocument
// (10-1) :bootJar task μ€ν μ μ :copyDocument taskκ° μ€ν λλλ‘ μμ‘΄μ± μ€μ
from ("${asciidoctor.outputDir}") {
// (10-2) Asciidoctor μ€νμΌλ‘ μμ±λλ index.html νμΌμ jar νμΌ μμ μΆκ°
into 'static/docs'
// (10-3) jar νμΌμ index.htmlμ μΆκ°ν΄ μ€μΌλ‘μ¨ μΉ λΈλΌμ°μ μμ μ μ(http://localhost:8080/docs/index.html) ν, API λ¬Έμλ₯Ό νμΈ κ°λ₯
}
}
[μ°Έκ³ ] https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html
2. API λ¬Έμ μ€λνμ μ¬μ©νκΈ° μν ν
νλ¦Ώ(λλ source νμΌ) μμ±
β API λ¬Έμ μ€λνμ΄ μμ± λμμ λ μ΄ μ€λνμ μ¬μ©ν΄μ μ΅μ’
API λ¬Έμλ‘ λ§λ€μ΄ μ£Όλ ν
νλ¦Ώ λ¬Έμ(index.adoc)λ₯Ό μμ±νλ κ²
βοΈ Gradle κΈ°λ° νλ‘μ νΈμμλ src/docs/asciidoc/
κ²½λ‘μ ν΄λΉνλ λλ ν 리 μμ±νκΈ°
βοΈ src/docs/asciidoc/
λλ ν 리 λ΄μ λΉμ΄μλ ν
νλ¦Ώ λ¬Έμ(index.adoc) μμ±νκΈ°
( λμ€μ λ§λ€μ΄μ§ μ€λνλ€μ νλ²μ λͺ¨μ htmlλ‘ λ³νν μ΅μ’
API λ¬Έμλ₯Ό μμ±ν μ©λ !)
β μμ κ°μ΄ λκ°μ§ μ€μ μ λ§μΉλ©΄ Controllerλ₯Ό ν μ€νΈ ν ν μ€νΈ μΌμ΄μ€λ₯Ό μμ±νκ³ , ν΄λΉ Controllerμ λν API μ€ν μ 보λ₯Ό ν μ€νΈ μΌμ΄μ€μ μΆκ°ν΄ μ£Όλ©΄ API λ¬Έμ μ€λνμ μμ±ν μ μλ€!
@WebMvcTest(MemberController.class) // (1)
@MockBean(JpaMetamodelMappingContext.class) // (2)
@AutoConfigureRestDocs // (3)
public class MemberControllerRestDocsTest {
@Autowired
private MockMvc mockMvc; // (4)
@MockBean
// (5) ν
μ€νΈ λμ Controller ν΄λμ€κ° μμ‘΄νλ κ°μ²΄λ₯Ό Mock Bean κ°μ²΄λ‘ μ£Όμ
λ°κΈ°
@Test
public void postMemberTest() throws Exception {
// given
// (6) ν
μ€νΈ λ°μ΄ν°
// (7) Mock κ°μ²΄λ₯Ό μ΄μ©ν Stubbing
// when
ResultActions actions =
mockMvc.perform(
// (8) request μ μ‘
);
// then
actions
.andExpect( // (9) responseμ λν κΈ°λ κ° κ²μ¦
.andDo(document(
// (10) API λ¬Έμ μ€ν μ 보 μΆκ°
));
}
}
( μμμ λλ¨Έμ§λ Mockitoλ₯Ό μ¬μ©νμ¬ Cotroller μ¬λΌμ΄μ€ ν μ€νΈλ₯Ό ν μ½λμ κ°μ )
( ν΄λμ€ λ 벨μ μ λν
μ΄μ
κ³Ό then
λΆλΆμμ .andDo(document(...));
μ΄νκ° API λ¬Έμμ λν μ 보μ ! )
(1) @WebMvcTest(MemberController.class)
Controller ν
μ€νΈλ₯Ό μν μ μ© μ λν
μ΄μ
( @SpringBootTest
μ λν
μ΄μ
μ¬μ© X )
κ΄νΈ μμλ ν μ€νΈ λμ Controller ν΄λμ€ μ§μ
(2) @MockBean(JpaMetamodelMappingContext.class)
Spring Boot κΈ°λ° ν μ€νΈλ νμ μ΅μμ ν¨ν€μ§ κ²½λ‘μ
~~~Application
ν΄λμ€λ₯Ό μ°Ύμμ μ€ννλλ°, μ΄ ν΄λμ€μλ@EnableJpaAuditing
μ λν μ΄μ μ΄ μΆκ°λμ΄μμ@EnableJpaAuditing // μ¬κΈ° @SpringBootApplication public class Section3Week3RestDocsApplication { public static void main(String[] args) { SpringApplication.run(Section3Week3RestDocsApplication.class, args); } }
β κ·Έλ¬λ©΄ JPAμ κ΄λ ¨λ Beanλ€μ νμλ‘ νκΈ° λλ¬Έμ
@WebMvcTest
μ λν μ΄μ μ μ¬μ©νμ¬ ν μ€νΈλ₯Ό μ§νν κ²½μ°,
κ΄νΈμ JpaMetamodelMappingContextλ₯Ό Mock κ°μ²΄λ‘ μ£Όμ ν΄ μ£Όμ΄μΌ ν¨
(3) @AutoConfigureRestDocs
(10) API λ¬Έμλ₯Ό μλ μμ±νκΈ° μν ν΄λΉ Controller νΈλ€λ¬ λ©μλμ API μ€ν μ 보λ₯Ό document(β¦)μ μΆκ°
.andDo(β¦)
λ©μλ
β API λ¬Έμλ₯Ό μμ± νκΈ° μν΄ Spring Rest Docsμμ μ§μνλ λ©μλ
document(β¦)
λ©μλ
β μΌλ°μ μΈ λμμ μ μνκ³ μ ν λ μ¬μ©
( andExpect()
μ²λΌ μ΄λ€ κ²μ¦ μμ
μ νλ κ² X )
β API μ€ν μ 보λ₯Ό μ λ¬ λ°μμ μ€μ§μ μΈ λ¬Έμν μμ
μ μννλ RestDocumentationResultHandler
ν΄λμ€μμ κ°μ₯ ν΅μ¬ κΈ°λ₯μ νλ λ©μλ
[document() λ©μλ μμ μΈ μ μλ νλΌλ―Έν°λ€ μ°Έκ³ ]
https://docs.spring.io/spring-restdocs/docs/current/reference/html5/#documenting-your-api
β
[jsonFieldType μ°Έκ³ ]
https://docs.spring.io/spring-restdocs/docs/current/reference/html5/#documenting-your-api-request-response-payloads-fields-json-field-types
β μ κΈ°λ³Έ ꡬ쑰λ₯Ό λ°λΌ API μ€ν μ 보λ₯Ό μμ±νλ©΄λ¨ !
( μμΈν λ΄μ©μ μ€μ΅ νμΌ μ°Έκ³ )
βοΈ
@SpringBootTest
vs@WebMvcTest
β
@SpringBootTest
μ λν μ΄μ
@AutoConfigureMockMvc
μ ν¨κ» μ¬μ©- νλ‘μ νΈμμ μ¬μ©νλ μ 체 Beanμ ApplicationContextμ λ±λ‘νμ¬ μ¬μ©
β ν μ€νΈ νκ²½μ ꡬμ±νλ κ²μ νΈλ¦¬
β But, μ€ν μλκ° μλμ μΌλ‘ λλ¦Ό
β
π λ°μ΄ν°λ² μ΄μ€κΉμ§ μμ² νλ‘μΈμ€κ° μ΄μ΄μ§λ ν΅ν© ν μ€νΈμ μ£Όλ‘ μ¬μ©
β @WebMvcTest
μ λν μ΄μ
- Controller ν μ€νΈμ νμν Beanλ§ ApplicationContextμ λ±λ‘νμ¬ μ¬μ©
β μ€ν μλ μλμ μΌλ‘ λΉ λ¦
But, Controllerμμ μμ‘΄νκ³ μλ κ°μ²΄κ° μλ€λ©΄ ν΄λΉ κ°μ²΄μ λν΄μ Mock κ°μ²΄λ₯Ό μ¬μ©νμ¬ μμ‘΄μ±μ μΌμΌμ΄ μ κ±°ν΄ μ£Όμ΄μΌν¨
β
π Controllerλ₯Ό μν μ¬λΌμ΄μ€ ν μ€νΈμ μ£Όλ‘ μ¬μ©
Spring Rest Docsλ₯Ό ν΅ν΄ μμ±λλ ν
μ€νΈ κΈ°λ° λ¬Έμ ν¬λ§·
β Spring Rest Docsλ₯Ό ν΅ν΄ λ§λ€μ΄μ§λ λ¬Έμ μ€λνκ³Ό μ΄ λ¬Έμ μ€λνμ μ¬μ©νλ ν
νλ¦Ώ λ¬Έμλ Asciidoc ν¬λ§·μ λ¬Έμλ‘ μ΄λ£¨μ΄μ Έ μμ
κΈ°μ λ¬Έμ μμ±μ μν΄ μ€κ³λ κ°λ²Όμ΄ λ§ν¬μ μΈμ΄
μ΄λ₯Ό μ΄μ©ν΄ μ’ λ μΈλ ¨λκ³ κ°λ μ± μ’μ λ¬Έμ λ§λ€κΈ° κ°λ₯ !
Ex.
= μ»€νΌ μ£Όλ¬Έ μ ν리μΌμ΄μ // (1) λ¬Έμμ μ λͺ© :sectnums: // (2) :toc: left // (3) :toclevels: 4 // (4) :toc-title: Table of Contents // (5) :source-highlighter: prettify // (6) β Joo Hyun Ju <57wnguswn57@gmail.com> // (7) λ¬Έμλ₯Ό μμ±ν μ΄μ μ 보 β v1.0.0, 2022.11.15 // (8) μμ± λ μ§ β // (9) API λ¬Έμ μ€λνμ μ΄μ©νλ λΆλΆ *** // (10) == MemberController === νμ λ±λ‘ .curl-request // (9-1) include::{snippets}/post-member/curl-request.adoc[] // (9-2) β .http-request include::{snippets}/post-member/http-request.adoc[] β .request-fields include::{snippets}/post-member/request-fields.adoc[] β .http-response include::{snippets}/post-member/http-response.adoc[] β .response-fields include::{snippets}/post-member/response-fields.adoc[]
(1) λ¬Έμμ μ λͺ©
=
λ₯Ό μΆκ°νμ¬ μ λͺ© μμ±=
μ κ°μκ° λμ΄λ μλ‘ κΈμλ μμμ§ )(2) :sectnums:
(3) :toc:
left
λ‘ μ€μ )(4) :toclevels:
====
κΉμ§μ μ λͺ©λ§ λͺ©μ°¨μ νμλ¨ )(5) :toc-title:
(6) :source-highlighter:
prettify
μ§μ )(9) API λ¬Έμ μ€λνμ μ΄μ©νλ λΆλΆ
(9-1) .
curl-request
λ₯Ό μΉμ
μ λͺ©μΌλ‘ ν¨ )(9-2) ν
νλ¦Ώ λ¬Έμμμ μ€λνμ μ¬μ©νλ λ°©λ²
β include::{snippets}/μ€λν λ¬Έμκ° μμΉν λλ ν 리/μ€λν λ¬ΈμνμΌλͺ
.adoc[]
include
β Asciidoctorμμ μ¬μ©νλ 맀ν¬λ‘(macro) μ€ νλ
β μ€λνμ ν
νλ¦Ώ λ¬Έμμ ν¬ν¨ν λ μ¬μ©
::
β 맀ν¬λ‘λ₯Ό μ¬μ©νκΈ° μν νκΈ°λ²
βοΈ λ§€ν¬λ‘ (macro)
β μ΄λ€ λ°λ³΅λλ μμ μ μλννλ€λ μλ―Έ
{snippets}
β ν΄λΉ μ€λνμ΄ μμ±λλ λν΄νΈ κ²½λ‘
β build.gradle
νμΌμ μ€μ ν snippetsDir
λ³μλ₯Ό μ°Έμ‘°νλ λ° μ¬μ©ν μ μμ
(10) ***
λ°μ€ λ¬Έλ¨
CAUTION:
/ NOTE:
/ TIP:
/ IMPORTANT:
/ WARNING:
λ±
URL Scheme μλ μΈμ
http
/ https
/ ftp
/ irc
/ mailto
/ hgd@gmail.com
κ³Ό κ°μ URL Schemeλ Asciidoc μμ μλμΌλ‘ μΈμνμ¬ λ§ν¬ μ€μ λ¨image::
image::https://spring.io/images/spring-logo-9146a4d3298760c2e7e49595184e1975.svg[spring]
[Asciidoctor μ¬μ©λ² μ°Έκ³ ]
AsciiDoc ν¬λ§·μ λ¬Έμλ₯Ό νμ±ν΄μ HTML 5, 맀λ΄μΌ νμ΄μ§, PDF λ° EPUB 3 λ±μ λ¬Έμλ₯Ό μμ±νλ ν΄
Spring Rest Docsμμλ Asciidoc ν¬λ§·μ λ¬Έμλ₯Ό HTML νμΌλ‘ λ³ννκΈ° μν΄ λ΄λΆμ μΌλ‘ Asciidoctorλ₯Ό μ¬μ©νκ³ μμ
μμ κΈ°λ³Έ ꡬ쑰μ λ°λΌ API μ€ν μ 보λ₯Ό μμ±ν ν ν
μ€νΈκ° passed
κ° λλ©΄,
μλμ κ°μ΄ build > generated-snippets > μ€λνλͺ
ν΄λμ ν΄λΉ μ€λνλ€μ΄ μμ±λ¨ !
βοΈ snippet μ’ λ₯
curl-request.adoc
β νΈμΆμ λν curl λͺ λ Ήμ ν¬ν¨ νλ λ¬Έμhttpie-request.adoc
β νΈμΆμ λν http λͺ λ Ήμ ν¬ν¨ νλ λ¬Έμhttp-request.adoc
β http μμ² μ 보 λ¬Έμhttp-response.adoc
β http μλ΅ μ 보 λ¬Έμrequest-body.adoc
β μ μ‘λ http μμ² λ³Έλ¬Έ λ¬Έμresponse-body.adoc
β λ°νλ http μλ΅ λ³Έλ¬Έ λ¬Έμrequest-parameters.adoc
β νΈμΆμ parameter μ λν λ¬Έμpath-parameters.adoc
β http μμ²μ url μ ν¬ν¨λλ path parameter μ λν λ¬Έμrequest-fields.adoc
β http μμ² object μ λν λ¬Έμresponse-fields.adoc
β http μλ΅ object μ λν λ¬Έμ
λͺ¨λ ν
μ€νΈλ₯Ό λ§μΉκ³ μ€λνλ€μ΄ λͺ¨λ μμ±λλ©΄,
Spring Rest Docs μ€μ μμ λ§λ€μ΄ λμλ ν
νλ¦Ώ λ¬Έμλ₯Ό μμ±ν src/docs/asciidoc/index.adoc
νμΌμ
μλμ κ°μ΄ μ€λνλ€μ λͺ¨λ ν©μ³ HTMLλ‘ λ³νμ μν μ΅μ’
API λ¬Έμλ₯Ό λ§λ€μ΄μ£Όλ©΄ λ¨!
μ΄μ λ€ μμ±μ νλ€λ©΄,
μ μ¬μ§μ²λΌ Gradleμ :build
or :bootJar
task λͺ
λ Ήμ μ€ννμ¬ index.adoc
νμΌμ index.html
νμΌλ‘ λ³ννκΈ° !
κ·Έλ¬λ©΄ μμ κ°μ΄ src/main/resources/static.docs/
κ²½λ‘μ index.html
μ΄ μκΉ !!
μ΄λ₯Ό μΈν°λ·μμ νμΈνκ³ μΆλ€λ©΄,
intellij μμ μ ν리μΌμ΄μ
μ€ν ν, http://localhost:8080/docs/index.html
μ΄ URLμ μΉ λΈλΌμ°μ μ μ
λ ₯νλ€λ©΄
μλμ κ°μ΄ API λ¬Έμκ° htmlν λ κ²μ λ³Ό μ μμ ~
[μ°Έκ³ ] https://jogeum.net/16
μ€λ νμ΅μ μ μ νμ΅νλ Controller μ¬λΌμ΄μ€ ν μ€νΈμ μ’ λ μΆκ°λ§ νλ©΄ λλ λΆλΆμ΄μ΄μ μ¬μ κ³ μλμΌλ‘ λ§λ€μ΄μ§ API λ¬Έμλ₯Ό μ§μ λ³Ό μ μμ΄μ λ μ¬λ―Έμλ μ±ν°μλ€ !