본문 바로가기

개발-사용기/serverless 사용기

5. Typescript & Serverless 사용기 - swagger문서 자동화 2부

이번에 해볼 예제들은 다음을 전제로 진행된다.

 

  • aws-cli가 설치되어 있고 credential 설정이 완료되어 있다.
  • 호스팅 가능한 s3버킷이 이미 존재한다.

aws-cli 설치는 아래의 공식문서를 참조해서 설치하면 된다.

https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/install-cliv2.html

 

s3버킷을 cloudfront - route53으로 연결해서 호스팅 하는 것은 이후에 포스팅할 예정이다. 지금은 s3의 주소를 사용해서 예제를 진행하겠다.

 

1. swagger.json 배포

 

swagger.json파일을 s3에 배포한다. 

 

aws s3 cp ./swagger_dist/swagger.json s3://[s3버킷명]/swagger/swagger.json --acl public-read

 

기존에 aws-cli설정이 완료되어 있으면 aws s3 cp 명령어를 통해 파일을 업로드할 수 있다. `--acl public -read'는 업로드하는 파일이나 폴더의 접근권한을 설정해주는 부분인데, public-read 권한을 주면 해당 파일을 외부에서도 url을 통해 접근 가능하게 해 준다.

 

업로드 명령어는 package.json 에 script로 등록해서 편하게 사용 가능하므로 되도록 aws-cli설정을 완료하고 명령어를 통해 업로드하는 걸 권장한다. 

 

 

객체 URL의 주소는 밑의 진행에 사용되니 잘 저장해놓도록 하자.

 

 

2. swagger-ui-dist

 

2.1 swagger-ui-dist 설치

 

npm i swagger-ui-dist --save-dev

 

2.2 node_modules에서 swagger-ui-dist 가져오기

 

프로젝트 root 경로에 swagger_hosting 폴더를 생성해주고 node_modules -> swagger-ui-dist 폴더 내에 파일들을 복사해서 옮겨온다. 그러면 다음과 같은 구조가 될 것이다.

 

swagger_hosting
    absolute-path.js
    favicon-16x16.png
    favicon-32x32.png
    index.html
    index.js
    oauth2-redirect.html
    package.json
    README.md
    swagger-ui-bundle.js
    swagger-ui-bundle.js.map
    swagger-ui-standalone-preset.js
    swagger-ui-standalone-preset.js.map
    swagger-ui.css
    swagger-ui.css.map
    swagger-ui.js
    swagger-ui.js.map
    

 

2.3 index.html 수정

 

swagger_hosting폴더의 index.html에는 문서를 생성하는데 참고할 데이터를 가져오는 url을 설정해주는 부분이 있다. 이곳에 방금 우리가 배포한 swagger.json의 url을 설정해주면 swagger.json파일이 변경될 때마다 갱신된 정보를 볼 수 있다. 아까 이미지에서 빨간색으로 표시된 부분의 url을 주소에 넣어준다.

 

  <body>
    <div id="swagger-ui"></div>

    <script src="./swagger-ui-bundle.js"> </script>
    <script src="./swagger-ui-standalone-preset.js"> </script>
    <script>
    window.onload = function() {
      // Begin Swagger UI call region
      const ui = SwaggerUIBundle({
      	// 이 url부분을 변경해주면 된다.
        url: "https://petstore.swagger.io/v2/swagger.json",
        dom_id: '#swagger-ui',
        deepLinking: true,
        presets: [
          SwaggerUIBundle.presets.apis,
          SwaggerUIStandalonePreset
        ],
        plugins: [
          SwaggerUIBundle.plugins.DownloadUrl
        ],
        layout: "StandaloneLayout"
      })
      // End Swagger UI call region

      window.ui = ui
    }
  </script>
  </body>

 

2.4 swagger_hosting 폴더 배포

 

aws-cli에는 sync 명령어가 있는데, 아까의 cp명령어와는 달리 폴더를 업로드할 때 사용할 수 있다.

 

aws s3 sync ./swagger_hosting s3://[s3버킷명]/swagger --acl public-read

 

hosting 폴더를 업로드 후 s3버킷에 들어가서 index.html 파일의 s3 url로 접속해보면 다음과 같은 swagger 페이지를 볼 수 있다.

 

 

아직 아무것도 없지만, class-validator를 통해 생성한 ApiPostRequest가 Schema에 들어가 있는 걸 확인할 수 있다. 

 

이제 package.json 에 script를 만들고 주석을 생성해서 swagger api생성을 자동화시켜보자.

 

3. swagger 주석 추가

 

기존에 만들었던 api_example_post에 swagger 주석을 추가한다.

 

import { APIGatewayProxyHandler } from 'aws-lambda';
import { ApiPostRequest } from '@model/request-model/api-example.model';
import { createModelAndValidation, requestSuccess, requestFail } from '@util/http.util';

// 추가된 부분 START
/**
 *  @swagger
 *  /api_example_post:
 *    post:
 *      description: API POST example
 *      summary: POST 예제
 *      requestBody:
 *        content:
 *          application/json:
 *            schema:
 *              $ref: '#/components/schemas/ApiPostRequest'
 *      responses:
 *        200:
 *          description: 성공
 *          content:
 *            application/json:
 *              schema:
 *                $ref: '#/components/schemas/ApiPostRequest'
 *          
 */
 // 추가된 부분 END
export const api_example_post: APIGatewayProxyHandler = async (event, _context) => {
    try {
        let { body } = <any>event
        body = JSON.parse(body)

        const optionalParamList = ['name']
        const requireParamList = ['id']
        const paramList = [...requireParamList, ...optionalParamList]

        const apiPostReqest = await createModelAndValidation(new ApiPostRequest(), body, paramList)

        return requestSuccess({ message: `success` })
    } catch (error) {
        console.log("api_example_post:APIGatewayProxyHandler -> error", error)

        return requestFail({ message: error })
    }
}

 

추가된 주석 부분을 보면 '@swagger'로 시작되고 있음을 알 수 있다. '@swagger'를 표기해야 이 주석이 swagger문서를 제작하기 위한 주석이라는 걸 인식할 수 있다. 주석 양식은 yml 파일 양식을 따르고 있기 때문에 indent를 잘 맞춰줘야 한다. 여기서 중요한 부분은 우리가 기존에 만들었던 ApiPostRequest를 schema에서 사용 가능하다는 것이다. 

 

이번엔 package.json에 script를 추가해서 배포를 좀 더 편하게 만들어보자.

 

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "sls offline",
    "swagger:build": "tsc --project ./script && node ./swagger_dist/script/swagger.script.js",
    // 추가된 부분 START
    "swagger:json:publish": "aws s3 cp ./swagger_dist/swagger.json s3://[s3 버킷명]/swagger/swagger.json --acl public-read",
    "swagger:hosting:publish": "aws s3 sync ./swagger_hosting s3://[s3 버킷명]/swagger --acl public-read"
    // 추가된 부분 END
  },

 

swagger:json:publish와 swagger:hosting:publish 가 추가되었다. 내용은 위에서 이미 해본 것이라 따로 설명하지 않겠다. swagger:build후 swagger:hosting:publish를 실행시키면 새로 생성된 swagger.json이 업로드된다. 기존에 호스팅 했던 s3의 index.html로 다시 접속해보면 방금 추가한 api를 확인할 수 있다.

 

 

정리

 

여기까지 swagger 문서 자동화 작업이 끝났다. 분명 부족한 부분이 많이 있겠지만 본인 스타일대로 잘 설계한다면 더 편하게 사용 가능할 거라 생각한다. 

 

다음번에는 serverless를 스테이지별로 나누고 배포하는 작업을 하려 한다. 그러면서 serverless에서 빠지지 않고 발생하는 CORS 문제도 같이 해결하는 방법을 정리해보겠다.