[게시판 만들기] TIL 10. Get/veiw/Edit/Delete Post


  1. include

  2. exclude


😀 Notice Board 레파지토리😀
Stack : Javascript, express, nodejs, sequelize


★ : 이번 과정을 통해서 새로 만들어진 파일

☆ : 이번 과정을 통해서 수정된 파일

/
├── 📁/server
│   ├── 📄README.md                     # Notice_Board README./
├── 📁/server
│   ├── 📄README.md                     # Notice_Board README.md 파일
│   ├── 📄index.js                      # node.js로 작성된 웹 서버 진입점
│   ├── 📄package.json
│   ├── 📄package-lock.json
│   ├── 📄.gitignore                    # node_modules, env 등 포함되지 않게 설정요망
│   ├── 📁/config                       # 환경변수
│   │    ├── 📄config.js        
│   │    └── 📄jwt.js                   # jwt 관련 환경변수
│   ├── 📁/controllers                  # 기능 API
│   │    ├── 📄☆ index.js        
│   │    ├── 📁User                     # 유저관련 API
│   │    │    ├── 📄index.js 
│   │    │    ├── 📄join.js             # join API
│   │    │    ├── 📄login.js            # login API
│   │    │    ├── 📄logout.js           # logout API
│   │    │    └── 📄withdrawal.js    # withdrawal API
│   │    ├── 📁MyPage                   # 마이페이지 API
│   │    │    ├── 📄index.js 
│   │    │    ├── 📄myPage.js            # myPage API
│   │    │    └── 📄editUserInfo.js      # editUserInfo API
│   │    └── 📁Boards                   # 게시판 API
│   │         ├── 📄☆ index.js 
│   │         ├── 📄writeBoard.js        # writeBoard API
│   │         ├── 📄searchBords.js       # writeBoard API
│   │         ├── 📄★ getBoards.js      # getBoards API
│   │         ├── 📄★ viewBoard.js      # viewBoard API\
│   │         └── 📄★ editBoard.js      # editBoard API
│   │         └── 📄★ deleteBoard.js    # deleteBoard API
│   ├── 📁/middlewares
│   │    ├── 📄CheckEmailForm.js        # email 양식이 맞는지 확인하는 middleware
│   │    ├── 📄CheckPassword.js         # password 조건이 맞는지 확인하는 middleware      
│   │    └── 📄checkToken.js            # JWT 검증 middleware
│   ├── 📁/migrations 
│   │    ├── 📄20210819052749-create-users.js
│   │    ├── 📄20210819065842-add-column-in-usersTable.js   
│   │    ├── 📄20210910065541-create-boards.js
│   │    └── 📄20210910070528-fk-Boards.js         
│   ├── 📁/models                       # DB 모델 파일
│   │    ├── 📄index.js
│   │    ├── 📄users.js
│   │    └── 📄boards.js
│   ├── 📁/routes
│        └── 📄☆ index.js               # 분기 파일
│   


controllers/Boards/getBoards.js

const { Boards } = require('../../models');
const { Users } = require('../../models');

module.exports = {
  get : async (req, res) =>{
    Boards.findAll({
      order: [['createdAt', 'DESC']],
      attributes :{exclude :["content"]},
      include : [
        { model : Users, 
          required: true, 
          attributes : {exclude :["id","email","password", "salt", "createdAt", "updatedAt"]} }
      ]
    }).then(data => {
        res.status(200).send(data)
    })
  }
}


user API들과 겹치는 부분이 많아 어려운 점은 없었으나, 해당 기능을 작성하면서 includeexclude 기능을 사용하였기 때문에 그에 대한 설명을 정리한다.


1. includeexclude

controllers/Boards/getBoards.js

const { Boards } = require('../../models');
const { Users } = require('../../models');

module.exports = {
  get : async (req, res) =>{
    Boards.findAll({
      order: [['createdAt', 'DESC']],
      attributes :{exclude :["content"]},
      include : [
        { model : Users, 
          required: true, 
          attributes : {exclude :["id","email","password", "salt", "createdAt", "updatedAt"]} }
      ]
    }).then(data => {
        res.status(200).send(data)
    })
  }
}

13일 자 작성한 코드를 보면서 한가지 놓친 게 있다는 사실 깨달았다. 네이버 카페에서 검색하면 나오는 정보는 포스트 이름, 작성자 이름, 작성 시간, 좋아요나 조회 수, 댓글 개수가 나온다. 댓글 개수는 생각했던 것이 아니니까 Reply API를 만들 때 칼럼을 추가할지 말지에 대해서 고민해보도록 하고. 어제 자로 알아봤던 건 작성자 이름이였고, 오늘 자로 알아본 것은 응답 객체(res)에 불필요한 정보를 덜어내는 것이었다.

1.1 include

공식 레퍼런스 👉 https://sequelize.org/master/manual/eager-loading.html

