pile·
백엔드·마켓컬리마켓컬리 Hello World·

내가 만든 API를 널리 알리기 - Spring REST Docs 가이드편

컬리 신규 입사자가 선물하기 시스템을 재개발하며 API 문서화 도구로 Spring REST Docs를 택한 이유와, 정적 문서의 아쉬움을 Swagger UI 결합으로 보완한 과정을 다룬다. Swagger(Springdoc)와의 장단점 비교가 중심이다.

핵심 포인트
  • Swagger는 상세 정보를 넣을수록 운영코드에 애노테이션이 침투하는 반면, Spring REST Docs는 테스트 작성을 강제해 문서 신뢰도를 높인다.
  • Springdoc은 기본 설정만으로 Swagger-UI를 렌더링하지만, 풍부한 정보를 주려면 결국 애노테이션을 운영코드에 넣어야 한다.
  • Spring REST Docs는 테스트 실행으로 Asciidoc 스니펫을 만들어 asciidoctor로 HTML을 조합하며, API 변경 시 누락을 테스트가 즉시 잡는다.
  • 정적 문서의 단점은 restdocs-api-spec으로 OpenAPI(OAS) 문서를 생성해 Swagger-UI로 동적 확인하도록 보완했다.
상세 정리
  • 배경: Wiki 문서로 된 기존 API 문서가 탐탁치 않아 선물하기 재개발 때 Spring REST Docs로 전환했고, 예제 프로젝트를 별도로 공개했다.
  • 도구 선택지: Java REST 문서화 도구로 Swagger, Spring REST Docs, RAML이 있으며 RAML은 사실상 제외된다.
  • Swagger 침투성: Springfox는 2020년 이후 활동이 없어 Springdoc을 권하지만, Springdoc도 기본 제공 정보는 밋밋해 상세화하려면 스웨거 애노테이션이 운영코드로 침투한다.
  • Springdoc 기본 동작: springdoc-openapi-ui 의존성만 추가하면 swagger-ui.html 경로로 UI를 볼 수 있고, 애노테이션 없이도 컨트롤러 클래스명을 케밥 태그로, 파라미터 클래스를 스키마로 추출한다.
  • REST Docs 원리: 문서에 포함될 스니펫을 얻으려면 반드시 테스트를 작성해야 하며, 스니펫에 오류가 있으면 테스트가 실패해 서비스 안정성을 보장한다.
  • 테스트 프레임워크: Spring MVC Test, WebFlux WebTestClient, REST Assured로 테스트를 작성해 스니펫을 생성하고 asciidoctor로 HTML로 렌더한다.
  • 커스텀 스니펫 함정: 사용자 정의 스니펫은 src/test/resources/org/springframework/restdocs/templates/asciidoctor 경로에 둬야 하는데, IntelliJ에서 패키지 표기(점)로 등록하면 적용이 안 될 수 있어 버전별 경로 확인이 필요하다.
  • 로컬 테스트 보안: 문서에서 API를 직접 호출하려면 CORS·CSRF·FrameOption을 비활성화해야 하는데, 반드시 local/dev/stage 프로파일에서만 적용하도록 WebSecurityConfig를 분리했다.
  • Swagger 결합: restdocs-api-spec으로 테스트 코드를 거의 공유하면서 OAS(openapi3.yaml)를 생성, MockMvcRestDocumentationWrapper.document로 REST Docs 스니펫과 OAS를 동시에 만든다.
  • 패키징: bootJar 태스크에서 build/docs/asciidoc 산출물과 openapi3.yaml을 jar 정적 리소스로 포함해, 스프링 부트 정적 파일 지원으로 Swagger-UI와 문서를 함께 서빙한다.
  • 결론: 두 도구는 각자 장단점이 있어 엔지니어가 선택할 문제지만, 테스트로 신뢰감을 높인다는 점에서 저자는 Spring REST Docs를 권한다.
왜 읽나Spring 기반 API 문서화에서 Swagger와 REST Docs를 저울질하거나 둘을 결합하려는 백엔드 개발자에게.
마켓컬리
마켓컬리 Hello World 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 백엔드·github-engGitHub Engineering·

    조기 종료를 없애야 벡터화된다 — 메모리 속도 소스 코드 케이스 폴딩

    GitHub의 코드 검색 엔진 Blackbird는 480TB 이상의 소스 코드를 인덱싱하기 전 모든 바이트에 case folding을 적용한다. 이 글은 Rust로 구현한 case folding을 메모리 대역폭 한계(45+ GiB/s)까지 끌어올린 두 가지 반직관적 최적화를 상세히 다룬다. 핵심은 루프 조기 종료(break) 제거로 LLVM 벡터화를 유도하고, UTF-8을 디코딩하지 않고 바이트 공간 산술만으로 fold를 수행하는 것이다.

    #rust#unicode#simd+2
  2. 백엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    트랜잭션 스크립트에서 숙소 메타 + 가격 계산 모듈로 — 전시 아키텍처 개선기 (2/3)

    여기어때 전시개발팀이 숙소 상세(PDP) API를 해부한 결과, 코드상으로는 DB 호출 3번처럼 보이던 요청이 실제로는 MongoDB $lookup 체인으로 컬렉션을 19회 접근하는 구조였다. 이 트랜잭션 스크립트 방식의 핵심 문제는 "aggregation이 I/O를 가린다"는 점으로, 독립적인 쿼리 10개가 단일 파이프라인에 직렬화되어 병렬화 기회를 잃고, 가격 때문에 거의 안 바뀌는 이미지까지 매 요청마다 읽어야 하는 읽기 증폭이 발생했다. V3에서는 "조회 시점 조립"을 "쓰기 시점 사전 조립"으로 전환하고, 화면별로 복제되던 가격 계산 로직을 goodsprice 단일 모듈로 수렴했다. 4개 API(PLP/PDP/RDP/ILP)의 반복 마이그레이션은 Claude Code skill로 절차를 고정하고 쉐도잉 + 동일성 검증으로 안전망을 마련하는 방식으로 진행됐다.

    #architecture#migration#caching+2