백앤드(Back-End)/Swagger

[Swagger] Swagger Yaml 파일 RESTFul API 클라이언트 구축

RyanSin 2021. 1. 28. 23:34
반응형

- 지난 시간

안녕하세요. 지난 시간에는 Swagger Yaml 파일 기본 작성법에 대해 알아봤습니다.

 

놓치고 오신 분들은 한번 아래 링크를 통해 학습하고 오시는 걸 추천드립니다.

any-ting.tistory.com/12

 

[Swagger] Swagger Yaml 기본 파일 작성

- 지난 시간 지난 시간에는 Swaager UI를 구축하는 시간을 가졌습니다. 혹시 구축하지 않으셨다면 아래 링크를 보고 구축하고 오시면 되겠습니다. any-ting.tistory.com/11 [Swagger] Swagger UI를 활용한 내부 A

any-ting.tistory.com

- 개요

이번 시간에는 실제 RESTFul API 구조에 맞게 하나씩 만들어 보도록 하겠습니다.

 

결과 화면을 먼저 보여드리도록 하겠습니다.

 

 

기본적으로 많이 사용되는 RESTFul API Method는 아래와 같습니다.

 

  • GET : 조회
  • POST : 생성
  • PUT : 수정
  • DELETE : 삭제
  • PATCH : 전체 수정
  • POST : 파일 업로드 (추가 기능)

- 기본 정보

openapi: 3.0.0
info:
  version: '1.0.0'
  title: '개발이 취미인 남자'
  description: '프로젝트 설명 RestFul Api 클라이언트 UI 로컬 서버를 구동 후 요청해주세요.'

#내가 요청하고 싶은 서버 url 설정 다수로 설정가능
servers:
- description: "유저 등록 API"
  url: http://localhost:3000/api
- description: "파일 업로드 API"
  url: http://localhost:3000

# API 요청 경로 및 데이터 세팅
# paths 밑에 RESTFul API Method를 선언해서 한다.
paths:

- GET 방식

유저 데이터 전체 조회

 // Client  
  /users:
    get:
      summary: "유저 데이터 전체조회"
      description: "서버에 데이터를 보내지 않고 Get방식으로 요청"
      tags:
        - Get 방식
      responses:
        '200':
          description: 전체 유저 정보
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  users:
                    type: object
                    example: [{ "id": 1, "name": "유저1" },
                              { "id": 2, "name": "유저2" },
                              { "id": 3, "name": "유저3" }]
                              
 // Server
 /**
   * @path {GET} http://localhost:3000/api/users
   * @description 요청 데이터 값이 없고 반환 값이 있는 GET Method
   */
  app.get("/api/users", (req, res) => {

      //유저 정보 반환
      res.json({ok: true, users: users});
  })

특정 유저 조회 (Query & Path 방식) 

 

 //Client
  /users/{user_id}:
    get:
      summary: "특정 유저조회 Path 방식"
      description: "요청 경로에 값을 담아 서버에 보낸다."
      tags:
        - Get 방식
      parameters:
        - in: path
          name: user_id
          required: true
          description: 유저 아이디
          schema:
            type: string
      responses:
        '200':
          description: 사용자가 서버로 전달하는 값에 따라 결과 값은 다릅니다. (유저 조회)
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  users:
                    type: object
                    example: [{ "id": 1, "name": "유저1" }]

  /users/user?user_id={user_id}:
    get:
      summary: "특정 유저조회 Query 방식"
      description: "요청 경로에 값을 담아 서버에 보낸다."
      tags:
        - Get 방식
      parameters:
        - in: query
          name: user_id
          required: true
          description: 유저 아이디
          schema:
            type: string
      responses:
        '200':
          description: 사용자가 서버로 전달하는 값에 따라 결과 값은 다릅니다. (유저 조회)
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  users:
                    type: object
                    example: [{ "id": 1, "name": "유저1" }]
                    
 //Server
 /**
   * @path {GET} http://localhost:3000/api/users/:user_id
   * @description Path Variables 요청 데이터 값이 있고 반환 값이 있는 GET Method 
   * 
   *  Path Variables 방식
   * 
   *  ex) 아래 GET 주소 에서 :user_id 는 서버에서 설정한 주소 키 값이다.
   *      값을 찾을 때는 req.params.user_id 로 값을 찾는다.
   * 
   *  *주의 사항*
   *  :user_id 이 부분은 변수이기 때문에 
   *  경로가 /users/1 이거나 /users/2 이거 일때 둘다 라우터를 거치게 된다.
   *  그렇기 때문에 다른 라우터 보다 아래 있어야 한다.
   */
  app.get("/api/users/:user_id", (req, res) => {

      const user_id = req.params.user_id

      //filter라는 함수는 자바스크립트에서 배열 함수이다. 필터링을 할때 많이 사용된다 필터링한 데이터를 새로운 배열로 반환한다.
      const user = users.filter(data => data.id == user_id);

      res.json({ok: true, user: user})
  })
  
 /**
   * @path {GET} http://localhost:3000/api/users/user?user_id=1
   * @description Query Params 요청 데이터 값이 있고 반환 값이 있는 GET Method 
   * 
   *  Query Params 방식
   *  user 뒤에 user_id변수를 통해 값을 찾아 올수 있다.
   *  &를 통해 두번째 변수를 받아서 사용할 수 있다.(/user?user_id=1&name="유저1")
   * 
   */
  app.get("/api/users/user", (req, res) => {

      const user_id = req.query.user_id

      //filter라는 함수는 자바스크립트에서 배열 함수이다. 필터링을 할때 많이 사용된다 필터링한 데이터를 새로운 배열로 반환한다.
      const user = users.filter(data => data.id == user_id);

      res.json({ok: false, user: user})
  })

 

