320x100
반응형
목차
이전에 진행했던 Spring-React 프로젝트에서 API명세를 엑셀을 통해서 관리를 했다
나름 그래도 정리된 문서를 보고 뷰를 작성함에 있어서 편리함은 있었지만 하나의 프로젝트에서 관리를 해보고자 Rest Docs을 적용하게 되었다
Swagger vs Rest Docs
처음에는 인턴때 API명세를 Swagger를 통해서 확인을 해서 Swagger를 사용하고자 했으나 찾아보니 서비스 코드내에 어노테이션을 작성해야 했고 기존 로직과 함께 작성되어 관리에 불편함이 있을 듯 하여 Spring Rest Docs를 사용하게 되었다
그래도 나중에 Swagger를 한번쯤은 사용해볼 생각이다
Rest Docs 설정
실행 환경
- java
- jdk11
- 빌드툴
- Gradle
- 테스트
- Junit5
- MockMvc
build.gradle
plugins {
id 'org.springframework.boot' version '2.7.2'
id 'io.spring.dependency-management' version '1.0.12.RELEASE'
id 'java'
id "org.asciidoctor.jvm.convert" version "3.3.2" // 1.
}
group = 'com.jhs'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
asciidoctorExt // 2.
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
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'
// 3.
asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
}
// 4.
ext {
snippetsDir = file('build/generated-snippets')
}
test {
outputs.dir snippetsDir // 5.
useJUnitPlatform()
}
// 6.
asciidoctor {
inputs.dir snippetsDir // 6-1
configurations 'asciidoctorExt' // 6-2
dependsOn test
}
// 7.
task copyDocument(type: Copy) {
dependsOn asciidoctor
doFirst{
delete file('src/main/resources/static/docs')
}
from file("build/docs/asciidoc")
into file("src/main/resources/static/docs")
}
// 8.
build {
dependsOn copyDocument
}
// 9.
bootJar {
dependsOn asciidoctor
from ("${asciidoctor.outputDir}/html5") {
into 'static/docs'
}
}
- Asciidoctor 플러그인 적용
- Asciidoctor 의존성 설정 명시
- 의존성 설정
- build/generated-snippets 에 생긴 .adoc 파일들을 프로젝트 내의 .adoc 파일에서 읽어들일 수 있도록 설정해줌
- snippets 생성 폴더 위치 명시
- 테스트 실행시 해당 위치로 생성되도록 설정
- Asciidoctor 작업 설정
- snippetsDir을 입력으로 설정
- 위에서 작성한 configuration 적용
- test 작업 이후에 작동하도록 설정
- static/docs 지우기 --> IDE내에서도 static/docs 확인 가능
- asccidoctor 작업 이후 생성된 HTML 파일을 static/docs 로 copy
- build 의 의존작업 명시
- jar 빌드 전에 doc생성build 폴더 내에서만 확인 가능 (7,8,9 과정 실행시 굳이 안해도 됨)
- jar안에 static/docs directory로 doc copy
Spring 공식 문서를 참조하여 설정했습니다
테스트코드
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.ResultActions;
import static org.mockito.BDDMockito.*;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.restdocs.request.RequestDocumentation.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(MemberController.class) // Controller Unit test 설정
@AutoConfigureRestDocs // RestDocs 자동 설정
class MemberControllerTest {
@MockBean
protected MemberService memberService;
@Test
@DisplayName("getMemberInfo - Get /member?memberId")
void common() throws Exception {
//given
MemberInfoResponse response = MemberInfoResponse.builder()
.memberId("memberA@naver.com")
.memberName("memberA")
.password("memberA")
.age(10)
.salary(100)
.build();
given(memberService.getMemberInfo("memberA@naver.com")).willReturn(response);
String memberId = "memberA@naver.com";
//when
ResultActions action = mockMvc.perform(get("/member?memberId=" + memberId));
//then
SingleResponseData responseData = SingleResponseData.of(response);
action.andExpect(status().isOk())
.andExpect(content().json(createJson(responseData)))
.andExpect(jsonPath("$.data.memberId").exists())
.andDo(
// rest docs 문서 작성 시작
document("member/create", // directory명 위에서 설정한 build/generated-snippets 하위에 생성
// --> build/generated-snippets/member/create
requestParameters( // queryString 관련 변수 정보 입력
parameterWithName("memberId").description("memberId to find")
),
responseFields( // response data 필드 정보 입력
subsectionWithPath("data").description("DATA"),
fieldWithPath("statusCode").description("STATUS_CODE"),
fieldWithPath("message").description("MESSAGE")
)));
}
}
기본 생성 파일
- build/generated-snippets/member/create/curl-request.adoc
- build/generated-snippets/member/create/http-request.adoc
- build/generated-snippets/member/create/http-response.adoc
- build/generated-snippets/member/create/httpie-request.adoc
- build/generated-snippets/member/create/request-body.adoc
- build/generated-snippets/member/create/response-body.adoc
추가 생성 파일
document()
안에서 직접 정보를 입력한 것에 대해서 추가적으로 생성이 된다
- build/generated-snippets/member/create/request-parameters.adoc
- build/generated-snippets/member/create/response-fields.adoc
문서 만들기
위에서 만들어진 .adoc파일을 이용해서 하나의 통합본? 통합파일을 만들 차례이다
우선 src/docs/asciidoc/index.adoc
(adoc파일 이름은 원하는 대로)을 만들면 해당 파일이 build/docs/asciidoctor/
밑에 html파일이 생성되게 된다
그 후 이전 설정에서 해둔대로 src/main/resources/static/docs
밑으로 html파일이 복사되어 진다
= API Docs
Spring-React 공부
:icons: font
:source-highlighter: highlightjs // 문서에 표기되는 코드들의 하이라이팅을 highlightjs를 사용
:toc: left // toc (Table Of Contents)를 문서의 좌측에 두기
:toc-title: API // toc 제목
:toclevels: 2 // toc 생성 헤더레벨
:sectlinks:
== Member Crate
=== Http Request
include::{snippets}/member/create/http-request.adoc[] // 1.
== Member Create // 2.
operation::member/create[snippets='http-request,http-response,request-body,response-body,request-fields,response-fields']
adoc파일을 사용하는 방법에는 두가지가 있다
- 파일을 하나씩 적용 이때는 header도 직접 적용해줘야 한다
- 여러 파일을 한번에 적용 알아서 header를 적용해준다 단계도 하나 깊게 적용 (여기서는 ###헤더로 적용된다)
해당 index.adoc파일 작성 후 build를 다시하면 src/main/resources/static/docs
밑에 html파일이 생성된다
320x100
반응형
'공부기록 > Spring' 카테고리의 다른 글
Spring-Rest Docs(3) (0) | 2022.08.16 |
---|---|
Spring-Rest Docs(2) (0) | 2022.08.11 |
Spring boot CORS 설정 (0) | 2022.08.03 |
DTO관련 고민 (0) | 2022.07.13 |
Spring - 예외처리 (0) | 2022.02.06 |