👾 작성자: 유지원
🐬 작성자의 한마디: 클라한테 이쁨받기? 쉽지!
npm install swagger-cli swagger-ui-express yamljs
npm install -D @types/swagger-ui-express @types/yamljs
openapi: 3.0.0
info:
version: 1.0.0
title: SOPT API docs
description: SOPT SERVER SEMINAR
license:
name: Jionee
servers:
- url: http://localhost:8000/ #자신의 포트번호
#Paths api 경로 지정
paths: {}
...
//swagger 연결
import swaggerUi from 'swagger-ui-express';
import YAML from 'yamljs';
const path = require('path');
const swaggerSpec = YAML.load(path.join(__dirname, '../build/swagger.yaml'))
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
...
...
"scripts": {
"build": "tsc && node dist",
**"api-docs": "swagger-cli bundle ./src/swagger/openapi.yaml --outfile build/swagger.yaml --type yaml",
"predev": "npm run api-docs",**
"dev": "nodemon"
},
...
이제 터미널에 npm run dev 명령어를 치면,
→ api-docs를 predev로 dev 실행 전에 실행시켜줘서
→ swagger.yaml파일이 자동으로 생성된다.
화면에 뿌리는 것은 index.ts 파일에서 해줬으므로 이렇게만 설정해주면
http://localhost:8000/api-docs 에서 swagger 화면을 볼 수 있다.
Yeah~
명세 작성은 중복을 줄이기 위해
openapi.yaml에는 → 공통되는 부분을,
각 도메인별 yaml 에는 → 해당되는 부분을 작성한다.
예시를 보면서 익혀보자
components:
parameters: null
#Schemas : model 정보
schemas:
user:
properties:
name:
type: string
description: 유저 이름
age:
type: number
description: 유저 나이
phone:
type: string
description: 핸드폰번호
email:
type: string
description: 이메일 주소
school:
properties:
name:
type: string
description: 학교 이름
major:
type: string
description: 전공
Error:
type: object
properties:
success:
type: boolean
message:
type: string
#Examples
examples:
userExample:
value:
{
"name": "홍길동",
"phone": "01011112222",
"email": "swaggerTest@naver.com",
"school": {
"name": "xx대학교",
"major": "컴퓨터공학부"
}
}
#Responses 재사용되는 애들
responses:
successResponse:
description: successful request with no data
content:
application/json:
schema:
type: object
example: {"status": 200, "success": true, "message": "message"}
BadRequest:
description: 잘못된 요청
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
success: false
message: 잘못된 요청
InternalServerError:
description: 서버 에러
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
success: false
message: 서버 내부 오류
#Paths api 경로 지정
paths:
/user:
$ref: './user.yaml#/~1user'
/user/{userId}:
$ref: './user.yaml#/~1user~1{userId}'
openapi: 3.0.0
info:
version: 1.0.0
title: SOPT API docs
description: SOPT SERVER SEMINAR
license:
name: Jionee
servers:
- url: http://localhost:8000/
components:
parameters: null
#Schemas : model 정보
schemas:
user:
properties:
name:
type: string
description: 유저 이름
age:
type: number
description: 유저 나이
phone:
type: string
description: 핸드폰번호
email:
type: string
description: 이메일 주소
school:
properties:
name:
type: string
description: 학교 이름
major:
type: string
description: 전공
Error:
type: object
properties:
success:
type: boolean
message:
type: string
#Examples
examples:
userExample:
value:
{
"name": "홍길동",
"phone": "01011112222",
"email": "swaggerTest@naver.com",
"school": {
"name": "xx대학교",
"major": "컴퓨터공학부"
}
}
#Responses 재사용되는 애들
responses:
successResponse:
description: successful request with no data
content:
application/json:
schema:
type: object
example: {"status": 200, "success": true, "message": "message"}
BadRequest:
description: 잘못된 요청
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
success: false
message: 잘못된 요청
InternalServerError:
description: 서버 에러
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
example:
success: false
message: 서버 내부 오류
#Paths api 경로 지정
paths:
/user:
$ref: './user.yaml#/~1user'
/user/{userId}:
$ref: './user.yaml#/~1user~1{userId}'
/user:
post:
tags:
- User
summary: 유저 생성
consumes:
- application/json
requestBody:
x-name: body
required: true
content:
application/json:
schema:
$ref: './openapi.yaml#/components/schemas/user'
examples:
userExample:
$ref: './openapi.yaml#/components/examples/userExample'
responses:
'200':
$ref: './openapi.yaml#/components/responses/successResponse'
'400':
$ref: './openapi.yaml#/components/responses/BadRequest'
'500':
$ref: './openapi.yaml#/components/responses/InternalServerError'
/user/{userId}:
get:
tags:
- User
summary: 유저 정보 조회
parameters:
- in: path
name: userId
required: true
description: 유저 id
schema:
type: string
responses:
'200':
description: 유저 조회 성공
content:
application/json:
schema:
type: object
example: {
"status": 200,
"success": true,
"message": "유저 조회 성공",
"data": {
"school": {
"name": "xx대학교",
"major": "컴퓨터공학부"
},
"_id": "6283a755c2f673e5e81a6fea",
"name": "홍길동",
"phone": "01011112222",
"email": "validateTest-email2@naver.com",
"age": 20
}
}
'400':
$ref: './openapi.yaml#/components/responses/BadRequest'
'500':
$ref: './openapi.yaml#/components/responses/InternalServerError'
/user:
post:
tags:
- User
summary: 유저 생성
consumes:
- application/json
requestBody:
x-name: body
required: true
content:
application/json:
schema:
$ref: './openapi.yaml#/components/schemas/user'
examples:
userExample:
$ref: './openapi.yaml#/components/examples/userExample'
responses:
'200':
$ref: './openapi.yaml#/components/responses/successResponse'
'400':
$ref: './openapi.yaml#/components/responses/BadRequest'
'500':
$ref: './openapi.yaml#/components/responses/InternalServerError'
/user/{userId}:
get:
tags:
- User
summary: 유저 정보 조회
parameters:
- in: path
name: userId
required: true
description: 유저 id
schema:
type: string
responses:
'200':
description: 유저 조회 성공
content:
application/json:
schema:
type: object
example: {
"status": 200,
"success": true,
"message": "유저 조회 성공",
"data": {
"school": {
"name": "xx대학교",
"major": "컴퓨터공학부"
},
"_id": "6283a755c2f673e5e81a6fea",
"name": "홍길동",
"phone": "01011112222",
"email": "validateTest-email2@naver.com",
"age": 20
}
}
'400':
$ref: './openapi.yaml#/components/responses/BadRequest'
'500':
$ref: './openapi.yaml#/components/responses/InternalServerError'
put:
tags:
- User
summary: 유저 정보 수정
parameters:
- in: path
name: userId
required: true
description: 유저 id
schema:
type: string
consumes:
- application/json
requestBody:
description: \[Optional\] name, age, phone, email, school-name, school-major
x-name: body
required: true
content:
application/json:
schema:
$ref: './openapi.yaml#/components/schemas/user'
delete:
tags:
- User
summary: 유저 삭제
parameters:
- in: path
name: userId
required: true
description: 유저 id
schema:
type: string
참고
https://airplane9876.tistory.com/14 | yaml 파일 나누기 짱짱맨 |
---|---|
https://velog.io/@hyex/Node.js-TS-프로젝트에-swagger-적용하기-Feat.-파일-분리 | 파일분리22 |
https://velog.io/@kyy00n/Node.js-Swagger-개요-적용 | |
https://llshl.tistory.com/49 | auto-gen이라는 라이브러리도 있던데 사용해보니까 어차피 얘도 수동이더라구요..? |
https://any-ting.tistory.com/105 | 주석을 사용해서 지양하는 것이 좋을 듯한데, yaml 형태 같은 것은 참고해도 좋을 듯 합니다 |
자꾸 openapi.yaml이 validate하지 않는다고 한다면?
→ 무언가가 빠졌을 확률 있음, 아래의 openAPI.tootls 에서 검증하기
(저는 이거 썼어용)
Error: No default engine was specified and no extension was provided
res.render 쓰지 말구 res.json으로 바꿔버리잣
res.json({
message: err.message,
error: err
});