공식문서에서 보면 Finder 함수는include절을 사용할 시, SQL문의 Join과 같은 결과를 만든다고 한다. 이 함수의 기본값은 outer join이기 때문에, 만약 inner join의 결과를 바란다면, required:trueinclude절의 옵션에 넣어야 한다. 그리고 where과 operators 또한 사용할 수 있다고 한다.

const { Boards } = require('../../models');
const { Users } = require('../../models');

module.exports = {
  get : async (req, res) =>{
    Boards.findAll({
      order: [['createdAt', 'DESC']],
      include : [{ model : Users}]
    }).then(data => {
        res.status(200).send(data)
    })
  }
}

exclude 없는 상태에서 위처럼 코드를 작성할 때 Boards 테이블과 Users 테이블에 있는 모든 데이터가 출력된다. 즉, 불필요한, 혹은 노출되면 안 되는 정보까지 모두 노출된다.

[
  {
    "id": 2,
    "userId" : 1,
    "title": "제목입니다1",
    "content": "내용입니다2",
    "likes": 0,
    "createdAt": "2021-08-01T06:02:00.000Z",
    "user": {
    	"id" : 1,
    	"email" : "assignment@example.com",
        "nickname": "팬더",
        "password": "abc123",
        "slat": "asdfasgda",
        "createdAt": "2021-08-01T06:02:00.000Z",
        "updatedAt": "2021-08-01T06:02:00.000Z",
    }
  }
]

위처럼 우리에게 필요한 것은 nickname뿐인데, 다른 데이터도 출력된다. 특히 여기서는 노출되면 안 되는 password와 slat 값이 노출되고 있다.

1.2 exclude

공식 레퍼런스 👉 https://sequelize.org/master/manual/model-querying-basics.html

원래라면 필요한 칼럼만 노출하는 법을 찾았는데, 쉽게 나오지 않아서 불필요한 칼럼은 배제하고 출력할 수 있는 exclude로 대체했다. 레퍼런스에는 Similarly, it’s also possible to remove a selected few attributes:라고 아주 짧게 설명되어있어서 일단 무작정 시도해보았다.

const { Boards } = require('../../models');
const { Users } = require('../../models');

module.exports = {
  get : async (req, res) =>{
    Boards.findAll({
      order: [['createdAt', 'DESC']],
      attributes :{exclude :["content", "updatedAt"]},
      include : [
        { model : Users, 
          required: true, 
          attributes : {exclude :["id","email","password", "salt", "createdAt", "updatedAt"]} }
      ]
    }).then(data => {
        res.status(200).send(data)
    })
  }
}

Users 테이블에서는 nickname을 빼고 전부 불필요한 데이터이기 때문에 nickname을 제외한 모든 칼럼을 배제했고, Boards 테이블에서는 content 만 필요하지 않다고 판단하여 content 칼럼만 배제하였다.

[
  {
    "id": 2,
    "userId" : 1,
    "title": "제목입니다1",
    "likes": 0,
    "createdAt": "2021-08-01T06:02:00.000Z",
    "user": {
        "nickname": "팬더",
    }
  }
]

적용하고나면 위처럼 깔끔하게 출력된다.


2. 고민 중인 것

controllers/Boards/editBoard.js

const { Boards } = require('../../models');
const { Users } = require('../../models');

module.exports = {
  put : async (req, res) =>{
    const { id } = req.params;
    const email = req.user;

    const dbUserId = await Users.findOne({
      where : {
        email
      } 
    }).then(data => data.dataValues.id)

    const dbWriterId = await Boards.findOne({
      where : {
        id
      }
    }).then(data => data.dataValues.userId)

    if(dbUserId != dbWriterId) {
      res.status(400).send("You're not the author of this post.");
    }
    else {
      const {title , content} = req.body;
      
      if(!title && !content){
        Boards.update({},{
          where : { id }
        })
        .then (data => {
          console.log(data)
          res.status(200).send(data)
        })
      }
      else if(title && content) {
        Boards.update({
          title, content
        },{
          where : { id }
        })
        .then (data => {
          console.log(data)
          res.status(200).send(data)
        })
      }
      else {
        if (!title) {
          Boards.update({
            content
          },{
            where : { id }
          })
          .then (data => {
            console.log(data)
            res.status(200).send(data)
          })
        }
        else if (!content) {
          Boards.update({
            title
          },{
            where : { id }
          })
          .then (data => {
            console.log(data)
            res.status(200).send(data)
          })
        }
      }
    }
  }
}

포스트 수정 API에 중복되는 부분이 너무 많다…

Boards
    .update({
        //여기 들어오는 값만 다름.
    },{
        where : { id }
    })
    .then (data => {
        res.status(200).send(data)
    })

정확히는 위 코드가 각 if문에서 겹치고 있는데, 이걸 미들웨어화 하거나, 함수로 만들어서 줄어보고 싶다… ㅜ




© 2020. by RIVER

Powered by RIVER