개발팀에서 일하다 보면 API 문서화만큼 애증의 관계인 작업도 드뭅니다. 분명 중요한 일이고, 없으면 협업이 불가능하다는 걸 모두가 알지만, 막상 손대기 시작하면 끝없는 수작업과 동기화 문제에 직면하곤 하죠. 특히 RESTful API가 복잡해지고 서비스 규모가 커질수록, 개발자가 직접 문서를 작성하고 코드 변경에 맞춰 수동으로 업데이트하는 것은 거의 불가능에 가까운 일이 됩니다.
저 역시 수많은 프로젝트에서 API 문서의 비동기화 문제로 프론트엔드 개발팀, QA팀과 불필요한 커뮤니케이션 비용을 치렀던 경험이 많습니다. API가 변경되었는데 문서에는 반영되지 않아 프론트엔드 개발자가 엉뚱한 스펙으로 개발하거나, 새로운 필드가 추가되었는데 QA팀이 모르는 상태로 테스트를 진행해 버그를 놓치는 등의 상황 말이죠. 이런 문제를 해결하기 위해 여러 방법을 모색하던 중, OpenAPI와 Swagger를 적극적으로 도입하게 되었고, 그 과정에서 얻은 인사이트와 실전 전략을 공유하고자 합니다.
📑 목차
- OpenAPI/Swagger, 왜 이제는 필수 도구가 되었나?
- 전통적인 API 문서화의 문제점들
- 실제 적용해보니: OpenAPI 정의 파일 생성 전략
- 코드 기반 자동 생성 (Code-First Approach)
- 디자인 우선 접근 (Design-First Approach)
- 코드 기반 vs 디자인 우선: 우리 팀에 맞는 선택은?
- API 문서 동기화, 이대로는 안된다! CI/CD 파이프라인 통합
- Git 연동을 통한 버전 관리
- 빌드 자동화와 문서 배포
- 동기화 과정에서 겪었던 시행착오와 해결책
- 스펙 불일치 문제와 테스트 강화
- 협업 시 문서 업데이트 정책
- OpenAPI/Swagger의 확장 활용: Mock Server, 테스트 자동화
- Mock Server로 프론트엔드 개발 가속화
- Postman, Insomnia 연동으로 테스트 효율 증대
- 성공적인 OpenAPI/Swagger 도입을 위한 실전 팁
Image by RiaanMarais on Pixabay
OpenAPI/Swagger, 왜 이제는 필수 도구가 되었나?
과거에는 API 문서화를 위해 위키나 노션 같은 협업 도구에 수동으로 작성하거나, 코드 주석을 통해 간략하게 남기는 경우가 많았습니다. 하지만 이런 방식은 몇 가지 치명적인 단점을 가지고 있었습니다.
전통적인 API 문서화의 문제점들
- 잦은 불일치: 코드 변경 시 문서 업데이트를 잊어버려, 실제 동작과 문서 내용이 달라지는 경우가 빈번했습니다. 이는 프론트엔드, 모바일 앱 개발팀, QA팀, 심지어 외부 연동 파트너사에게까지 혼란을 야기했습니다.
- 유지보수 비용: API가 늘어날수록 문서를 수동으로 유지보수하는 데 드는 시간과 인력이 기하급수적으로 증가했습니다. 이는 개발팀의 생산성을 저해하는 주된 요인이었습니다.
- 일관성 부족: 여러 개발자가 문서를 작성하다 보면 포맷이나 상세 수준이 제각각이 되어, 문서를 읽는 사람이 혼란을 겪기 쉬웠습니다.
- 활용성 한계: 단순히 정보를 나열하는 수준에 그쳐, 테스트 자동화나 클라이언트 코드 생성 등 다른 개발 작업에 활용하기 어려웠습니다.
OpenAPI Specification (OAS)은 이러한 문제점들을 해결하기 위해 등장한 표준입니다. RESTful API를 기계가 읽고 사람이 이해할 수 있는 형식으로 기술하는 것을 목표로 합니다. 그리고 Swagger는 이 OpenAPI Specification을 기반으로 API 문서를 생성, 시각화, 테스트할 수 있도록 돕는 도구 모음입니다. 특히 Swagger UI는 웹 브라우저를 통해 API 목록을 탐색하고 각 엔드포인트의 상세 정보를 확인하며, 심지어 직접 API 호출까지 해볼 수 있는 강력한 기능을 제공합니다. 제가 직접 써보니, 이 두 가지 조합이 API 문서화의 패러다임을 완전히 바꾸어 놓았음을 실감했습니다.
실제 적용해보니: OpenAPI 정의 파일 생성 전략
OpenAPI 정의 파일을 만드는 방법은 크게 두 가지로 나눌 수 있습니다. 우리 팀이 어떤 개발 문화와 프로세스를 가지고 있는지에 따라 적합한 방식을 선택해야 합니다.
코드 기반 자동 생성 (Code-First Approach)
이 방식은 백엔드 코드에 주석이나 어노테이션을 추가하여 OpenAPI 정의 파일을 자동으로 생성하는 방식입니다. 스프링(Spring) 기반의 Java 프로젝트에서는 Springdoc-openapi나 Springfox 같은 라이브러리를, Python/Django에서는 drf-spectacular를, Node.js/Express에서는 swagger-jsdoc 등을 활용할 수 있습니다. 실제로 적용해 본 결과, 이 방식은 다음과 같은 장단점을 가졌습니다.
- 장점:
- 코드와 문서의 높은 동기화: 코드가 변경되면 문서는 자동으로 업데이트되므로, 수동으로 문서를 관리할 필요가 줄어듭니다. 이는 문서 불일치 문제를 근본적으로 해결하는 가장 강력한 방법입니다.
- 개발자 친화적: 익숙한 개발 환경에서 코드를 작성하며 바로 문서를 정의할 수 있어, 별도의 도구를 익힐 필요가 적습니다.
- 빠른 개발 속도: API 개발 완료와 동시에 문서가 생성되므로, 문서 작성에 드는 시간을 절약할 수 있습니다.
- 단점:
- 문서 작성 강제성: 모든 API에 대해 정확한 주석이나 어노테이션을 달아야 하므로, 개발자에게 추가적인 작업 부담이 될 수 있습니다. (그러나 이는 좋은 문서화를 위한 필수적인 노력이라고 생각합니다.)
- 디자인 선행 어려움: API 스펙이 확정되기 전에 프론트엔드 개발을 시작하거나, 외부와 스펙을 미리 공유하기 어려울 수 있습니다.
예를 들어, Spring Boot 프로젝트에서 Springdoc-openapi를 사용하는 경우, 컨트롤러 메서드에 간단한 어노테이션을 추가하는 것만으로 풍부한 문서가 생성됩니다.
@RestController
@RequestMapping("/api/v1/users")
@Tag(name = "사용자 관리 API", description = "사용자 정보를 조회하고 관리합니다.")
public class UserController {
@Operation(summary = "모든 사용자 조회", description = "시스템에 등록된 모든 사용자 목록을 반환합니다.")
@ApiResponse(responseCode = "200", description = "성공적으로 사용자 목록을 반환했습니다.")
@GetMapping
public ResponseEntity<List<UserResponse>> getAllUsers() {
// ...
return ResponseEntity.ok(userList);
}
@Operation(summary = "특정 사용자 조회", description = "사용자 ID로 특정 사용자의 상세 정보를 조회합니다.")
@Parameter(name = "userId", description = "조회할 사용자의 ID", required = true, example = "1")
@ApiResponse(responseCode = "200", description = "성공적으로 사용자 정보를 반환했습니다.")
@ApiResponse(responseCode = "404", description = "해당 ID의 사용자를 찾을 수 없습니다.")
@GetMapping("/{userId}")
public ResponseEntity<UserResponse> getUserById(@PathVariable Long userId) {
// ...
return ResponseEntity.ok(user);
}
}
디자인 우선 접근 (Design-First Approach)
이 방식은 API 개발 전에 OpenAPI 정의 파일을 먼저 작성하여 스펙을 확정하고, 그 스펙을 기반으로 백엔드 개발 및 프론트엔드 개발, 테스트를 진행하는 방식입니다. Swagger Editor, Stoplight Studio, Postman 같은 도구를 활용할 수 있습니다. 실제로 적용해보니, 이 방식은 다음과 같은 장단점을 가졌습니다.
- 장점:
- 선행 디자인 및 협업 용이: 개발 시작 전에 API 스펙에 대한 충분한 논의와 합의가 가능하며, 프론트엔드 개발팀이 Mock Server를 활용하여 백엔드 개발과 병렬로 작업을 시작할 수 있습니다.
- 일관된 스펙 유지: 모든 팀원이 동일한 스펙 문서를 참조하므로, 개발 과정에서 발생할 수 있는 오해를 줄일 수 있습니다.
- 품질 향상: API 설계 단계에서 오류를 발견하고 수정할 기회를 제공하여, 개발 후반부에 발생하는 문제를 줄일 수 있습니다.
- 단점:
- 코드와의 동기화 문제: 백엔드 코드가 변경될 때 OpenAPI 정의 파일도 수동으로 업데이트해야 하므로, 문서 불일치 위험이 다시 발생할 수 있습니다. (이를 해결하기 위한 전략은 다음 섹션에서 다룹니다.)
- 초기 학습 곡선: OpenAPI Specification 문법을 익히고 별도의 디자인 도구를 사용하는 데 시간이 필요할 수 있습니다.
코드 기반 vs 디자인 우선: 우리 팀에 맞는 선택은?
어떤 방식이 더 좋다고 단정하기는 어렵습니다. 팀의 규모, 프로젝트 특성, 개발 문화에 따라 최적의 선택이 달라질 수 있습니다. 제가 여러 프로젝트에 적용해 본 결과, 두 가지 방식을 비교하면 다음과 같습니다.
| 구분 | 코드 기반 (Code-First) | 디자인 우선 (Design-First) |
|---|---|---|
| 주요 장점 | 코드-문서 동기화 자동화, 개발자 친화적 | 사전 협업 용이, 병렬 개발 가능, 일관된 스펙 |
| 주요 단점 | 선행 디자인 어려움, 문서 작성 강제성 | 코드-문서 동기화 수동 관리, 초기 학습 필요 |
| 적합한 상황 | 내부 서비스, 백엔드 주도 개발, 빠른 MVP 개발 | 외부 연동 API, 복잡한 협업, 엄격한 스펙 관리 |
| 추천 도구 | Springdoc-openapi, drf-spectacular, swagger-jsdoc | Swagger Editor, Stoplight Studio, Postman |
최적의 전략은 이 두 가지를 혼합하는 것이라고 직접 경험을 통해 깨달았습니다. 초기에는 디자인 우선으로 핵심 API 스펙을 확정하고, 이후 백엔드 개발 과정에서는 코드 기반으로 문서를 자동 생성하여 동기화하는 하이브리드 접근 방식이 가장 효과적이었습니다. 이렇게 하면 초기 설계의 일관성을 유지하면서도, 개발 단계에서의 문서 불일치 위험을 최소화할 수 있습니다.
API 문서 동기화, 이대로는 안된다! CI/CD 파이프라인 통합
OpenAPI 정의 파일을 생성하는 것만큼 중요한 것이, 이 정의 파일을 최신 상태로 유지하고 배포하는 것입니다. 아무리 좋은 문서라도 최신 코드와 동기화되지 않으면 무용지물이 됩니다. 이 문제를 해결하기 위한 핵심 전략은 바로 CI/CD 파이프라인에 문서 생성 및 배포 단계를 통합하는 것입니다.
Git 연동을 통한 버전 관리
OpenAPI 정의 파일(.yaml 또는 .json)은 소스 코드와 함께 Git 저장소에 관리되어야 합니다. 특히 디자인 우선 방식으로 스펙을 작성했다면, 이 파일 자체가 API의 '단일 진실 공급원(Single Source of Truth)'이 됩니다. 코드 기반 자동 생성 방식의 경우, 라이브러리를 통해 런타임에 문서가 동적으로 생성되므로 별도의 파일 커밋이 필요 없을 수도 있지만, 빌드 시점에 정의 파일을 추출하여 Git에 버전 관리하는 것도 좋은 방법입니다. 이렇게 함으로써 문서의 변경 이력을 추적하고, 필요한 경우 과거 버전으로 되돌릴 수 있습니다.
빌드 자동화와 문서 배포
제가 실제로 적용해 본 가장 효과적인 방법은, 백엔드 서비스의 빌드 및 배포 과정에 OpenAPI 문서 관련 작업을 포함하는 것입니다. CI/CD 파이프라인은 다음과 같은 단계를 포함할 수 있습니다.
- 코드 빌드: 백엔드 서비스 코드를 빌드합니다. (예: Maven, Gradle, npm 등)
- OpenAPI 정의 파일 생성: 빌드된 코드에서 OpenAPI 정의 파일을 자동 생성합니다. (코드 기반 방식의 경우)
- 문서 유효성 검사: 생성된 OpenAPI 정의 파일이 유효한지 검사합니다. (예: `swagger-cli validate` 명령어 사용)
- 문서 배포: 생성/검증된 OpenAPI 정의 파일을 지정된 위치에 배포합니다.
- Swagger UI 호스팅: Swagger UI를 통해 웹 서버에 정적 파일로 호스팅합니다.
- 문서 관리 플랫폼 연동: Stoplight, Redocly, Postman과 같은 전문 API 문서 관리 플랫폼에 업로드합니다.
- API Gateway 연동: Amazon API Gateway, Azure API Management 등 API Gateway에 정의 파일을 연동하여 문서 및 Mock Server 기능을 활용합니다.
- 알림: 문서 배포가 완료되면 관련 팀(프론트엔드, QA)에 알림을 보냅니다.
다음은 GitHub Actions를 사용하여 Spring Boot 프로젝트의 OpenAPI 문서를 빌드하고 S3에 배포하는 간략한 예시입니다.
name: CI/CD Pipeline for OpenAPI Docs
on:
push:
branches:
- main
paths:
- 'src/main/java/**' # 백엔드 코드 변경 시 트리거
- 'pom.xml'
jobs:
build-and-deploy-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: 'maven'
- name: Build with Maven and Generate OpenAPI JSON
run: |
mvn clean package -DskipTests
# Springdoc-openapi는 애플리케이션 실행 시점에 JSON을 생성하므로,
# 이를 위한 별도의 프로파일/테스트 실행 또는 actuator 엔드포인트 호출 필요
# 예를 들어, 특정 포트에서 앱을 잠시 실행하고 curl로 호출하여 JSON 추출
java -jar target/*.jar &
sleep 30 # 앱이 완전히 시작될 때까지 대기
curl http://localhost:8080/v3/api-docs > openapi-spec.json
- name: Validate OpenAPI Spec
run: |
npm install -g @redocly/openapi-cli # 또는 swagger-cli
openapi lint openapi-spec.json
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2
- name: Deploy OpenAPI Spec to S3
run: |
aws s3 cp openapi-spec.json s3://${{ secrets.S3_BUCKET_NAME }}/api-docs/openapi-spec.json --acl public-read
- name: Invalidate CloudFront Cache (Optional)
run: |
aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} --paths "/api-docs/openapi-spec.json"
이처럼 CI/CD 파이프라인에 문서 자동 생성 및 배포 단계를 포함하면, 코드 변경과 함께 문서가 항상 최신 상태로 유지되므로 개발팀의 생산성을 크게 향상시킬 수 있습니다. 실제로 적용한 후, 프론트엔드 개발팀의 "문서가 최신이 아니에요!"라는 불평이 획기적으로 줄어들었음을 확인할 수 있었습니다.
Image by frankvouffa on Pixabay
동기화 과정에서 겪었던 시행착오와 해결책
물론, 모든 과정이 순탄했던 것은 아닙니다. OpenAPI/Swagger를 도입하고 CI/CD에 통합하면서 몇 가지 시행착오를 겪었고, 이를 통해 중요한 교훈을 얻었습니다.
스펙 불일치 문제와 테스트 강화
코드 기반 자동 생성 방식에서도 간혹 실제 API의 동작과 문서의 스펙이 미묘하게 불일치하는 경우가 있었습니다. 예를 들어, 특정 필드의 nullable 여부가 코드에는 반영되었지만 어노테이션을 누락하여 문서에는 반영되지 않는 식이죠. 이를 해결하기 위해 API 테스트 코드를 강화했습니다. 단순히 API가 200 OK를 반환하는지 확인하는 것을 넘어, 응답 JSON의 스키마 유효성을 검사하는 테스트를 추가했습니다. OpenAPI 정의 파일을 기반으로 응답 스키마를 검증하는 라이브러리(예: Java의 JSON Schema Validator)를 활용하여, 테스트 단계에서 문서 불일치를 조기에 발견할 수 있도록 했습니다. 이는 개발 후반에 발생하는 큰 문제를 사전에 방지하는 데 큰 도움이 되었습니다.
협업 시 문서 업데이트 정책
디자인 우선 방식이나 하이브리드 방식에서는 API 스펙 변경 시 팀원 간의 소통과 합의가 중요합니다. 단순히 코드를 변경하고 문서를 업데이트하는 것을 넘어, "어떤 API를 변경할 때 OpenAPI 정의 파일을 먼저 수정할 것인가?", "누가 변경 사항을 리뷰하고 승인할 것인가?" 와 같은 명확한 정책이 필요했습니다. 저희 팀은 다음과 같은 정책을 수립했습니다.
- 주요 API 변경 (필드 추가/삭제, 타입 변경 등): OpenAPI 정의 파일을 먼저 업데이트하고, 관련 팀(프론트엔드, QA)의 리뷰를 거친 후 백엔드 코드를 수정합니다.
- 사소한 변경 (설명 보강, 예시 추가 등): 백엔드 개발자가 직접 코드 주석/어노테이션을 수정하고, CI/CD를 통해 문서에 반영합니다.
- 정기적인 문서 리뷰: 스프린트 단위 또는 특정 마일스톤 도달 시점에, 모든 API 문서의 최신성을 확인하고 피드백을 주고받는 시간을 가졌습니다.
이러한 정책을 통해 문서 불일치로 인한 혼란을 크게 줄일 수 있었고, 협업의 효율성을 높일 수 있었습니다.
Image by 5851928 on Pixabay
OpenAPI/Swagger의 확장 활용: Mock Server, 테스트 자동화
OpenAPI/Swagger는 단순히 문서를 시각화하는 것을 넘어, 개발 프로세스 전반에 걸쳐 다양한 방식으로 활용될 수 있는 강력한 도구입니다. 제가 직접 경험하며 가장 유용하다고 느꼈던 두 가지 확장 활용법을 소개합니다.
Mock Server로 프론트엔드 개발 가속화
API 정의 파일이 있다면, 실제 백엔드 API가 개발되기 전에도 OpenAPI Mock Server를 사용하여 가상의 응답을 생성할 수 있습니다. 프론트엔드 개발팀은 이 Mock Server를 바라보며 백엔드 개발과 독립적으로 작업을 진행할 수 있습니다. 실제로 이 방식을 적용한 프로젝트에서, 프론트엔드 개발 속도가 약 20% 이상 향상되는 것을 확인할 수 있었습니다. 특히 백엔드 API 개발이 지연될 때 프론트엔드 개발이 멈추지 않고 계속될 수 있다는 점이 큰 장점이었습니다. Swagger Codegen, Stoplight Studio, Postman의 Mock Server 기능 등을 활용할 수 있습니다.
Postman, Insomnia 연동으로 테스트 효율 증대
OpenAPI 정의 파일은 Postman이나 Insomnia 같은 API 클라이언트에 바로 임포트하여 사용할 수 있습니다. 이렇게 되면 모든 API 엔드포인트, 요청 파라미터, 응답 스키마가 자동으로 설정되어, QA팀이나 다른 개발자가 API를 수동으로 테스트할 때 드는 시간을 획기적으로 줄일 수 있습니다. 또한, Postman Collection을 자동으로 생성하고 이를 활용하여 API 통합 테스트를 자동화하는 것도 가능합니다. 저희 팀은 Postman Newman을 CI/CD 파이프라인에 통합하여, 백엔드 배포 후 주요 API의 동작 여부를 자동으로 검증하는 데 활용했습니다. 이는 API의 안정성을 확보하고 릴리스 프로세스를 가속화하는 데 크게 기여했습니다.
성공적인 OpenAPI/Swagger 도입을 위한 실전 팁
OpenAPI/Swagger를 성공적으로 도입하고 팀의 생산성을 극대화하기 위해 제가 경험을 통해 얻은 몇 가지 실전 팁을 공유합니다.
- 팀 문화와 가이드라인 정립: 단순히 도구를 도입하는 것을 넘어, "API 문서는 항상 최신 상태여야 한다"는 팀 문화를 정립하는 것이 중요합니다. 어떤 정보가 문서에 포함되어야 하는지, 어떤 형식으로 작성해야 하는지 등에 대한 명확한 가이드라인을 만들고 공유해야 합니다. (예: 모든 요청/응답 필드에 대한 상세 설명, 예외 상황 처리, 인증 방식 명시 등)
- 지속적인 학습과 도구 업데이트: OpenAPI Specification과 관련 도구들은 끊임없이 발전하고 있습니다. 새로운 버전의 스펙이나 더 효율적인 라이브러리가 나오면, 이를 학습하고 적용하여 문서화 프로세스를 지속적으로 개선해야 합니다.
- 문서 소비자(프론트엔드, QA)와의 적극적인 소통: 백엔드 개발자만이 문서를 만드는 것이 아니라, 문서를 사용하는 프론트엔드 개발자나 QA팀의 피드백을 적극적으로 수용해야 합니다. 그들이 어떤 정보를 필요로 하는지, 어떤 부분이 불편한지 파악하여 문서를 개선해나가야 합니다. "문서는 사용하는 사람의 관점에서 작성되어야 한다"는 원칙을 잊지 마세요.
- 에러 응답 스펙 통일: API 에러 응답 스펙을 통일하고 OpenAPI에 명확히 정의하는 것이 매우 중요합니다. 에러 메시지, 코드, 상세 정보 등을 일관된 형식으로 제공하면 프론트엔드 개발자가 에러 처리를 보다 쉽게 구현할 수 있습니다.
OpenAPI/Swagger는 단순히 API 문서를 만드는 도구가 아니라, 개발팀의 협업 방식과 생산성을 혁신하는 강력한 플랫폼입니다. 처음에는 학습 곡선과 도입 비용이 발생할 수 있지만, 장기적으로는 개발 프로세스의 효율성 증대, 커뮤니케이션 비용 감소, 서비스 품질 향상이라는 엄청난 가치를 제공합니다. 여러분의 프로젝트에서도 OpenAPI/Swagger를 성공적으로 도입하여 API 문서화의 고통에서 벗어나시길 바랍니다.
여러분은 OpenAPI/Swagger를 어떻게 활용하고 계신가요? 혹시 제가 미처 다루지 못한 꿀팁이나 겪었던 재미있는 에피소드가 있다면 댓글로 공유해 주세요! 함께 더 나은 개발 문화를 만들어갈 수 있을 것이라 생각합니다.