[Spring] 프로젝트에 Spring REST Docs 적용

2023. 8. 17. 23:04초기 과업/BackEnd

작성자알 수 없는 사용자

728x90
반응형

 

안녕하세요. 기깔나는 사람들에서 백엔드를 맡고있는 황시아입니다.

크루 합류 후 초기과업을 진행하게 되면서 Spring REST Docs를 적용하게 되어서 그 과정을 적어보려 합니다.

 


Spring REST Docs

Spring REST Docs는 API 문서 생성 자동화 도구로서 이 분야에서는 Swagger와 함께 양대산맥입니다.

Spring REST Docs는 작성한 테스트코드가 통과되었을 때에만 API 문서가 생성되기 때문에 작성된 문서의 신뢰도가 높다는 장점이 있습니다.

 

Spring REST Docs는 아주 잠깐 써 봤지만, 둘 다 써본 입장에서는 처음 세팅만 잘 해 놓으면 Spring REST Docs가 훨씬 편했습니다. 왜냐하면 Spring REST Docs에서는 비즈니스 로직에 Swagger처럼 설명을 위한 어노테이션을 달지 않아도 되기 때문입니다. test 폴더에서 작성한 테스트코드만 통과되면 알아서 문서 생성이 됩니다. 

 

그렇기 때문에 API 스펙에서 변경사항이 생기면 어노테이션을 일일이 수정해줘야 하는 Swagger에 비해 신뢰도가 높아지고 손이 훨씬 덜 갑니다. API 스펙이 처음 한 번만 작성되고 나중에 변경되지 않는 일은 절대로 일어날 수 없기 때문에 Swagger를 사용한다면 수많은 어노테이션들을 일일이 수정해줘야 하죠... 그러다 누락되는 부분도 생기고요. Swagger를 써 보신 분들은 공감하실 것입니다.

 

하지만 Swagger는 테스트코드를 작성하지 않아도 문서를 만들 수 있는 반면, Spring REST Docs는 테스트코드를 작성하지 않으면 문서가 생성되지 않기 때문에 테스트코드 작성을 위한 부가적인 공수가 들어갈 수 있습니다. 그래서 두 도구의 장단점을 파악하셔서 프로젝트의 상황에 맞게 선택하셔서 적용하시면 될 듯 합니다.

 

그럼 이제부터 간략한 테스트코드와 함께 세팅 방법을 알아보겠습니다.

IDE는 인텔리제이 기준으로 작성되었습니다.


프로젝트 세팅

build.gradle

plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.14'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
	/**
	 * Asciidoctor 플러그인 적용
	 * gradle 7.0 이상부터는 jvm 사용
	 */
	id "org.asciidoctor.jvm.convert" version "3.3.2"
}

group = 'com'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '11'
}

configurations {
	asciidoctorExtensions // dependencies 에서 적용한 것 추가
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	// spring boot
	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'

	// h2
	runtimeOnly 'com.h2database:h2'

	// mariadb
	runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'

	// lombok
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testAnnotationProcessor 'org.projectlombok:lombok'

	testImplementation 'org.springframework.boot:spring-boot-starter-test'

	/**
	 * build/generated-snippets 에 생긴 .adoc 조각들을 프로젝트 내의 .adoc 파일에서 읽어들일 수 있도록 연동해준다.
	 * 이 덕분에 .adoc 파일에서 operation 같은 매크로를 사용하여 스니펫 조각들을 연동할 수 있는 것이다.
	 * 그리고 최종적으로 .adoc 파일을 HTML로 만들어 export 해준다.
	 */
	asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor'

	/**
	 * restdocs-mockmvc의 testCompile 구성 -> mockMvc를 사용해서 snippets 조각들을 뽑아낼 수 있게 된다.
	 * MockMvc 대신 WebTestClient을 사용하려면 spring-restdocs-webtestclient 추가
	 * MockMvc 대신 REST Assured를 사용하려면 spring-restdocs-restassured 를 추가
	 */
	testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
}

ext {
	// 아래서 사용할 변수 선언
	snippetsDir = file('./build/generated-snippets')
}

test {
	// 위에서 작성한 snippetsDir 디렉토리를 test의 output으로 구성하는 설정 -> 스니펫 조각들이 build/generated-snippets로 출력
	outputs.dir snippetsDir
	useJUnitPlatform()
}

asciidoctor { // asciidoctor 작업 구성
	dependsOn test                         // test 작업 이후에 작동하도록 하는 설정
	configurations 'asciidoctorExtensions' // 위에서 작성한 configuration 적용
	inputs.dir snippetsDir                 // snippetsDir 를 입력으로 구성

	/**
	 * source가 없으면 .adoc파일을 전부 html로 만들어버림
	 * source 지정시 특정 adoc만 HTML로 만든다.
	 */
	sources{
		include("**/index.adoc","**/common/*.adoc")
	}

	/**
	 * 특정 .adoc에 다른 adoc 파일을 가져와서(include) 사용하고 싶을 경우 경로를 baseDir로 맞춰주는 설정
	 * 개별 adoc으로 운영한다면 필요 없는 옵션
	 */
	baseDirFollowsSourceFile()
}

