Introduction
Spring REST Docs는 정확하고 가독성 좋은 REST 문서를 제공하는 것을 목표로 한 Spring 프로젝트 중 하나이다.
Asciidoctor를 활용하여 테스트코드를 adoc으로 변환한 후 HTML로 변환시켜 주는데, 대안으로 Spring REST Docs는 Markdown을 사용할 수도 있다.
참고! adoc(Asciidoc)은 Markdown과 마찬가지로 문서 작성을 위한 경량형 마크업 언어입니다. 문서 자체는 .adoc 확장자의 text문서에 불과하고, Asciidoctor(https://asciidoctor.org/) 를 이용해 html이나 pdf등으로 변환하여 활용할 수 있다.
기본적으로 Spring MVC의 test freamwork에서 제공하는 MockMvc로 테스트 코드를 작성하여 사용한다. 그 외 Spring WebFlux의 WebTestClient, REST Assured 3에서도 적용할 수 있다.
장점은 테스트 코드로 REST API 문서를 작성해주기 때문에 테스트가 검증되어있다면 작성되는 문서 또한 신뢰할 수 있다는 장점이 있다.
자 이제 간단한 예제로 어떻게 테스트 코드로 REST API 문서를 만들어낼 수 있는 지 살펴보자.
사전준비
의존성 추가
spring-boot-starter-data-jpa
spring-boot-starter-web
spring-boot-starter-test
spring-restdocs-mockmvc
lombok
h2
Spring initializr(start.spring.io/)로 위와 같이 의존성을 추가해 프로젝트를 생성했다. spring-boot-starter-test은 web을 추가하면 자동으로 추가 된다.
자 위와 같이 프로젝트를 생성한 후 pom.xml을 보면 maven plugin 쪽에 아래와 같은 plugin이 추가돼있을 것이다.
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.8</version>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html</backend>
<doctype>book</doctype>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-asciidoctor</artifactId>
<version>${spring-restdocs.version}</version>
</dependency>
</dependencies>
</plugin>
Spring REST Docs는 Swagger와는 차이점이 있다. Swagger는 자바 코드로 REST API 문서 자체를 html로 자동으로 생성시켜준다. 하지만 Spring REST Docs는 Test로 생성된 Snippets들로 자신이 원하는대로 문서를 조합하여 REST API 문서를 만들 수 있다.
이를 위해 adoc이란 문서를 사용하는데, 위 플러그인 Asciidoctor가 바로 메이븐 빌드 시에 adoc을 html로 변환시켜 REST API 문서를 생성해주는 플러그인이다.
예제용 웹 어플리케이션 작성
예제용으로 간단한 웹 서비스를 만들어보았다.
예제용 도메인 Sample 엔티티
@Entity
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"name"})
public class Sample {
@Id @GeneratedValue
private Long id;
private String name;
public Sample(String name) {
super();
this.name = name;
}
}
예제용 SampleRepository
public interface SampleRepository extends JpaRepository<Sample, Long> {
List<Sample> findByName(String name);
}
예제용 SampleService
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class SampleService {
private final SampleRepository sampleRepository;
public List<Sample> getSamples() {
return sampleRepository.findAll();
}
}
예제용 SampleController
@RestController
@RequiredArgsConstructor
public class SampleController {
private final SampleService sampleService;
@GetMapping("/api/sample")
public List<Sample> getSamples() {
return sampleService.getSamples();
}
}
웹 어플리케이션을 구성을 끝 마친 후다음으로 테스트용 데이터를 아래와 같이 넣어줬다.
@Component
@RequiredArgsConstructor
public class init {
private final SampleRepository sampleRepository;
@PostConstruct
public void init() {
for (int i = 1; i <= 20 ; i++) {
sampleRepository.save(new Sample("sample" + i));
}
}
}
테스트 코드 작성
필자는 JUnit5의 예제를 보고 해당 글을 작성하니, Junit4의 예제를 보고 싶은 사람은 공식 문서에 JUnit4 Example을 확인하길 바람.
먼저 RestDocumentationExtension을 다음과 같이 Test 클래스에 적용한다.
@SpringBootTest
@ExtendWith({ RestDocumentationExtension.class, SpringExtension.class })
class DemoApplicationTests {
RestDocumentationExtension은 빌드툴(maven, gradle)에 따라 아래와 같이 산출물이 저장될 경로를 자동으로 설정해주는 역할을 한다.
Build tool | Output directory |
Maven |
target/generated-snippets |
Gradle |
build/generated-snippets |
그 다음 @BeforeEach 메소드를 통해 MockMvc를 테스트마다 주입해준다.
private MockMvc mockMvc;
@BeforeEach
public void setUp(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {
this.mockMvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.apply(documentationConfiguration(restDocumentation))
.build();
}
MockMvc에 추가적으로 설정할 수 있는 요소들은 공식문서를 참고
이제 Test를 통해 Snippets를 생성할 것이다. Snippets는 위에서도 언급했듯이 Test를 실행하면 생성되는 REST API 문서를 만들기 위한 adoc 문서이다. 이해가 안 된다면 좀 더 살펴보면 이해가 될 것이다.
@Test
void contextLoads() throws Exception {
this.mockMvc.perform(get("/api/sample").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(document("index"));
}
위의 Test 코드가 실행하여 성공했다면 아래와 같이 REST Docs에서 생성해주는 adoc파일들이 생성된다.
아래의 adoc들은 기본적으로 생성해주는 adoc들이며 테스트에 작성되는 코드에 따라 추가적인 adoc들도 제공한다.
자세한 것은 다음의 공식문서를 참고하자.
-
<output-directory>/index/curl-request.adoc
-
<output-directory>/index/http-request.adoc
-
<output-directory>/index/http-response.adoc
-
<output-directory>/index/httpie-request.adoc
-
<output-directory>/index/request-body.adoc
-
<output-directory>/index/response-body.adoc
별 다른 경로 설정이 없었다면, 아래와 같은 경로에 생성됐을 것이다.
Snippets를 활용해 REST API 문서 생성
자 이제 REST API 문서를 만들 준비가 끝났다. Snippets를 사용하기 위해서는 먼저 직접 .adoc 파일을 하나 만들어줘야 한다. 파일의 이름은 원하는대로 지어도 된다. 다만 생성되는 html 파일의 이름은 .adoc 파일의 이름과 동일하다는 점을 유의하자.
.adoc을 생성해줘야 하는 경로와 html 파일이 생성되는 경로는 빌드툴(maven, gradle)에 따라 다음과 같다.
Build tool | Source files | Generated files |
Maven |
src/main/asciidoc/*.adoc |
target/generated-docs/*.html |
Gradle |
src/docs/asciidoc/*.adoc |
build/asciidoc/html5/*.html |
필자는 api-docs.adoc으로 생성했고, 다음과 같이 Snippets를 조합했다.
= index
== get index
include::{snippets}/index/curl-request.adoc[]
include::{snippets}/index/http-request.adoc[]
include::{snippets}/index/http-response.adoc[]
이제 Maven이나 Gradle로 빌드를 하면 위 표를 참고하여 Generated files 경로를 보면 api-docs.html이 생성됐을 것이다.
생성된 REST API 문서는 다음과 같다.
소스코드 GitHub: github.com/KyeonghoYoo/spring-rest-docs-demo
Reference
Spring REST Docs 공식문서: docs.spring.io/spring-restdocs/docs/2.0.5.RELEASE/reference/html5/
'Study > spring' 카테고리의 다른 글
Spring Web MVC - Multipart 요청 다루기 (0) | 2021.02.23 |
---|---|
Spring Cache Abstraction 정리 (0) | 2021.02.09 |
QueryDSL(3) - 프로젝션, distinct, 동적 쿼리, 벌크 연산 (0) | 2021.01.26 |
QueryDSL(2) - 쿼리 생성 방법, 기본 문법 (0) | 2021.01.25 |
QueryDSL(1)- QueryDSL과 설정 방법 (0) | 2021.01.25 |