Swagger - ynjch97/YNJCH_WIKI GitHub Wiki

1. Swagger

  • ๊ณต์‹ ์‚ฌ์ดํŠธ https://swagger.io/
  • ์ฐธ๊ณ  https://real-dongsoo7.tistory.com/58
  • Open Api Specification(OAS)๋ฅผ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ
  • API๋“ค์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ŠคํŽ™(spec)์„ ๋ช…์„ธ, ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ
  • API ๋ฌธ์„œํ™”๋ฅผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์คŒ
  • ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„ฃ์–ด์„œ ์‹ค์ œ๋กœ ์–ด๋–ค ์‘๋‹ต์ด ์˜ค๋Š”์ง€ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ
  • Swagger๋งŒ ์ „๋‹ฌํ•ด์ฃผ๋ฉด API Path์™€ Request, Response ๊ฐ’ ๋ฐ ์ œ์•ฝ ๋“ฑ์„ ํ•œ๋ฒˆ์— ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์Œ

1-1. Swagger Tools

  • API ๋””์ž์ธ : Swagger-editor๋ฅผ ํ†ตํ•ด api๋ฅผ ๋ฌธ์„œํ™”ํ•˜๊ณ  ๋น ๋ฅด๊ฒŒ ๋ช…์„ธํ•  ์ˆ˜ ์žˆ์Œ
    • Swagger Editor : Swagger ํ‘œ์ค€์— ๋”ฐ๋ฅธ API ์„ค๊ณ„์„œ/๋ช…์„ธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์—๋””ํ„ฐ
  • API Development : Swagger-codegen์„ ํ†ตํ•ด ์ž‘์„ฑ๋œ ๋ฌธ์„œ๋ฅผ ํ†ตํ•ด SDK๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋นŒ๋“œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ„์†Œํ™” ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์คŒ / ๋ฌธ์„œ๋ฅผ ํ†ตํ•ด ์‹คํ–‰ํ•˜๋ฉด ํ”„๋กœํ†  ํƒ€์ž… ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑ
    • Swagger Codegen : Swagger๋กœ ์ •์˜๋œ๋Œ€๋กœ ํด๋ผ์ด์–ธํŠธ/์„œ๋ฒ„ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” CLI ํˆด
  • API Documentation : Swagger-UI๋ฅผ ํ†ตํ•ด ์ž‘์„ฑ๋œ API๋ฅผ ์‹œ๊ฐํ™”
    • Swagger UI : Swagger UI๋Š” Swagger API ๋ช…์„ธ์„œ๋ฅผ HTML ํ˜•์‹์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ํˆด
  • API Testing : Swagger-Inspector๋ฅผ ํ†ตํ•ด API๋ฅผ ์‹œ๊ฐํ™” ํ•˜๊ณ  ๋น ๋ฅธ ํ…Œ์ŠคํŒ…์„ ์ง„ํ–‰
  • Standardize : Swagger-hub๋ฅผ ํ†ตํ•ด ๊ฐœ์ธ, ํŒ€์›๋“ค์ด API ์ •๋ณด๋ฅผ ๊ณต์œ ํ•˜๋Š” Hub

1-2. Open API์™€์˜ ๊ด€๊ณ„

  • ์ฐธ๊ณ  https://swagger.io/blog/api-strategy/difference-between-swagger-and-openapi/
  • OpenAPI๋Š” RESTful API ์„ค๊ณ„๋ฅผ ์œ„ํ•œ ์—…๊ณ„ ํ‘œ์ค€ ์‚ฌ์–‘์„ ๋‚˜ํƒ€๋‚ด๊ณ  Swagger๋Š” SmartBear ๋„๊ตฌ ์„ธํŠธ๋ฅผ ๋‚˜ํƒ€๋ƒ„
  • Swagger : OpenAPI ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ ์„ธํŠธ(Swagger Editor, Swagger UI, SwaggerHub)

2. API ๋””์ž์ธ

  • ๊ณต์‹ ์‚ฌ์ดํŠธ > Docs ํƒญ - ๋ฌธ์„œ ์ž‘์„ฑํ•˜๋Š” ๊ธฐ์ดˆ์ ์ธ ๋ฌธ๋ฒ•์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ
  • ๋„ํ๋จผํŠธ ์˜ต์…˜์„ ์„ ํƒ ํ›„ ์ด๋™ (๊ธฐ๋ณธ์€ OpenAPI V3.0)

2-1. Swagger-Editor

  • ์‚ฌ์šฉ ๋ฐฉ๋ฒ• : ๊ณต์‹ ์‚ฌ์ดํŠธ์˜ Live Demo๋ฅผ ์ด์šฉ / ์—๋””ํ„ฐ ์†Œ์Šค๋ฅผ ๋‹ค์šด ๋ฐ›์•„์„œ ์‚ฌ์šฉ

