개발 블로그를 시작하며 – Spring REST Docs 도전기

gigyesik·2025년 5월 10일

개발 블로그를 시작하며 – Spring REST Docs 도전기

gigyesik의 블로그를 시작한다.
첫 글은 최근 경험한 Spring REST Docs 기반 API 문서 자동화 도전기를 다룬다.
기술을 공부하고 정리하는 과정 자체를 기록으로 남겨두기 위해 블로그를 시작했다.


🧭 블로그를 시작한 이유

개발을 하면서 마주치는 문제와 해결 과정, 익힌 기술을 정리해두고 싶었다.
개인 메모만으로는 검색도 어렵고 정리가 부족하다는 걸 느꼈고, 기록을 습관으로 만들기 위해 블로그를 택했다.


🚀 고민의 시작: Swagger vs Spring REST Docs

프로젝트에서 API 문서 자동화 도구를 선택해야 했다.
내부 API 문서를 외부에 공유해야 했고, 항상 최신 상태를 유지해야 했다.
Swagger UI는 편했지만 변경 사항이 반영되지 않거나 설명이 누락되는 경우가 종종 있었다.
기존에는 Swagger를 써왔지만, 이번엔 Spring REST Docs가 적합할 수 있다는 판단이 있었다.

Swagger

  • 빠르고 편리하다.
  • UI 기반으로 문서를 자동 생성해주기 때문에 개발 속도가 빠르다.
  • 하지만 문서 품질을 세밀하게 제어하기 어렵고, 실제 API와 동기화가 안 되는 경우가 종종 있었다.

Spring REST Docs

  • 테스트 코드 기반으로 문서를 생성한다.
  • 테스트가 실패하면 문서도 생성되지 않기 때문에, 항상 실제 동작과 문서가 일치한다.
  • 문서를 Asciidoctor 등으로 정교하게 구성할 수 있다.

고민 끝에 REST Docs를 선택했다.
자동화보다는 정확성이 중요했고, 테스트 코드로 API 품질을 높일 수 있다는 점도 매력적이었다.


🔧 Spring REST Docs 적용 과정

1. Gradle 설정

plugins {
    id 'org.asciidoctor.jvm.convert' version 'x.x.x'
}

ext {
    snippetsDir = file('build/generated-snippets')
}

dependencies {
    testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    outputs.dir snippetsDir
}

2. 테스트 코드 작성

@WebMvcTest(UserController.class)
@AutoConfigureRestDocs(outputDir = "build/generated-snippets")
class UserApiDocsTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    void 사용자_정보_조회_API_문서화() throws Exception {
        given(userService.getUserInfo(1L))
            .willReturn(new UserResponse("gigyesik", "gigyesik@gigyesik.dev"));

        mockMvc.perform(RestDocumentationRequestBuilders.get("/api/users/{id}", 1L)
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andDo(document("get-user-info",
                        pathParameters(
                            parameterWithName("id").description("사용자 ID")
                        ),
                        responseFields(
                            fieldWithPath("name").description("사용자 이름"),
                            fieldWithPath("email").description("이메일")
                        )
                ));
    }
}

3. asciidoctor 설정

asciidoctor {
    inputs.dir snippetsDir
    dependsOn test
    sourceDir = file("src/docs/asciidoc")
    outputDir = file("build/docs/asciidoc")
}

4. 문서 구성 예시

= API 문서
:toc: left
:toclevels: 2

== 사용자 정보 조회

=== 요청

include::{snippets}/get-user-info/http-request.adoc[]

=== 응답

include::{snippets}/get-user-info/http-response.adoc[]

=== 응답 필드 설명

include::{snippets}/get-user-info/response-fields.adoc[]

5. 빌드 후 결과

build/docs/asciidoc/index.html

docs 예시

HTML 문서가 생성되며, API 요청/응답 예시, 설명, 구조까지 정리된 문서를 확인할 수 있다.


🧩 시행착오와 배운 점

  • MockMvc의 컨트롤러 범위 설정을 잘못해 테스트가 실패했던 경험
  • responseFields 문서화 시 null 가능 필드 처리 주의
  • build.gradle 내 asciidoctor 설정이 누락되어 문서가 생성되지 않았던 문제

이 과정을 통해 REST Docs의 작동 구조를 좀 더 깊이 이해할 수 있었다.


📌 마무리

이 블로그를 경험을 정리하고 공유하는 공간으로 활용해보려 한다.
기술을 기록하는 과정을 통해 나 자신도 성장하고, 누군가에게 작게나마 도움이 되길 바란다.


👉 요약/입문자용 정리는 Tistory:
📎 Spring REST Docs 도전기 – Swagger 대신 선택한 이유

profile
Server Dev

0개의 댓글