Spring REST Docs

클라이언트 입장에선 어떤 API 가 있는지 모르므로 문서화가 필요하다.

개발자가 코드 수정하고 문서도 같이 수정 안하면 쌓이고 쌓여서 결국 코드기능과 문서 스펙이 일치하지 않을수있다


[Spring Rest Docs 장점]

  1. 운영코드에 영향이없다. (애노테이션이나 XML 같은게 없다)
  2. 변경시에도 Test 케이스 실행 후 문서를 최신화가 해서 생성해준다. 

설정방법이 그리 어렵지는 않고 순서대로 설명해주니 스프링 공식 문서를 참고하자.

 

build.gradle

본인 기준 설정을 마친 build.gradle 파일은 아래와 같으며 설정을 마쳤으면 코끼리를 돌리면 된다.

build.gradle 의 맨 아랫줄만 조금 다르고 나머진 다 같으니 맨 아래 부분만 이걸 참고하면 된다.

너무 길어서 접어놓았으니 필요 시 열어 보자.

더보기
plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.15'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
	// 플러그인 추가
	id "org.asciidoctor.jvm.convert" version "3.3.2"
}

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

java {
	sourceCompatibility = '11'
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
	// asciidoc 설정
	asciidoctorExt
}

repositories {
	mavenCentral()
}

ext {
	// 버전 관리용으로 상수로 뺀다
	asciidocVersion = "2.0.7.RELEASE"
	// test 를 통해 생성되는 asciiDoc 경로 지정
	snippetsDir = file('build/generated-snippets')
}

dependencies {
	// SpringBoot
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-validation'

	// RestDocs 
	asciidoctorExt "org.springframework.restdocs:spring-restdocs-asciidoctor:${asciidocVersion}"
	testImplementation "org.springframework.restdocs:spring-restdocs-mockmvc:${asciidocVersion}"

	// QueryDsl
	implementation "com.querydsl:querydsl-core"
	implementation "com.querydsl:querydsl-jpa"
	annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" // querydsl JPAAnnotationProcessor 사용 지정
	annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError(javax.annotation.Entity) 발생 대응
	annotationProcessor "jakarta.annotation:jakarta.annotation-api"

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

	// H2
	runtimeOnly 'com.h2database:h2'

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

tasks.named('test') {
	useJUnitPlatform()
}

// 대충 경로지정한단 뜻
test {
	outputs.dir snippetsDir
}

// 대충 테스트 진행하고 문서 생성한다는 뜻
asciidoctor {
	inputs.dir snippetsDir
	configurations 'asciidoctorExt'
	dependsOn test
}

// 대충 최종적으로 jar 파일 생성할때 asciidoc 도 같이 생성될 수 있게 한다는뜻
bootJar {
	dependsOn asciidoctor

	copy{
		from asciidoctor.outputDir
		into 'src/main/resources/static/docs'
	}
}

 

PostControllerDocTest

전에 @SpringBootTest 에서는 MockMvc 빈 주입이 안된다고 했었다.

여기서는 우리가 전에 했던 방식인 @AutoConfigureMockMvc 를 써서 의존성 주입을 받은게 아니라

아래처럼 @BeforeEach 에서 RestDoc 에 필요한 설정으로 MockMvc 를 직접 초기화 시켰다.

이제 기존에 하던것 처럼 테스트를 작성하면 asciidoc 이 생성된다. 단건 조회 테스트를 예시로 작성해보자.

@SpringBootTest
@ExtendWith(RestDocumentationExtension.class)
public class PostControllerDocTest {

    private MockMvc mockMvc;

    @Autowired
    private PostRepository postRepository;

    @BeforeEach
    void setUp(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .apply(documentationConfiguration(restDocumentation))
            .build();
    }

    @DisplayName("글 단건 조회 테스트")
    @Test
    void test1() throws Exception {
        // given
        Post post = Post.builder()
            .title("우리 이쁜 미카공주님")
            .content("우리 공주님")
            .build();
        postRepository.save(post);

        this.mockMvc.perform(
            MockMvcRequestBuilders.get("/posts/{postId}", 1L)
                .accept(MediaType.APPLICATION_JSON)
            )
            .andExpect(status().isOk())
            .andDo(print())
            .andDo(document("index"));
    }
}

 

테스트를 수행하면 위 사진처럼 generated-snippets 폴더에 asciidoc 파일들이 생성됨을 확인할 수 있다.

테스트 맨 아랫줄에 작성한 .andDo(document("폴더이름")) 으로 폴더 이름을 설정할 수 있다.

해당 폴더 안에 HTTP 요청 및 응답 정보, 요청 및 응답의 body 정보가 asciidoc 으로 생성된다.

 

그런 다음 아래처럼 src 폴더 아래에 src.docs.asciidoc 폴더를 만들고 asciidoc 폴더 안에 (폴더이름).adoc 파일을 만든다.

여기서는 index.adoc 으로 만들겠다.

 

 

index.adoc

그리고 그 adoc 파일에 아래와 같은 양식으로 위에서 생성했던 asciidoc 중 원하는 걸로 설정한다.

인텔리제이에서 이쁘게 보라고 플러그인 설치하라고 하는데 설치하면 오른쪽에서 미리보기를 볼 수 있다.

마크다운 문법과 비슷하다.

= 미카 공주님 API
:toc:

== 글 단건 조회

=== 요청

include::{snippets}/index/http-request.adoc[]

=== 응답

include::{snippets}/index/http-response.adoc[]

=== CURL

include::{snippets}/index/curl-request.adoc[]

ㄴ :toc:

적용하면 아래처럼 목차를 표현할 수 있다.

 

 

+ Recent posts