- POST 방식

유저 등록

//Client
  /users/add:
      post:
        summary: "유저 등록"
        description: "POST 방식으로 유저를 등록한다."
        tags:
          - Post 방식      
        requestBody:
          description: 사용자가 서버로 전달하는 값에 따라 결과 값은 다릅니다. (유저 등록)
          required: true
          content:
            application/x-www-form-urlencoded:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    description: "유저 고유아이디"
                  name:
                    type: string
                    description: "유저 이름"
        responses:
          '200':
            description: 유저 등록 성공
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    ok:
                      type: boolean
                    data:
                      type: object
                      example: [{ "id": 1, "name": "유저1" },
                                { "id": 2, "name": "유저2" },
                                { "id": 3, "name": "유저3" },
                                { "id": 4, "name": "유저4" }]

//Server
/**
 * @path {POST} http://localhost:3000/api/users/add
 * @description POST Method
 * 
 *  POST 데이터를 생성할 때 사용된다.
 *  req.body에 데이터를 담아서 보통 보낸다.
 */
app.post("/api/users/add", (req, res) => {

    // 구조분해를 통해 id 와 name을 추출
    const { id, name } = req.body

    //concat 함수는 자바스크립트에서 배열 함수이다. 새로운 데이터를 추가하면 새로운 배열로 반환한다.
    const user = users.concat({id, name});

    res.json({ok: true, users: user})
})

 

- PUT 방식

//Client
  /users/update:
    put:
      summary: "유저 수정"
      description: "PUT 방식을 통해 유저 수정(전체 데이터를 수정할 때 사용함)"
      tags:
        - Put 방식
      requestBody:
        description: 유저 수정
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                id:
                  type: int
                  description: "유저 고유아이디"
                name:
                  type: string
                  description: "유저 이름"
      responses:
        '200':
          description: 사용자가 서버로 전달하는 값에 따라 결과 값은 다릅니다.(유저 수정)
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  data:
                    type: string
                    example: [{ "id": 1, "name": "유저1" },
                              { "id": 2, "name": "유저2" },
                              { "id": 3, "name": "유저3" }]

//Server
/**
 * @path {PUT} http://localhost:3000/api/users/update
 * @description 전체 데이터를 수정할 때 사용되는 Method
 */
app.put("/api/users/update", (req, res) => {
    
    // 구조분해를 통해 id 와 name을 추출
    const { id, name } = req.body

    //map 함수는 자바스크립트에서 배열 함수이다. 요소를 일괄적으로 변경할 때 사용됩니다.
    const user = users.map(data => {

        if(data.id == id) data.name = name

        return {
            id: data.id,
            name: data.name
        }
    })

    res.json({ok: true, users: user})
})

 

- PATCH 방식

//Client
  /user/update/{user_id}:
    patch:
      summary: "유저 수정"
      description: "Patch 방식을 통해 특정 유저 수정(단일 데이터를 수정할 때 사용함)"
      tags:
        - Patch 방식
      parameters:
        - in: path
          name: user_id
          required: true
          description: 유저 아이디
          schema:
            type: string
      requestBody:
        description: 유저 수정
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: "유저 이름"
      responses:
        '200':
          description: 사용자가 서버로 전달하는 값에 따라 결과 값은 다릅니다. (유저 수정)
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  data:
                    type: string
                    example: [{ "id": 1, "name": "유저1" },
                              { "id": 2, "name": "유저2" },
                              { "id": 3, "name": "유저3" }]
                              
