백엔드 개발자로서 API 문서화는 선택이 아닌 필수라고 생각합니다. 개발자들과의 원활한 협업, API 사용법 공유, 테스트 용이성 등 문서화가 가져오는 이점은 매우 큽니다. NestJS에서는 Swagger를 통해 비교적 쉽게 API 문서화를 구현할 수 있습니다.
이번 글에서는 제가 지금까지 스웨거를 작성하며 느낀 불편함들과 이를 개선한 여정과 나아가 라이브러리로 배포한 과정을 작성해보겠습니다.
지금까지 진행한 스웨거 작성 방식과 개선 사항들
처음 스웨거 문서에서 제공하는 방식으로 진행한 프로젝트는 규모가 커질수록 문서화에 투입되는 리소스는 기하급수적으로 증가했습니다.
특히 다음과 같은 코드는 가독성을 심각하게 해쳤습니다.
@ApiOperation({ summary: '강의 패스권 생성' })
@ApiBody({ type: CreateLecturePassDto })
@ApiResponse({
status: 201,
description: '강의 패스권 생성 성공',
schema: {
example: {
statusCode: 201,
data: {
// 수십 줄의 예시 데이터...
}
}
}
})
@ApiResponse({
status: 400,
description: '잘못된 요청',
// 더 많은 스키마 정의...
})
@Post('/lecture')
@UseGuards(LecturerAccessTokenGuard)
async createLecturePass() {
// 실제 비즈니스 로직은 여기에...
}
프로젝트 중반에 이르자 이 문제는 무시할 수 없는 수준이 되었습니다. 개발 속도가 느려졌고, 문서화 품질도 개발자에 따라 들쑥날쑥했습니다. 팀원들도 API 문서화에 많은 시간을 소모하며 스트레스를 호소했습니다.
첫 번째 접근법으로 NestJS의 applyDecorators 함수를 활용해 여러 데코레이터를 하나로 통합했습니다:
// 여러 데코레이터를 하나로 통합
export function ApiCreateLecturePass() {
return applyDecorators(
ApiOperation({ summary: '강의 패스권 생성' }),
ApiBody({ type: CreateLecturePassDto }),
ApiResponse({
status: 201,
description: '강의 패스권 생성 성공',
schema: { /* ... */ }
}),
ApiResponse({
status: 400,
description: '잘못된 요청',
schema: { /* ... */ }
})
);
}
// 컨트롤러에서 사용
@ApiCreateLecturePass()
@Post('/lecture')
@UseGuards(LecturerAccessTokenGuard)
async createLecturePass() {
// 비즈니스 로직
}
이 방식은 즉각적인 효과가 있었습니다.