Redocly API 문서 빌드
KakaoPay v2를 구축하면서 API 문서 관리 방식을 근본적으로 바꾼 경험을 기록한다. 기존 API Blueprint 문법으로 작성한 .apib 문서 체계에서 Redocly 기반의 자동 빌드 체계로 전환했고, 이것이 API-first 설계 접근을 실현하는 핵심 도구가 되었다. 이 선택은 한 서비스 안에서 끝나지 않고, 이후 글로벌 결제 시스템 전반의 문서화 기준이 조금씩 바뀌는 출발점이 되었다.
왜 문서 자동화가 먼저였나
단순히 도구를 도입한 이야기가 아니다. 왜 API 스펙을 코드보다 먼저 작성해야 했는지, 그리고 CI 파이프라인에 API 문서 빌드를 통합하면서 겪은 Docker 환경의 exit code 핸들링 문제까지 포함하여 기록한다.
기존 APIB 문서의 어떤 점이 병목이었나
기존 결제 서비스들의 API 문서는 API Blueprint 문법으로 작성한 .apib 파일로 관리되고 있었다. 공식 문법 기준으로 보면 FORMAT: 1A, HOST, 리소스 그룹, 요청/응답 예시, 속성 블록을 텍스트 중심으로 쌓아가는 방식이다. 이 방식 자체가 틀린 것은 아니었지만, 실무에서는 불편한 점이 분명했다. 코드와 문서를 더 긴밀하게 묶고, 스키마 기반 모델링과 벨리데이션까지 연결하고, 파라미터와 응답 구조를 도구 체인 안에서 일관되게 다루는 데에는 한계가 있었다. 코드가 바뀔 때마다 문서를 수동으로 맞춰야 했고, 당연히 코드와 문서의 불일치가 빈번했다. 특히 다른 팀이나 글로벌 팀이 한국 결제 API를 사용할 때, 문서와 실제 API 동작이 다르면 통합 과정에서 시간이 낭비된다.
KakaoPay v2는 처음부터 새로 만드는 서비스였으므로, 이 문제를 구조적으로 해결할 기회가 있었다. 그래서 내가 먼저 APIB에서 OpenAPI로 기준을 옮기고, 스펙을 코드 저장소에 함께 관리하며, 빌드 시 자동으로 API 문서를 생성하는 흐름을 제안했다. 문서를 따로 적어두는 방식이 아니라, 스키마를 기준으로 모델링, 벨리데이션, 문서화가 함께 굴러가는 구조를 처음부터 잡자는 방향이었다.
물론 Swagger 계열 방식도 고려 대상이었다. 다만 코드에 annotation이 덕지덕지 붙기 시작하면, 문서화를 위해 도메인 코드가 오염되고 구조가 금방 지저분해진다는 부담이 있었다. 그래서 구현 코드에 문서 annotation을 과도하게 섞기보다는, OpenAPI 스펙 파일을 별도로 두고 Redocly로 관리하는 쪽이 더 낫다고 판단했다.
결국 이 결정은 단순히 도구 하나를 바꾼 일이 아니었다. 기존 APIB를 버리고 내가 설계한 문서-스키마-파이프라인 구조를 기반으로, 글로벌 결제 시스템의 문서화 방식과 공통화 방향도 점차 그쪽으로 옮겨가기 시작했다.
핵심 체크포인트
- 초기 구축 단계에서 가장 먼저 한 작업이 API 문서 구조를 잡는 것이었다. 코드를 작성하기 전에 API 스펙부터 정의하고, 기존 APIB 문서 기준을 하나의 OpenAPI 스펙 파일로 옮겨 재정리했다.
- API-first 접근이란 구현 코드보다 API 명세를 먼저 정의하는 방식이다. 이렇게 하면 프론트엔드(앱/웹), 글로벌 결제 코어, QA 팀이 모두 같은 API 스펙을 기준으로 병렬 작업할 수 있다. 구현이 끝나기 전에 목업(mock) 서버를 제공할 수도 있다.
- Redocly를 API 문서 도구로 선택한 이유는 네 가지였다. 첫째, OpenAPI 스펙을 직접 렌더링할 수 있어 별도 변환 없이 스펙 파일 자체가 문서가 된다. 둘째, 스키마와 문서를 함께 다루기 좋아 모델링과 벨리데이션 기준을 한 곳에서 맞추기 편했다. 셋째, Swagger annotation처럼 구현 코드에 문서 요소가 과하게 섞이지 않게 할 수 있었다. 넷째, CLI 도구가 제공되어 로컬과 CI 환경 모두에서 동일하게 동작하고 결과물을 정적으로 빌드할 수 있었다.
API Blueprint를 실제로 어떻게 썼나
API Blueprint 공식 문법은 문서 친화적이다. 최상단에 FORMAT: 1A와 HOST를 두고, 그 아래에 리소스 그룹과 액션, 요청/응답 예시를 Markdown처럼 이어 붙인다. 초기에 빠르게 문서를 써 내려가기에는 나쁘지 않았고, 읽는 사람 입장에서도 구조가 단순했다.
| 항목 | API Blueprint에서의 역할 | 실무에서 느낀 점 |
|---|---|---|
FORMAT: 1A | 문서가 API Blueprint 형식임을 선언 | 진입은 쉽지만 이후 구조화는 수작업 비중이 컸다 |
HOST | 기본 API 호스트 정의 | 환경별 분기 관리에는 별 도움이 되지 않았다 |
# Group | 리소스 묶음 | 문서 목차로는 좋았지만 스키마 재사용과는 거리가 있었다 |
+ Attributes | 요청/응답 속성 정의 | 읽기에는 좋지만 검증 규칙과 강하게 연결되진 않았다 |
+ Request / + Response | 예시 바디와 상태 코드 기술 | 예시는 풍부했지만 코드와 자동 동기화되지는 않았다 |
아래는 공식 문법 스타일에 가깝게 정리한 간단한 예시다.
FORMAT: 1A
HOST: https://api.example.com
# Group Stored Payments
## Stored Payment Registration [/stored-payments/registrations]
### Register [POST]
+ Request (application/json)
+ Attributes
+ provider: `kakaopay` (string, required)
+ customerId: `USER-12345` (string, required)
+ Response 200 (application/json)
+ Attributes
+ registrationId: `REG-20231018-001` (string, required)
+ status: `completed` (string, required)
+ sid: `SID-abc123xyz789` (string)문제는 여기서부터였다. 문서는 읽기 좋았지만, 스키마를 재사용해 검증하거나 모델과 직접 연결하기가 어려웠다. 결국 예시가 늘수록 문서와 구현을 같이 관리하는 부담이 커졌다.
Redocly/OpenAPI는 무엇이 달랐나
Redocly는 OpenAPI 문서를 렌더링하고, CLI로 lint와 문서 빌드를 수행하는 흐름이 명확했다. 우리에게 중요했던 건 단순히 예쁜 문서를 만드는 기능이 아니라, OpenAPI 스펙과 스키마를 코드 저장소 안에서 같이 관리하면서 자동 검증과 문서 빌드를 연결할 수 있다는 점이었다.
이때 전제로 깔려 있던 것이 하나 더 있었다. 앞 글에서 설명했듯이, 우리는 요청/응답 스키마를 공통 라이브러리와 함께 묶어 서비스 경계에서 재사용하고 있었다. 그래서 Redocly 글에서는 그 라이브러리 구현을 다시 길게 풀기보다, 이미 만들어둔 스키마와 OpenAPI 문서를 어떻게 한 파이프라인으로 묶었는지에 집중하는 편이 맞다. 그 구조 자체는 KakaoPay v2 신규 구축에서 더 자세히 다뤘다.
| 항목 | API Blueprint(.apib) | Redocly + OpenAPI 3.1 |
|---|---|---|
| 문서 작성 방식 | Markdown 중심 문법 | 스펙 중심 YAML/JSON |
| 스키마 재사용 | 제한적 | $ref로 적극 재사용 가능 |
| 검증 연계 | 약함 | lint, schema validation, tooling 연계가 강함 |
| 코드와 동기화 | 수동 관리 성격이 강함 | 저장소와 파이프라인에 같이 묶기 좋음 |
| 문서 배포 | 별도 조합 필요 | CLI로 빌드와 산출물 생성이 단순함 |
공식 CLI 흐름에 맞춘 가장 단순한 사용 예시는 아래와 비슷했다.
apis:
payment@v1:
root: openapi/payment.yamlopenapi: 3.1.0
info:
title: Payment API
version: 1.0.0
paths:
/stored-payments/registrations:
post:
summary: Register stored payment
requestBody:
required: true
content:
application/json:
schema:
$ref: './schema/stored-payment-registration-request.json'
responses:
'200':
description: ok
content:
application/json:
schema:
$ref: './schema/stored-payment-registration-response.json'redocly lint openapi/payment.yaml
redocly build-docs openapi/payment.yaml --output docs/payment.html문서 빌드를 배포 흐름에 어떻게 넣었나
KakaoPay v2의 초기 구축 단계에서 가장 먼저 한 작업이 API 문서 구조를 잡는 것이었다. 코드를 작성하기 전에 API 스펙부터 정의하고, 기존 APIB 문서 기준을 하나의 체계적인 OpenAPI 스펙 파일로 옮겨 재정리했다.
API-first 접근이란 구현 코드보다 API 명세를 먼저 정의하는 방식이다. 이렇게 하면 프론트엔드(앱/웹), 글로벌 결제 코어, QA 팀이 모두 같은 API 스펙을 기준으로 병렬 작업할 수 있다. 구현이 끝나기 전에 목업(mock) 서버를 제공할 수도 있다.
Redocly를 API 문서 도구로 선택한 이유는 네 가지였다. 첫째, OpenAPI 스펙을 직접 렌더링할 수 있어 별도 변환 없이 스펙 파일 자체가 문서가 된다. 둘째, 스키마와 문서를 함께 다루기 좋아 모델링과 벨리데이션 기준을 한 곳에서 맞추기 편했다. 셋째, Swagger annotation처럼 구현 코드에 문서 요소가 과하게 섞이지 않게 할 수 있었다. 넷째, CLI 도구가 제공되어 로컬과 CI 환경 모두에서 동일하게 동작하고 결과물을 정적으로 빌드할 수 있었다.
도입 과정에서 Redocly의 설정 파일(.redocly.yaml)을 구성하고, API 스펙 파일의 경로와 빌드 출력 경로를 정의했다. 스펙 파일은 src/main/resources/openapi/ 디렉토리에, 빌드 결과는 build/docs/에 생성되도록 했다.
여기서 중요했던 건 문서만 따로 만드는 구조가 아니었다는 점이다. 어차피 파라미터와 응답은 같은 스키마를 기준으로 벨리데이션하고 있었기 때문에, 문서화할 때도 그 스키마를 그대로 재사용하면 됐다. 즉 검증용 스키마와 문서용 스키마를 따로 관리하는 것이 아니라, 하나의 OpenAPI 스펙이 모델링, 벨리데이션, 문서화를 동시에 맡는 구조였다.
이 흐름은 전부 파이프라인에서 자동으로 돌았다. 스펙 lint, 문서 빌드, 산출물 생성, 내부 개발자 센터 등록까지 이어지도록 붙여두면, 다른 팀은 최신 API 명세를 보고 그대로 개발하면 됐다. 결국 Redocly/OpenAPI의 장점은 문서를 예쁘게 보여주는 것보다, 스키마 하나를 기준으로 협업 비용을 줄이는 데 있었다.
흥미로웠던 점은 이런 불편이 우리 팀만의 고민은 아니었다는 것이다. 다른 팀들도 APIB가 점점 답답해져 대안을 찾고 있었고, 내가 Confluence에 정리해둔 설계 문서를 보고 먼저 연락해온 경우도 있었다. 결국 다들 비슷한 지점에서 더 다루기 쉬운 구조를 찾게 되고, 한번 기준이 잡히면 그 구조는 생각보다 빠르게 퍼진다.
APIB 문서를 OpenAPI 기준으로 옮겼다
기존 문서 체계를 OpenAPI 스펙 하나로 재정리했다.
lint와 빌드를 CI에 붙였다
문서도 코드처럼 검증되도록 빌드 단계에 포함시켰다.
산출물을 배포 흐름과 연결했다
정적 문서 결과물이 내부 개발자 센터까지 자동 등록되도록 연결했다.
CI 예시 코드
문서와 코드를 함께 검증하려면 API 스펙 lint와 문서 빌드를 CI 단계에 고정하는 방식이 단순하다.
steps:
- name: Lint OpenAPI
run: redocly lint openapi/payment.yaml
- name: Build Docs
run: redocly build-docs openapi/payment.yaml --output docs/payment.html
- name: Publish Developer Portal
run: cp docs/payment.html developer-center/payment.html
- name: Upload Artifact
run: cp docs/payment.html artifacts/문서 자동화가 개발 속도를 지탱한 방식
이 글의 핵심은 문서를 예쁘게 만들었다는 데 있지 않다. API 명세를 코드와 같은 배포 흐름 안에 넣어두면, 구현과 문서가 함께 움직이고 팀 간 협업 비용도 줄어든다. 같은 스키마로 벨리데이션과 문서화를 같이 가져가고, 그 결과가 파이프라인을 통해 내부 개발자 센터까지 자동으로 반영되면, 다른 팀은 최신 명세를 보고 바로 개발을 이어갈 수 있다. KakaoPay v2에서 Redocly가 중요했던 이유는 바로 그 운영 기준을 만들었기 때문이다. 그리고 그 기준은 KakaoPay 한 서비스에만 머물지 않고, 글로벌 결제 시스템이 점차 더 공통화된 구조로 옮겨가는 데에도 영향을 줬다.
다음 글에서는 같은 맥락에서 품질 기준을 코드 구조로 밀어붙였던 테스트 커버리지 80% 이야기를 이어서 본다.