//Server
/**
 * @path {PATCH} http://localhost:3000/api/user/update/:user_id
 * @description 단일 데이터를 수정할 때 사용되는 Method
 */
app.patch("/api/user/update/:user_id", (req, res) => {

    const { user_id} = req.params
    const { name } = req.body

    //map 함수는 자바스크립트에서 배열 함수이다. 요소를 일괄적으로 변경할 때 사용됩니다.
    const user = users.map(data => {

        if(data.id == user_id) data.name = name

        return {
            id: data.id,
            name: data.name
        }
    })

    res.json({ok: true, users: user})
})

 

- DELETE 방식

//Client
  /user/delete:
    delete:
      summary: "특정 유저 삭제"
      description: "요청 경로에 값을 담아 서버에 보낸다."
      tags:
        - Delete 방식
      parameters:
        - in: query
          name: user_id
          required: true
          description: 유저 아이디
          schema:
            type: string
      responses:
        '200':
          description: 사용자가 서버로 전달하는 값에 따라 결과 값은 다릅니다. (유저 삭제)
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  users:
                    type: object
                    example: [{ "id": 1, "name": "유저1" },
                              { "id": 2, "name": "유저2" },
                              { "id": 3, "name": "유저3" }]
                              
//Server
/**
 * @path {DELETE} http://localhost:3000/api/user/delete
 * @description 데이터 삭제
 * 
 */
app.delete("/api/user/delete", (req, res) => {

    const user_id = req.query.user_id

    //filter라는 함수는 자바스크립트에서 배열 함수이다. 필터링을 할때 많이 사용된다 필터링한 데이터를 새로운 배열로 반환한다.
    const user = users.filter(data => data.id != user_id );

    res.json({ok: true, users: user})
})

 

- 파일 업로드 방식

//Client
  /multipart/upload:
    post:
      summary: 파일 업로드
      description: 파일 업로드 서버로 전송해주세요.
      tags:
        - multipart/form-data Post 파일업로드
      requestBody:
        description: "파일 업로드"
        required: true
        content: 
          multipart/form-data:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: "파일 이름"
                file:
                  type: array
                  items:
                    type: string
                    format: binary
      responses:
        '200':
          description: 파일 업로드 성공
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  data:
                    type: string
                    example: Multipart Upload Ok
                    
//Server
/**
 * @author Ryan
 * @description 여러 파일 업로드
 * 
 * 클라이언트에서 file이라는 Key(fieldname) 값을 통해 파일을 전송하면 req.files 안에 파일 정보를 배열([]) 형태로 얻을 수 있다.
 * 
 * array('fieldname', maxCount) 필드 이름과 최대 파일 수를 정합니다.
 * 지정된 수 보다 더 많은 파일을 업로드하면 에러가 발생합니다.
 */
app.post('/multipart/upload', upload.array('file'), (req, res, next) => {

  const { name } = req.body;
  console.log("body 데이터 : ", name);

  //배열 형태이기 때문에 반복문을 통해 파일 정보를 알아낸다.
  req.files.map(data => {
    console.log("폼에 정의된 필드명 : ", data.fieldname);
    console.log("사용자가 업로드한 파일 명 : ", data.originalname);
    console.log("파일의 엔코딩 타입 : ", data.encoding);
    console.log("파일의 Mime 타입 : ", data.mimetype);
    console.log("파일이 저장된 폴더 : ", data.destination);
    console.log("destinatin에 저장된 파일 명 : ", data.filename);
    console.log("업로드된 파일의 전체 경로 ", data.path);
    console.log("파일의 바이트(byte 사이즈)", data.size);
  })

  res.json({ok: true, data: "Multipart Upload Ok"})

})

자세한 설명은 저번 시간에 내용을 확인하셨다면 이해를 하실 겁니다.

 

위 예시를 보고 이해가 안 가시면 댓글을 남겨주시면 감사하겠습니다. :)

 

항상 실습은 꼭 해주세요. 직접 해보는 게 실력 향상에 최고입니다.!

 

소스 저장소(GItHub)

- Swagger Client

github.com/Ryan-Sin/Swagger-UI/tree/RestFul-API

 

Ryan-Sin/Swagger-UI

Contribute to Ryan-Sin/Swagger-UI development by creating an account on GitHub.

github.com

- Server 유저 & 파일

 

1. 유저

github.com/Ryan-Sin/Node_Express

 

Ryan-Sin/Node_Express

Contribute to Ryan-Sin/Node_Express development by creating an account on GitHub.

github.com

2. 파일 업로드

github.com/Ryan-Sin/Node_Express_Multer

 

Ryan-Sin/Node_Express_Multer

Contribute to Ryan-Sin/Node_Express_Multer development by creating an account on GitHub.

github.com