API 문서화
프로젝트를 진행하다 보면 다른 업체와 협업을 하거나 프로젝트 정보를 공유하는 경우가 생기게 된다.
많은 API를 모두 설명할 수 없어서 보통은 API 문서를 사용해서 통신에 필요한 정보를 제공하곤 한다.
API 문서화 도구를 사용하지 않고도 직접 html 파일로 작성하거나 다른 프로그램으로 작성할 수 있다.
하지만 그렇게 되면 개발과 문서 작업 둘 다 병행해야하기 때문에 많은 시간과 인력을 낭비하게 된다.
그리고 수작업으로 진행하다보면 내용을 빼먹는 경우도 생기게 된다.
그렇기 때문에 대부분 API 문서화 도구 사용을 추천한다.
Swagger vs Spring REST Docs
많이 사용하는 API 문서화 도구로는 Swagger와 Spring Rest Docs가 있다.
Swagger
장점
- API를 테스트해 볼 수 있는 화면이 제공된다.
- Spring REST Docs에 비해 적용이 쉽다.
단점
- 비즈니스 로직에 명세를 작성해야 해서 전체적으로 코드의 가독성이 떨어진다.
- 비즈니스 로직과 동기화가 안될 수 있다.
- 테스트 기반이 아니기 때문에 안정성을 보장할 수 없다.
Spring REST Docs
장점
- 테스트 코드를 기반으로 문서를 작성하기 때문에 안정성이 어느정도 보장된다.
- 테스트 코드에서 명세를 작성하기 때문에 비즈니스 로직의 가독성에 영향을 미치지 않는다.
단점
- Swagger에 비해 적용이 어렵다.
- 공식 문서 외의 레퍼런스가 많이 없다.
- Swagger에 비해 빌드 속도가 느리다.
- 테스트 코드 아래에 이어붙이는 형식으로 코드를 작성하기 때문에 테스트 코드가 길어진다.
각 도구마다 장단점이 있기때문에 원하는 도구를 선택해서 API 문서를 작성하면 된다.
Spring REST Docs 사용 이유
'보기 좋은 떡이 먹기도 좋다'라는 말이 있듯 가독성이 떨어지는 코드는 읽기도 싫어진다.
Swagger를 사용할 경우 비즈니스 로직에 Swagger 코드가 섞이게 된다.
여러 가지 어노테이션이 붙으면서 코드의 가독성이 현저히 낮아지게 된다.
그래서 번거롭더라도 개발 코드와 테스트 코드를 구분해서 작성하는 Spring REST Docs를 사용하기로 했다.
Spring REST Docs 사용하기
개발 환경
- SpringBoot 3.2.0
- Java 17
- Gradle 8.5
- JUnit 5
- MockMvc
build.gradle
plugins {
...
id 'org.asciidoctor.jvm.convert' version '4.0.0-alpha.1' // (1)
}
configurations {
asciidoctorExt // (2)
}
dependencies {
...
asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' // (3)
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' // (4)
}
ext {
snippetsDir = file('build/generated-snippets') // (5)
}
tasks.named('test') {
useJUnitPlatform()
outputs.dir snippetsDir // (6)
}
asciidoctor {
inputs.dir snippetsDir // (7)
baseDirFollowsSourceFile() // (8)
configurations 'asciidoctorExt' // (9)
dependsOn test // (10)
doFirst {
delete file('src/main/resources/static/docs') // (11)
}
}
task copyDocument(type: Copy) { // (12)
dependsOn asciidoctor
from file('build/docs/asciidoc')
into file('src/main/resources/static/docs')
}
build {
dependsOn copyDocument
}
• (1) asciidoctor 플러그인을 추가해준다.
이 플러그인은 adoc 파일을 변환하고 build 디렉토리에 복사하기 위해 사용한다.
• (2) asciidoctorExt를 Configuration에 지정해준다.
• (3) dependencies에 spring-restdocs-asciidoctor를 추가해준다.
adoc 파일에서 사용할 snippets 속성이 자동으로 build/generated-snippets를 가리키도록 해준다.
• (4) MockMvc를 사용할 예정이기 때문에 spring-restdocs-mockmvc도 dependencies에 추가해준다.
• (5) snippets 파일이 저장될 경로를 설정한다.
• (6) 출력할 디렉토리를 설정해준다.
• (7) asciidoctor에서 asciidoctorExt을 configurations로 사용하도록 설정한다.
• (8) .adoc 파일에서는 다른 .adoc 파일을 include하여 사용할 수 있는데 그럴 경우 경로를 동일하게 baseDir로
설정해준다. Gradle 6 버전에서는 자동으로 해주지만 7부터는 직접 명시해줘야 한다.
• (9) input 디렉토리를 설정해준다.
• (10) build 시 test 후 asciidoctor를 진행하도록 설정해준다. (순서 설정)
• (11) 중복을 막기 위해 새로운 문서를 생성할 때에는 전에 생성했던 문서들을 먼저 지운다.
• (12) build/docs/asciidoc 디렉토리에 생성된 html 문서를 src/main/resources/static/docs 디렉토리에 복사한다.
• (13) copyDocument 후 build 지정
RestDocsConfiguration
@TestConfiguration
public class RestDocsConfiguration {
@Bean
public RestDocumentationResultHandler write() {
return MockMvcRestDocumentation.document(
"{class-name}/{method-name}", // (1)
Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), // (2)
Preprocessors.preprocessResponse(Preprocessors.prettyPrint())
);
}
}
• (1) 생성된 snippets를 class-name/method-name 디렉토리에 저장되도록 identifier를 설정한다.
예를 들어 MockMvcRestDocumentation.document("docs") 라고 작성해주면 생성된 snippets는
build/generated-snippets/docs 디렉토리에 저장된다.
• (2) snippets를 보기 좋게 생성하기 위해서 사용한다.
RestDocumentationResultHandler의 write 메소드에 지정 후 Bean으로 등록해주면 된다.
위 설정을 따로 Configuration으로 등록하지않고도 사용할 수 있지만
테스트 코드에 공통적으로 사용할 코드일 경우 중복되는 코드를 줄이기 위해 사용하는 것이 좋다.
AbstractRestDocsTests
Rest Docs에 대한 설정을 모든 테스트 클래스에 동일하게 작성해줄 필요는 없다.
abstract 클래스로 만들어 각 테스트 클래스들이 상속받아 사용하도록 만들었다.
@Import(RestDocsConfiguration.class)
@ExtendWith(RestDocumentationExtension.class)
public abstract class AbstractRouteFinderTests {
@Autowired
protected RestDocumentationResultHandler restDocs;
@Autowired
protected MockMvc mockMvc;
@BeforeEach
void setUp(
final WebApplicationContext context,
final RestDocumentationContextProvider restDocumentation) {
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(documentationConfiguration(restDocumentation))
.alwaysDo(MockMvcResultHandlers.print())
.alwaysDo(restDocs)
.addFilters(new CharacterEncodingFilter("UTF-8", true))
.build();
}
}
TestController 작성
이전에 작성한 게시물의 TestController 코드만 살짝 변경 후 테스트를 진행하겠다.
https://tlseoqja.tistory.com/59
[Spring Boot] 단위 테스트 코드 작성 (JUnit 5)
Unit 테스트 Java에서 지원하는 JUnit 프레임워크를 이용해 단위 테스트를 실시하는 것을 Unit 테스트라고 한다. @Test 어노테이션이 붙은 함수 및 메소드를 테스트하는 것이다. Spring에서 단위 테스트
tlseoqja.tistory.com
TestController
@RestController
@RequiredArgsConstructor
public class TestController {
private final TestService testService;
@PostMapping("/test")
public int sum(@RequestBody Map<String, Integer> request) {
return testService.sum(request.get("num1"), request.get("num2"));
}
}
API 테스트 코드 작성
작성한 API를 이용해 테스트 코드를 작성하겠다.
앞서 말했듯 andDo()를 사용해서 field에 대한 내용을 채워줘야하지만
상속받은 AbstractRestDocsTests에서 BeforeEach로 .alwayDo()를 설정해줬기 때문에
RestDocumentationHandler가 알아서 실제 응답에 따라 API를 생성해준다.
TestApplicationTests
@ExtendWith({RestDocumentationExtension.class})
@SpringBootTest
@AutoConfigureRestDocs
class RouteFinderApplicationTests extends AbstractRouteFinderTests {
@Test
void RestDocsTest() throws Exception {
mockMvc.perform(post("/test")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"num1\": 1, \"num2\": 2}")
)
.andExpect(status().isOk());
}
}
참고한 블로그에서는 @SpringBootTest 어노테이션 대신 @WebMvcTest 어노테이션을 사용했다.
하지만 SpringBootTest 어노테이션으로 변경한 이유는 JPA 사용 시 Bean을 못찾는 오류가 발생했기 때문이다.
이는 각 어노테이션의 기능이 다르기 때문인데 자세한 내용은 아래의 블로그를 참고하면 된다.
https://mangkyu.tistory.com/242
[Spring] 스프링부트 테스트를 위한 의존성과 어노테이션, 애플리케이션 컨택스트 캐싱(@SpringBootTes
스프링부트에서 테스트를 작성하기 위한 다양한 어노테이션(@SpringBootTest, @WebMvcTest, @DataJpaTest)들을 알아보도록 하겠습니다. 실제 테스트를 작성하는 방법은 이 포스팅을 참고해주세요. 1. 스프링
mangkyu.tistory.com
asciidoc 문서 작성하기
테스트를 진행 후 성공 시 아래와 같이 snippets가 생성된다.
이제 해당 snippets를 이용해서 adoc 문서를 작성하겠다.
먼저 src/docs/asciidoc 디렉토리를 생성하고 index.adoc 파일을 생성한 후 아래의 내용을 작성해준다.
include를 사용해서 다른 파일을 가져올 수도 있다.
= Spring REST Docs Test
:doctype: book
:source-highlighter: highlightjs
:toc: left
:toclevels: 2
:seclinks:
== TestController
operation::test-controller-test/rest-docs-test[snippets="http-request,http-response"]
생성된 html 화면
참고 사이트
프로젝트에 Spring Rest Docs 적용하기
진행하는 팀 프로젝트에서 API 문서화 도구로 사용하게 된 Spring Rest Docs에 대해 정리하고자 한다 💻
velog.io
'🛠️Backend > Spring' 카테고리의 다른 글
[Spring Boot] Launch4j과 jar 파일을 사용해서 실행 파일(.exe) 만들기 (0) | 2024.03.06 |
---|---|
[Spring Boot] jar 파일 실행 시 외부 폴더 이미지 찾아서 내려주기 (0) | 2024.02.15 |
[Spring Boot] 단위 테스트 코드 작성 (JUnit 5) (0) | 2024.01.02 |
[Spring Boot] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 13 (0) | 2023.06.17 |
[Spring Boot] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 12 (0) | 2023.03.19 |
댓글