2-1-1. docker ์ด์šฉ

  • docker๋ฅผ ์ด์šฉํ•˜์—ฌ Swagger-Editor๋ฅผ ์„ค์น˜ํ•˜๋ ค๋ฉด ์•„๋ž˜ ๋ช…๋ น์–ด ์ž…๋ ฅ
docker pull swaggerapi/swagger-editor
docker run -d -p 80:8080 swaggerapi/swagger-editor

Swagger-editor

  • ๋กœ์ปฌ 80 ํฌํŠธ๋ฅผ ํ†ตํ•ด Swagger-editor๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์žˆ์Œ์„ ํ™•์ธ
  • ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด localhost:80 ํฌํŠธ๋กœ ์ ‘๊ทผ์„ ํ•˜๋ฉด Swagger-editor ํ™”๋ฉด ํ™•์ธ ๊ฐ€๋Šฅ
  • yaml, JSON ํ˜•์‹์œผ๋กœ ์ž‘์„ฑ ๊ฐ€๋Šฅ
  • ์•„๋ž˜ ๋‚ด์šฉ์€ Swagger๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ์˜ต์…˜
# ๋ช‡ ๋ฒ„์ „์˜ ์‹ ํ…์Šค๋ฅผ ์‚ฌ์šฉํ• ์ง€ ์„ค์ •ํ•ด ์ค๋‹ˆ๋‹ค.
swagger: "2.0"
info:
  version: "0.0.1"
  title: tistory test

# swagger๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š”  host๋ฅผ ์„ค์ •ํ•ด ์ค๋‹ˆ๋‹ค.
host: localhost:4000

# url์—์„œ ์‚ฌ์šฉํ•  basePath๋ฅผ ์„ค์ •ํ•ด ์ค๋‹ˆ๋‹ค.
basePath: /api/v1.0

schemes:
  # ํ”„๋กœํ† ์ฝœ์„ ์„ค์ •ํ•ด ์ฃผ๋Š” ๊ณณ์ธ๋ฐ, Production์œผ๋กœ ์‚ฌ์šฉ์‹œ http๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
  - http
  - https

# ์„œ๋ฒ„๋กœ ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ์˜ Content-type์„ ์„ค์ •ํ•ด ์ค๋‹ˆ๋‹ค.
consumes:
  - application/json

# ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „์†กํ•  ๋ฐ์ดํ„ฐ์˜ ํƒ€์ž…์„ ์„ค์ •ํ•ด ์ค๋‹ˆ๋‹ค.
produces:
  - application/json
  • API ์ž‘์„ฑ
API ์ž‘์„ฑ ํŽผ์ณ๋ณด๊ธฐ
paths:
  /user/{user_name}:
    post:
      tags:
      - "tag-for-user"
      summary: "api-summary"
      description: "swagger-example"
      consumes:
      - "application/x-www-form-urlencoded"

# parameters์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ๋ช…์„ธํ•œ ๋ถ€๋ถ„ ์ž…๋‹ˆ๋‹ค. 
# ์ด ๋ถ€๋ถ„์—์„œ ์ž‘์„ฑํ•˜๋Š” ์ˆœ์„œ๋Š” ํฐ ์˜๋ฏธ๊ฐ€ ์—†๋Š”๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
# in: path, header, body, query ์ €๋Š” ๋ณดํ†ต ๋„ค๊ฐ€์ง€ ํ˜•ํƒœ๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
# name : ๋ณ€์ˆ˜๋ช…์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ ๋„ค๊ฐ€์ง€ ๋ฐฉ์‹์„ ํ†ตํ•ด์„œ ๋„˜์–ด์˜ค๋Š” ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
# type : ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ๋ช…์‹œํ•ด ์ค๋‹ˆ๋‹ค. string, boolean, integer, number, array ... ๋“ฑ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐ์ดํ„ฐ ํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค.
# scheme $ref: ๋ฐ‘์˜ ๋ถ€๋ถ„์˜ model ์ž‘์„ฑ์„ ํ†ตํ•ด ์ฐธ์กฐํ•˜์—ฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

      parameters:
      - name: "user_name"
        in: "path"
        description: "spec for user_name"
        required: true
        type: "string"

      - name: "queryString-exam"
        in: "query"
        description: "offset for pagination"
        required: false
        type: "integer"

      - name: "header-exam"
        in: "header"
        required: true
        type: "string"

     - in: "body"
        name: "user"
        required: false
        schema:
          $ref: "#/definitions/user"