// static/docs 폴더 비우기
asciidoctor.doFirst {
	delete file('src/main/resources/static/docs')
}

// asccidoctor 작업 이후 생성된 HTML 파일을 static/docs 로 copy
task copyDocument(type: Copy) {
	dependsOn asciidoctor
	from file("build/docs/asciidoc")
	into file("src/main/resources/static/docs")
}

// build 의 의존작업 명시
build {
	dependsOn copyDocument
}

 

먼저 build.gradle을 위와 같이 작성합니다. 

저도 다른 블로그 글을 참고해서 작성한 것이라 중간중간 주석이 달려 있는데, 지금은 봐도 무슨 소리인가 싶으실 겁니다.

다음 단계를 진행하다 보면 자연스럽게 이해가 되니까 넘어갑시다.

 

테스트코드 작성

@RestController
public class TestController {

    @GetMapping("/api/restDocsTest")
    public String restDocsTestAPI() {
        return "test!!";
    }
}

 

테스트를 위한 정말 간단한 컨트롤러를 작성합니다.

일반적인 API 문서처럼 파라미터 정보도 작성을 하려면 단순하게 문자열만 리턴하면 안 되지만 제 글의 목적은 빠르고 간편하게 Spring REST Docs를 만들어 보는 것이기 때문에 넘어가겠습니다. 

 

https://backtony.github.io/spring/2021-10-15-spring-test-3/

 

Spring REST Docs 적용 및 최적화 하기

Java, JPA, Spring을 주로 다루고 공유합니다.

backtony.github.io

 

파라미터에 대한 자세한 작성법은 위 글을 참고하시는 것을 추천드립니다.

 

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestDocs
class TestControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    void test() throws Exception {
        mockMvc.perform(
                get("/api/restDocsTest")
                .contentType(MediaType.APPLICATION_JSON)
        ).andExpect(status().isOk())
                .andDo(
                        document("restDocsTest")
                );
    }
}

 

이제 테스트용 컨트롤러에 대한 테스트코드를 작성합니다. 

작성하다 보니 많은 부분을 static import 하게 되어 import문도 추가했으니 참고해서 작성하시면 되겠습니다.

 

 

작성한 테스트코드를 실행시키면 위와 같이 build 폴더 아래에 adoc 파일 조각들이 생깁니다.

이 조각들을 이용해서 API 문서를 작성할 수 있습니다.

 

index.adoc 만들기

문서를 만들기 전에 먼저 있으면 편한 플러그인 설치를 하고 가겠습니다.

 

 

adoc 파일을 미리 보고 편집할 수 있게 해주는 플러그인입니다. 

AsciiDoc 설치가 완료되셨다면, main/resources/static/docs 경로에 폴더를 생성합니다. 앞서 gradle 설정에 의해서 생성된 html 파일이 이 경로로 옮겨질 것입니다.

 

 

그 다음 src/docs/asciidoc 경로에 폴더를 생성한 다음 index.adoc 파일을 생성합니다.

 

= REST Docs 문서 만들기 (글의 제목)
:doctype: book
:icons: font
:source-highlighter: highlightjs // 문서에 표기되는 코드들의 하이라이팅을 highlightjs를 사용
:toc: left // toc (Table Of Contents)를 문서의 좌측에 두기
:toclevels: 2
:sectlinks:

[[Test-API]]
== Test API

[[restDocsTest]]
=== restDocsTest
operation::restDocsTest[snippets='http-request,path-parameters,http-response,response-fields']

 

생성된 파일에 위와 같이 작성합니다.

 

 

인텔리제이에서 AsciiDoc 플러그인을 설치하셨다면 위와 같이 미리보기가 제공되어서 작성하기가 한결 편하실 것입니다.

 

./gradlew build

 

이제 터미널에서 위 명령어를 입력해 빌드합니다.

 

 

빌드에 성공했다면 위와 같이 build/docs/asciidoc 폴더에 index.html 이라는 파일이 생기게 됩니다.

 

 

그리고 main/resources/static/docs 폴더에도 index.html이 복사가 되어 있는 것을 볼 수 있습니다. 이것 역시 아까 gradle에서 설정했던 것에 의해서 생성된 것입니다. 이제 이 파일을 웹에서 열어보시면...

 

 

위와 같이 API 문서가 생성된 것을 볼 수 있습니다.

그럼 이제 본격적인 개발을 시작하시면 되겠습니다.

감사합니다.

 

참고자료

🔗 - 

https://backtony.github.io/spring/2021-10-15-spring-test-3/

 

Spring REST Docs 적용 및 최적화 하기

Java, JPA, Spring을 주로 다루고 공유합니다.

backtony.github.io

https://velog.io/@chaerim1001/Spring-Rest-Docs-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-AsciiDoc-%EB%AC%B8%EB%B2%95

 

프로젝트에 Spring Rest Docs 적용하기

진행하는 팀 프로젝트에서 API 문서화 도구로 사용하게 된 Spring Rest Docs에 대해 정리하고자 한다 💻

velog.io

 

 

 

 

 

 

728x90
반응형