우아한테크코스 테코톡
벡터의 Spring RestDocs와 Swagger 같이 사용하기
https://youtu.be/WiK3iUUZI0k?si=MoQw2zWhUB3Ghfe_
벡터의 Spring RestDocs와 Swagger 같이 사용하기
- 벡터의 Spring RestDocs와 Swagger 같이 사용하기
- Spring RestDocs와 Swagger를 함께 쓰는 방법: 신뢰성과 사용성을 동시에 잡는 API 문서화
- 왜 API 문서 자동화가 필요한가
- Swagger의 장점과 한계
- Spring RestDocs의 장점과 한계
- 그래서 왜 둘을 같이 써야 하는가
- restdocs-api-spec이 하는 일
- Gradle 설정에서 바뀌는 것
- 테스트 코드는 얼마나 바뀌는가
- OpenAPI YAML 파일은 어떻게 생성되는가
- Swagger UI와 연결하는 방법: 플러그인보다 정적 파일 방식이 낫다
- Swagger UI 정적 파일 방식의 흐름
- 이 방식이 실무에서 좋은 이유
- 도입할 때 주의할 점
- 마무리
Spring RestDocs와 Swagger를 함께 쓰는 방법: 신뢰성과 사용성을 동시에 잡는 API 문서화
API 문서는 단순한 참고 자료가 아니라, 팀과 팀 사이의 약속이다. 특히 프론트엔드와 백엔드가 함께 일할 때 문서는 “이 API가 어떻게 동작하는지”를 맞추는 가장 중요한 소통 수단이 된다. 문제는 이 문서를 사람이 직접 관리하면 실제 코드와 문서가 어긋나기 쉽다는 점이다. 발표에서도 “문서만 믿고 썼는데 실제 API와 달라서 시간을 낭비했다”는 상황을 예로 들며, 수동 관리의 한계를 짚는다.
이 문제를 해결하는 핵심은 자동화다. 그런데 스프링 환경에서 API 문서 자동화를 고민하면 보통 두 가지 선택지 앞에 서게 된다. Swagger와 Spring RestDocs다. 각각 분명한 장점이 있지만, 각각의 단점도 뚜렷하다. 흥미로운 지점은, 이 둘 중 하나를 포기할 필요가 없다는 점이다. 발표 자료의 핵심 메시지는 바로 여기에 있다. RestDocs의 신뢰성과 Swagger UI의 편의성을 함께 가져갈 수 있다.
왜 API 문서 자동화가 필요한가
혼자 개발하는 작은 프로젝트에서는 문서 없이도 어느 정도 버틸 수 있다. 하지만 여러 명이 함께 개발하기 시작하면 상황이 달라진다. 문서는 더 이상 부가 자료가 아니라 협업의 기준점이 된다. 그런데 이 문서를 손으로 관리하면 다음 문제가 반복된다.
첫째, 누락이 생긴다. 둘째, 실제 응답과 문서가 달라진다. 셋째, 프론트엔드나 다른 소비자가 문서를 믿고 개발했다가 다시 확인하는 비용이 커진다.
결국 좋은 API 문서는 “보기 좋게 정리된 문서”가 아니라, 실제 코드와 지속적으로 동기화되는 문서여야 한다. 그래서 자동화가 필요하다.
Swagger의 장점과 한계
Swagger의 가장 큰 장점은 즉시성이다. 설정 몇 줄과 어노테이션만으로 꽤 보기 좋은 UI를 빠르게 얻을 수 있다. 발표에서도 Swagger는 “압도적인 편리함과 즉시성”을 제공하고, 브라우저 안에서 직접 테스트도 가능하다고 설명한다.
실무적으로 Swagger가 사랑받는 이유는 명확하다.
- 문서 도입이 빠르다
- UI가 직관적이다
- 테스트 버튼이 있어 API를 곧바로 실행해볼 수 있다
하지만 단점도 분명하다. 발표에서 지적한 핵심은 두 가지다.
첫째, 신뢰성이 상대적으로 낮다. 문서가 실제 테스트 성공 결과에서 나오지 않기 때문에, 코드와 문서가 어긋날 여지가 있다. 둘째, 운영 코드가 문서화 어노테이션으로 오염된다. 비즈니스 로직은 단순한데, 컨트롤러와 DTO에 문서화 코드가 가득 붙으면서 가독성이 떨어진다.
즉, Swagger는 빠르고 편리하지만, 정확성과 코드 순수성 면에서는 아쉬움이 있다.
Spring RestDocs의 장점과 한계
반대로 Spring RestDocs는 철학이 다르다. 핵심은 편리함보다 정확성이다. RestDocs는 테스트가 성공해야만 문서 조각이 생성되므로, 문서는 실제 성공한 API 동작을 그대로 반영한다. 발표에서도 “문서대로 했는데 안 된다”는 문제가 원천적으로 줄어든다고 설명한다.
또 다른 장점은 운영 코드가 깨끗하게 유지된다는 점이다. 문서화 로직은 테스트 코드에만 존재하고, 운영 코드에는 남지 않는다. 즉, 문서화 때문에 컨트롤러나 DTO가 지저분해지지 않는다.
하지만 RestDocs에도 분명한 약점이 있다.
- 기본 결과물 UI가 투박하다
- Swagger처럼 문서에서 바로 API를 실행해보기 어렵다
- 설정과 테스트 작성이 더 복잡하다
- 초반 러닝 커브가 있다
즉, RestDocs는 믿을 수 있지만 덜 친절하다.
그래서 왜 둘을 같이 써야 하는가
여기서 자연스러운 질문이 생긴다.
“Swagger의 예쁜 UI와 RestDocs의 신뢰성을 동시에 가질 수는 없을까?”
발표의 답은 가능하다는 것이다. 핵심 연결 고리가 바로 OAS(OpenAPI Specification) 다. OAS는 특정 도구에 종속되지 않는 REST API 명세 표준이다. 과거에는 Swagger 명세라는 인식이 강했지만, 지금은 REST API를 기술하는 범용 표준으로 자리 잡았다. 발표에서는 OAS를 “RestDocs와 Swagger 두 세계를 이어주는 징검다리”라고 표현한다.
즉, 흐름은 이렇게 된다.
- RestDocs 기반으로 테스트를 돌려 신뢰성 있는 문서 데이터를 만든다
- 그 결과를 OAS 형식으로 변환한다
- Swagger UI가 그 OAS 파일을 읽어 화면에 보여준다
이렇게 하면 문서의 원천은 테스트 기반이라 신뢰할 수 있고, 사용자 경험은 Swagger UI 수준으로 가져갈 수 있다.
restdocs-api-spec이 하는 일
이 연결을 가능하게 해주는 핵심 라이브러리가 restdocs-api-spec 이다. 발표 자료에 따르면 이 라이브러리는 Spring RestDocs 결과물을 OpenAPI 명세로 바꿔주는 오픈소스 도구이며, ePages에서 만들고 유지보수하고 있다.
이 라이브러리를 쓰면 기존 RestDocs 테스트 흐름을 거의 유지한 채, 결과물을 OpenAPI YAML로 생성할 수 있다. 즉, 테스트 기반 문서화라는 RestDocs의 장점은 유지하면서, 결과물은 Swagger가 읽을 수 있는 형태로 바꾸는 것이다.
Gradle 설정에서 바뀌는 것
발표에서 설명하는 설정 흐름은 크게 세 가지다.
첫째, Gradle 플러그인을 추가한다. 이 플러그인이 RestDocs 결과를 OpenAPI 명세로 변환하는 핵심 역할을 한다. 플러그인을 추가하면 openapi3 같은 태스크가 생성된다.
둘째, OpenAPI 생성 태스크에 대한 설정을 추가한다. 셋째, 기존 RestDocs 의존성에 더해 restdocs-api-spec 관련 라이브러리를 의존성에 포함한다.
핵심은 “전체 구조를 뒤엎는 것”이 아니라, 기존 RestDocs 흐름 위에 OpenAPI 생성 단계가 하나 더 올라간다는 점이다.
테스트 코드는 얼마나 바뀌는가
이 부분이 가장 실용적이다. 발표에서는 기존 RestDocs 테스트 코드를 거의 바꿀 필요가 없다고 설명한다. 실제로 핵심 차이는 document() 메서드의 import 대상이 바뀌는 정도다. 예전에는 Spring RestDocs의 document 를 사용했다면, 이제는 restdocs-api-spec 쪽 wrapper가 제공하는 document 를 사용하면 된다.
즉, 테스트 기반 문서화 경험은 그대로 유지하면서, 결과물만 OpenAPI 친화적으로 바뀌는 셈이다. 이 점이 도입 장벽을 크게 낮춘다.
OpenAPI YAML 파일은 어떻게 생성되는가
전체 흐름을 정리하면 다음과 같다.
먼저 개발자가 작성한 테스트 코드가 실행된다. 이 테스트는 기존 RestDocs처럼 문서 생성의 원천이다. 테스트가 성공하면 RestDocs는 각 API에 대한 문서 조각을 만든다.
그다음 restdocs-api-spec 라이브러리가 개입한다. 이 라이브러리는 API 메타데이터를 정리해 resource.json 형태로 만든다. 그리고 Gradle 플러그인이 이 resource.json 들을 모아 하나의 완전한 OpenAPI YAML 파일로 합친다.
즉, 최종적으로 Swagger가 읽을 수 있는 openapi.yaml 이 생성된다.
핵심은 이것이다. 문서의 출처는 여전히 테스트다. 따라서 결과물은 Swagger 형식이지만, 신뢰성은 RestDocs에서 가져온다.
Swagger UI와 연결하는 방법: 플러그인보다 정적 파일 방식이 낫다
이제 OpenAPI YAML이 생겼다면, 그걸 어떻게 예쁜 UI로 보여줄지가 남는다. 발표에서는 두 가지 방법을 언급한다.
첫 번째는 Swagger Generator 같은 플러그인을 사용하는 방식이다. 하지만 이 방식은 추천하지 않는다. 발표 자료에서도 해당 저장소가 아카이브되었고, 2022년 이후 업데이트가 멈춘 점을 근거로 든다. 즉, 유지보수 리스크가 크다.
그래서 추천하는 방식은 두 번째다. Swagger UI 정적 파일을 직접 프로젝트에 넣는 방식이다.
Swagger UI 정적 파일 방식의 흐름
이 방식은 생각보다 단순하다.
먼저 Swagger UI 공식 GitHub 저장소에서 릴리스 소스 코드를 내려받는다. 압축을 풀면 dist 폴더가 있는데, 이 안이 실제 배포용 UI 파일들이다. 이 파일들을 스프링 부트 프로젝트의 src/main/resources/static 아래에 복사한다. 그러면 스프링이 정적 리소스로 그대로 서빙할 수 있다.
그다음 OpenAPI YAML 파일을 이 static 폴더 안으로 복사하는 Gradle 태스크를 하나 추가한다. 발표 예시에서는 copyOasToSwagger 같은 태스크를 만들고, 먼저 OpenAPI 생성 태스크가 실행되도록 dependsOn 을 설정한 뒤, 결과 YAML 파일을 static 폴더로 복사한다.
마지막으로 swagger-initializer.js 파일에서 기본적으로 지정된 petstore 예제 URL을 우리가 생성한 YAML 경로로 바꿔주면 된다. 그러면 Swagger UI는 우리가 만든 OpenAPI 명세를 읽어 실제 문서를 렌더링한다.
즉, 구조는 단순하다.
- RestDocs 기반 테스트 실행
- OpenAPI YAML 생성
- YAML을 Swagger UI 정적 파일 위치로 복사
- Swagger UI가 YAML을 읽어 화면 렌더링
이 방식이 실무에서 좋은 이유
이 방식은 단순히 “둘 다 쓴다” 수준이 아니다. 실무적으로 꽤 이상적인 균형을 만든다.
첫째, 문서의 신뢰성이 높다. 테스트 성공을 기반으로 생성되기 때문이다. 둘째, 운영 코드를 어노테이션으로 오염시키지 않는다. 셋째, Swagger UI의 탐색성과 실행 편의성을 그대로 누릴 수 있다. 넷째, OpenAPI라는 표준 형식을 얻기 때문에 다른 도구와도 연계가 쉬워진다.
즉, “정확한데 보기 불편한 문서”와 “보기 좋지만 코드와 어긋날 수 있는 문서” 사이의 딜레마를 꽤 잘 해결한다.
도입할 때 주의할 점
물론 장점만 있는 것은 아니다. RestDocs 자체의 러닝 커브는 그대로 존재한다. 테스트를 꼼꼼히 작성해야 하고, 문서 조각 관리도 필요하다. 또한 Swagger UI 정적 파일 방식은 한 번 세팅해두면 안정적이지만, 처음엔 파일 복사와 태스크 구성, initializer 수정까지 손이 간다.
하지만 이 초기 설정 비용을 넘기면 이후에는 꽤 편해진다. 문서가 깨지면 테스트가 먼저 알려주고, UI는 Swagger가 대신 보기 좋게 제공하기 때문이다.
마무리
Swagger와 Spring RestDocs는 자주 “둘 중 하나를 고르는 선택지”처럼 이야기된다. 하지만 실제로는 그렇지 않다. 발표가 보여주는 핵심은, 두 도구를 경쟁 관계로 볼 필요가 없다는 점이다. RestDocs는 정확한 문서의 출처가 되고, Swagger UI는 그 문서를 소비하기 좋은 화면이 된다. 이 둘을 이어주는 표준이 OAS이고, 이를 실현해주는 도구가 restdocs-api-spec 이다.
정리하면 흐름은 이렇다.
RestDocs로 테스트 기반 문서를 만든다. restdocs-api-spec 으로 OpenAPI 명세를 만든다. Swagger UI가 그 명세를 읽어 보여준다.
결국 이렇게 된다. 신뢰성 높은 API 문서와 사용하기 좋은 UI를 동시에 얻을 수 있다.
프로젝트에서 “Swagger냐 RestDocs냐”를 고민하고 있었다면, 이제 질문을 조금 바꿔볼 수 있다.
“둘을 어떻게 같이 써서 더 좋은 문서를 만들 수 있을까?”