간단히 말해 스웨거란 API를 명세, 관리하여 사용자들이 보다 더 쉽게 알 수 있도록 도와주는 것.
회사 내의 다른 개발팀과 협업을 했어야했던 적이 있는데, 그 팀에서 API명세를 엑셀로 정리해서 줬던 적이 있는데 그게 제가 처음으로 본 API명세였습니다.
(저희 팀엔 API명세에 대한 것이 존재하지 않았습니다.)
다른 팀과의 협업을 하며 API명세가 있어야 서로 간의 소통이 명확하고 더 효율적으로 일을 하는 것 같은 느낌을 받았고, 저희 팀에서 내가 작업하지 않은 부분에 대해 유지보수를 해야할 경우에 API명세에 대한 필요성을 느꼈습니다.
Swagger-autogen이라는 라이브러리가 있어서 그냥 간단하게 해결이 될 줄 알았습니다..
.
.
프로젝트에 Swagger-autogen을 추가하고 간단한 설정을 한 후, 실행을 시켰는데.. 몇분이 지나도 터미널 창이 반응이 없었습니다..
.
.
기존 프로젝트의 API양이 너무 많아 명세 파일을 생성하는 데 시간이 많이 소요되었고, 앞으로 API가 추가될 때마다 똑같은 상황을 겪는다는 생각에 다른 방법을 찾아야했습니다..
많은 API를 기능별로 쪼개서 점진적으로 확장해나가자..!
기능별로 API들이 파일 분리가 되어있었고, 아무리 자동으로 문서화를 해준다곤 하지만 각 API별 설명을 전부 추가해준다는 것은 불가능해보였기에 기능별로 Swagger를 적용하기로 결정했습니다.
처음 Swagger를 도입하는 것이었기 때문에 적용하는게 문제가 되진 않을지, 적용을 하더라도 편하게 쓸 수 있을지에 대한 고민을 많이 했습니다.
기능별로 쪼개기는 결정을 했고..
태깅을 통해 API그룹화는 할 수 있었는데, 점진적으로 확장한다는 측면에서는 그룹화를 한다고 하더라도 한 페이지에 너무 많은 양의 API가 나열된다는 문제점이 있었습니다.
다양한 시도 끝에 Swagger 생성 옵션에 urls를 기능별로 추가해주면 아래와 같이 각 기능별로 페이징해서 볼 수 있다는 것을 알았고, 이 방법으로 기능별로 각각 분리해서 볼 수 있도록 처리했습니다.
의도하지 않은 API 오픈은 보안상 굉장히 취약할 것이라는 생각에 Swagger의 문서화는 운영 도메인에서는 접근을 할 수 없도록 처리가 필요했습니다.
허용된 계정만 접근이 가능하게 하는 것을 고려해봤는데, API문서를 보는데 로그인까지 한다는 것이 좀 과하다는 생각이 들어서 다른 방법을 찾아야했습니다.
API문서는 내부에서만 보면 되는 것이었기 때문에 내부테스트 환경에서만 Swagger가 라우팅되도록 설정을 하여, 운영환경에서는 API가 오픈이 되지않도록 처리했습니다.
저희 프로젝트에서는 기능별로 쪼개서 Swagger를 적용시켜야했기에, 간단하게 문서화가 바로 되는 것은 아니었고 조금의 셋팅이 필요했습니다.
따라서 다른 팀원분들도 잘 활용할 수 있도록 초기 셋팅을 간단하게 최적화하는 방법에 고민을 많이 했습니다.
Swagger 설정값들을 json파일로 만들어 각 기능별 Swagger가 추가될 때마다 자동으로 url이 생성될 수 있도록 라우팅 처리 부분에 아래와 같이 처리했습니다.
const options = require('./swagger/options.json');
options.swaggerOptions.urls.forEach((v) => {
app.get(v.url, (req, res) => res.json(require(v.path)));
});
그리고 문서화된 파일을 생성시켜줘야하는데 이 부분도 package.json에 스크립트를 설정해놔서 좀 더 편리하게 쓸 수 있도록 했습니다.
npm run swagger --target=test
// test 기능으로 분류된 api들의 문서화
프로젝트 구조가 각양각색이기에 예시는 저희 프로젝트 구조 기준입니다..!
swagger 관련 라이브러리 설치npm install swagger-autogen swagger-ui-express --save-dev
./server/routes/swagger 폴더 생성
각 기능별 swagger 파일 생성ex) ./server/routes/swagger/test.js
swagger에 등록하기 위한 output 파일(api 명세서) 생성ex) node ./server/routes/swagger/test.js
ex) npm run swagger --target=test
swagger-autogen 라이브러리로 인해 자동 생성되는 것!
swagger option 파일 생성./server/routes/swagger/options.json
urls내에 각 기능별 내용을 추가하여 swagger에 등록
./server/index.js에 swagger 설정
실서버에 스웨거 설정을 하게 되면 외부에도 api리스트가 공개가 되기 때문에 실서버는 설정하지 않음
#swagger.옵션
을 주석으로 넣어서 설정한다.(자세한건 아래 참고-SwaggerAutuGen 공식문서 참고)
옵션 | 설명 | 비고 |
---|---|---|
tags | api 태그 | |
summary | api 요약 | |
description | api 설명 | |
produces | api의 태그를 달아줌 | |
parameters | 파라미터를 정의 | #swagger.parameters['parameterName'] = { in: <string>(ex. path, header, query, body, formData... / default: query), description: <string>, required: <boolean>, type: <string>, format: <string>, schema: <array>, <object> 또는 <string> } |
requestBody | 요청 본문을 구현 | #swagger.requestBody = { required: true, schema: { $ref: "#/definitions/sample" } } |
responses | 응답을 정의 | #swagger.responses[<number>] = { description: <string>, schema: <array>, <object>, <string>, <number> or <boolean> } |
deprecated | 사용되지 않은 api |
하나의 파일을 통으로 tag 설정을 하려면 router.use 부분에 태그를 추가해준다.
router.use( '/add', add
//#swagger.tags = ['AddTest']
//#swagger.deprecated = false
);
output 파일 생성 시, SyntaxError: Invalid regular expression 오류가 발생하는 경우가 있음.
오류메세지를 통해 발생한 위치 파악 후 주석 처리하면 해결되긴 함.
하지만,, 주석 처리를 해버리면 동작에 필요한 코드인 경우 문제가 발생할 수 있음..
이 경우 API함수가 Arrow Function 형태로 바꾸면 해결되는 경우가 있었음.
저희 회사엔 QA가 따로 있진않지만 PM님들이 테스트도 진행해주십니다.
테스트를 하시면서 특수한 케이스를 만들기 위해 DB조작 요청을 할 때가 많은데,(예를 들어, 회원 정보에 전화번호가 없는 케이스) 매번 요청을 주고 받는 것이 효율적이지 못하다는 생각이 있었습니다.
Swagger적용을 하던 중 간단한 API 호출 테스트를 할 수 있다는 것을 알게되었고, 테스트 진행에 필요한 간단한 API를 만들어 Swagger로 문서화를 한 후, 테스터들이 직접 API를 호출해 DB조작을 할 수 있도록 하면 테스트도 원활하게 진행될 수 있을 것이라 생각했습니다.
결과적으로 테스터들이 사용할 수 있도록 매뉴얼을 따로 작성/공유하여 테스트를 더 원활하게 진행할 수 있게 되었습니다.
(PM 한 분이 너무 좋은 기능이라고 칭찬해주셨습니다. ^^)