# ์š”์ฒญ์ด ๋“ค์–ด์™”์„๋•Œ ์‘๋‹ต์— ๋Œ€ํ•œ ๋ช…์„ธ๋ฅผ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.
# ๊ฐ ์‘๋‹ต ์ฝ”๋“œ๋ณ„ ์‘๋‹ต ๋ฉ”์‹œ์ง€์™€ ํฌ๋ฉง์„ ์„ค์ •ํ•ด ์ค„ ์ˆ˜ ์ž‡์Šต๋‹ˆ๋‹ค.
      responses:
        200:
          description: "status code 200"
          schema:
            $ref: "#/definitions/user"
        401:
          description: "Authentication Error"
          schema:
            $ref: "#/definitions/SuccessResponse"
        500:
          description: "status code 500"
          schema:
            $ref: "#/definitions/ErrorResponse" 


# Response์™€ Request์— ์‚ฌ์šฉํ•  Model์„ ์ •์˜ํ•ด์ฃผ๋Š” ๋ถ€๋ถ„ ์ž…๋‹ˆ๋‹ค.
# Example ๋ฐ์ดํ„ฐ๋„ ์‚ฝ์ž…์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ Swagger-Inspecter๋ฅผ ํ†ตํ•œ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
definitions:
  user:
    type: "object"
    required:
    - "username"
    properties:
      id:
        type: "integer"
        description: "The user ID."
      username:
        type: "string"
        description: "The user name."
    example:
      id: 0
      username: "username"

SuccessResponse:
      properties:
        code:
          type: integer
        status:
          type: string
        message:
          type: string

 ErrorResponse:
    properties:
      code:
        type: integer
      status:
        type: string
      message:
        type: string

3. API Development

3-1. Swagger-codegen

  • Swagger๋ฅผ ํ†ตํ•ด API Server-stub์„ ์ œ์ž‘ํ•  ์ˆ˜ ์žˆ๊ณ  Client SDK๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ƒ์‚ฐ์†๋„๋ฅผ ๋Š˜๋ฆด ์ˆ˜ ์žˆ์Œ
  • ์ฐธ๊ณ  https://real-dongsoo7.tistory.com/59?category=716261
  • Swagger-Editor๋ฅผ ํ†ตํ•ด API ๋””์ž์ธ ์—ด๊ธฐ
  • Swagger-editor ์ƒ๋‹จ File -> Save as YAML -> .yaml ํŒŒ์ผ ์ƒ์„ฑํ•˜๊ธฐ
  • ์„ค์น˜ ๊ด€๋ จ ์ฐธ๊ณ  https://github.com/swagger-api/swagger-codegen
  • ๊น”๋”ํ•˜๊ฒŒ ๋ณด๊ธฐ ์œ„ํ•ด ํ•ด๋‹น ๊ฒฝ๋กœ์—์„œ ๋ช…๋ น์–ด ์‹คํ–‰
swagger-codegen generate -i {ํŒŒ์ผ ์ด๋ฆ„} -l {์–ธ์–ด}

Swagger-codegen

  • swagger-codegen ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด server stub์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Œ
  • ๊ธฐ๋ณธ์ ์œผ๋กœ MVC ํŒจํ„ด์— ๋งž์ถฐ์„œ ํ”„๋กœํ† ํƒ€์ž…์ด ์ƒ์„ฑ๋จ
tree

Swagger-codegen

  • npm install์„ ํ†ตํ•ด Dependency๋ฅผ ๋ชจ๋‘ ๋งž์ถฐ์ฃผ๊ณ  ํŒŒ์ผ์„ ์‹คํ–‰
  • ๊ธฐ๋ณธ์ ์œผ๋กœ Swagger-codegen์„ ์‹คํ–‰ํ•˜๋Š” ๊ณผ์ •์„ ํ†ตํ•ด Swagger-UI๋„ ๊ฐ™์ด ์„ค์น˜๋˜๋Š”๊ฒƒ์„ ํ™•์ธ
  • ๊ธฐ์กด์˜ ํ”„๋กœ์ ํŠธ์— Swgger-Editor ํ˜น์€ Swagger-UI๋ฅผ ์„ค์น˜ํ•˜๋Š” ๊ฒฝ์šฐ npm์— ์žˆ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Œ
nodemon index.js

Swagger-codegen

  • ๋ช…์‹œ๋˜์–ด ์žˆ๋Š”๊ฒƒ ์ฒ˜๋Ÿผ ํ•ด๋‹น์ฃผ์†Œ(localhost:3000/docs)๋กœ ์ ‘๊ทผ์„ ํ•˜๊ฒŒ๋˜๋ฉด Swagger-ui ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Œ

4. API Documentation

4-1. Swagger-UI

  • ๋…๋ฆฝ์ ์ธ UI๋ฅผ ๊ฐ€์ง„ ํŽ˜์ด์ง€๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ์Œ
  • Spec์— ๋Œ€ํ•ด ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์ œ์ž‘ํ•œ API์— ๋Œ€ํ•ด TEST๋„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ

5. ์ ์šฉ

  • ์ตœ์‹  ๋ฒ„์ „์ธ Swagger 3.x ๋ฒ„์ „์„ ์ ์šฉ

5-1. ์˜์กด์„ฑ ์ถ”๊ฐ€

  • Swagger 2.x ๋ฒ„์ „๊ณผ ๋‹ค๋ฅด๊ฒŒ springfox-boot-starter ํ•˜๋‚˜๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ํ•˜์œ„์— ํ•„์š”ํ•œ ๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Œ
  • ๋ฒ„์ „ ์ •๋ณด ํ™•์ธ https://mvnrepository.com/artifact/io.springfox/springfox-boot-starter
dependencies {
    implementation 'io.springfox:springfox-boot-starter:3.0.0'
}

5-2. Config ์ถ”๊ฐ€

@Configuration
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.OAS_30)
                .useDefaultResponseMessages(false)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.springswagger.controller"))
                .paths(PathSelectors.any())
                .build()
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Practice Swagger")
                .description("practice swagger config")
                .version("1.0")
                .build();
    }
}
  • Docket: Swagger ์„ค์ •์˜ ํ•ต์‹ฌ์ด ๋˜๋Š” Bean
  • useDefaultResponseMessages: Swagger ์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ธฐ๋ณธ ์‘๋‹ต ์ฝ”๋“œ (200, 401, 403, 404). false ๋กœ ์„ค์ •ํ•˜๋ฉด ๊ธฐ๋ณธ ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๋…ธ์ถœํ•˜์ง€ ์•Š์Œ
  • apis: api ์ŠคํŽ™์ด ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š” ํŒจํ‚ค์ง€ (Controller) ๋ฅผ ์ง€์ •
  • paths: apis ์— ์žˆ๋Š” API ์ค‘ ํŠน์ • path ๋ฅผ ์„ ํƒ
  • apiInfo:Swagger UI ๋กœ ๋…ธ์ถœํ•  ์ •๋ณด

5-3. Controller ์— ์ ์šฉ

@RestController
public class HelloController {

    @Operation(summary = "test hello", description = "hello api example")
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "OK !!"),
            @ApiResponse(responseCode = "400", description = "BAD REQUEST !!"),
            @ApiResponse(responseCode = "404", description = "NOT FOUND !!"),
            @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR !!")
    })
    @GetMapping("/hello")
    public ResponseEntity<String> hello(@Parameter(description = "์ด๋ฆ„", required = true, example = "Park") @RequestParam String name) {
        return ResponseEntity.ok("hello " + name);
    }
}

5-4. ์‹คํ–‰ ํ›„ ์ ‘์†

  • ๋กœ์ปฌ Spring Boot๋ฅผ ์‹คํ–‰ํ•œ ํ›„, URL ์ ‘์† (http://localhost:8080/<**๋ฃจํŠธ ์ปจํ…์ŠคํŠธ>/swagger-ui.html๋กœ ์ ‘์†)
  • swagger UI๊ฐ€ ์ ์šฉ๋œ ๊ฒƒ์„ ํ™•์ธ
  • API์˜ ์ •๋ณด๋ฅผ ํ™•์ธํ•˜๊ฑฐ๋‚˜, Try it out ๋ฒ„ํŠผ์„ ์‚ฌ์šฉํ•ด API๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Œ
  • Swagger2 : http://localhost:8080/swagger-ui.html
  • Swagger3 : http://localhost:8080/swagger-ui/index.html

6. ์ ์šฉ๋œ ์„ค์ • ํ™•์ธ

  • SwaggerConfig ์—์„œ ์„ค์ •ํ•œ ์ •๋ณด๋“ค์€ Swagger ์ƒ๋‹จ์— ๋‚˜์˜ด ์„ค์ • ํ™•์ธ
  • Controller ์—์„œ ์„ธํŒ…ํ•œ ์„ค์ • ์„ค์ • ํ™•์ธ

6-1. SpringDoc

  • Swagger ๋Š” SpringFox ์™ธ์— SpringDoc ์œผ๋กœ๋„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Œ
  • ํ˜„์žฌ Spring Boot 2.6 ๋ฒ„์ „์—์„œ SpringFox Swagger 3.0 ์˜ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” ์ด์Šˆ๊ฐ€ ์กด์žฌ > SpringDoc ๊ณต์‹ ๋ฌธ์„œ ์ฐธ๊ณ , Spring Boot๋ฅผ 2.5 ๋ฒ„์ „๋Œ€๋กœ ๋‚ด๋ฆฌ์ง€ ์•Š์•„๋„ Swagger๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Œ
โš ๏ธ **GitHub.com Fallback** โš ๏ธ