게시판 - 회원가입 ( 백엔드 )

김주언·2022년 10월 5일
0

MERN

목록 보기
4/4
post-thumbnail

1. User 모델 생성

board/server/models/User.js

const mongoose = require("mongoose");
// schema
const userSchema = mongoose.Schema(
  {
    userid: { type: String, required: true, unique: true },
    // select : false -> DB에서 데이터 읽어올 떄 password는 읽어오지 않는다.
    password: { type: String, required: true , select : false},
    name: { type: String, required: true },
    email: { type: String },
  },
  {
    toObject: { virtuals: true },
  }
);

// virtuals
userSchema
  .virtual("pwConfirm")
  .get(function () {
    return this._pwConfirm;
  })
  .set(function (value) {
    this._pwConfirm = value;
  });

userSchema
  .virtual("originPw")
  .get(function () {
    return this._originPw;
  })
  .set(function (value) {
    this._originPw = value;
  });

userSchema
  .virtual("currPw")
  .get(function () {
    return this._currPw;
  })
  .set(function (value) {
    this._currPw = value;
  });

userSchema
  .virtual("newPw")
  .get(function () {
    return this._newPw;
  })
  .set(function (value) {
    this._newPw = value;
  });

// password validation
userSchema.path("password").validate(function (value) {
  // this 는 유저 모델
  const user = this;

  // 유저 생성
  if (user.isNew) {
    // user가 새로운 document인 경우 -> 생성
    if (!user.pwConfirm) {
      // 모댈.invalidate : 첫번쨰로 인자 항목이름, 두번쨰로 인자 에러메세지
      user.invalidate("pwConfirm", "비밀번호 확인 칸을 입력하세요!");
    }

    if (user.password !== user.pwConfirm) {
      user.invalidate(
        "pwConfirm",
        "비밀번호와 비밀번호 확인이 일치하지 않습니다!"
      );
    }

    // 기존 유저 정보 수정
  } else {
    if (!user.currPw) {
      user.invalidate("currPw", "현재 패스워드를 입력하세요");
    } else if (user.currPw != user.originPw) {
      user.invalidate("currPw", "현재 패스워드가 틀렸습니다");
    }

    if (user.newPw !== user.pwConfirm) {
      user.invalidate("pwConfirm", "비밀번호 확인이 일치하지 않습니다!");
    }
  }
});


const User = mongoose.model("user", userSchema);
module.exports = User;
  • virtuals
    : DB에 실제로 저장되지는 않지만 필요한 값들. DB에 존재하는 값들로부터 만들어낼 수 있는 정보들. (회원가입이나 정보수정을 위해 새로운 password나 현재 패스워드가 필요하지만 저장할 필요는 없는 것처럼..)
    즉 DB에 저장될 필요는 없지만 model에서 사용하고는 싶은 항목들을 virtual로 생성
  • Schema.path
    SchemaType을 반환한다.

  • password validation
    패스워드를 데이터베이스에 생성 또는 수정하기 전 값이 유효한지 확인한다.

    • model.isNew
      해당 모델이 새로 생성되는 경우에는 true, 아닌 경우에는 false
      이를 이용하여 회원가입인지 회원정보 수정인지 판별 가능

2. 라우터 설정

HTTP VerbActionPath설명
GETindex/users모든 유저 리스트 조회
GETretrieve/users/:id특정 유저 조회
POSTcreate/users신규 유저 생성
PUTreplace/users/:id특정 유저 갱신
DELETEdelete/users/:id특정 유저 삭제

board/server/routes/users.js

전체 코드

const express = require("express");
const router = express.Router();
const User = require("../models/User");

router.get("/", (req, res) => {
  User.find({})
    .sort({ username: 1 })
    .exec((err, users) => {
      if (err) return res.json(err);
      res.json(users);
    });
});

router.get("/:_id", (req, res) => {
  User.findOne({ _id: req.params._id }, (err, user) => {
    if (err) res.json(err);
    res.json(user);
  });
});

router.post("/", (req, res) => {
  console.log(req.body);
  User.create(req.body, (err, user) => {
    if (err) res.json(err);
    res.json(user);
  });
});

router.put("/:_id", (req, res) => {
  User.findOne({ _id: req.params._id })
    .select("password")
    .exec((err, user) => {
      if (err) return res.json(err);

      // 유저 업데이트하기
      user.originPw = user.password;
      user.password = req.body.newPw ? req.body.newPw : user.password;

      for (para in req.body) {
        user[para] = req.body[para];
      }

      user.save((err, user) => {
        if (err) return res.json(err);
        res.json(user);
      });
    });
});

router.delete("/:_id", (req, res) => {
  User.deleteOne({ _id: req.params._id }, (err) => {
    if (err) return res.json(err);
    res.status(204).end();
  });
});

module.exports = router;

2.1 GET /users

router.get("/", (req, res) => {
  // 모든 다큐먼트 검색
  User.find({})
    .sort({ name: 1 })	// 유저의 이름을 기준으로 정렬한다. (역순 정렬은 -1)
    .exec((err, users) => {	// 실행
      if (err) return res.json(err);
      res.json(users);
    });
});


데이터베이스에 저장된 모든 유저의 목록을 반환한다.

생성된 유저들을 보면 virtual로 설정한 값들은 저장되지 않은 것이 확인된다.


2.2 GET /users/:id

// /users/ObjectId
router.get("/:_id", (req, res) => {
  // url로 넘어온 파라미터를 _id로 저장하여, 해당 아이디를 가지는 유저를 찾는다
  User.findOne({ _id: req.params._id }, (err, user) => {
    if (err) res.json(err);
    res.json(user);
  });
});

파라미터로 유저의 아이디를 전달받고 이를 이용하여 유저를 검색하여 반환한다.


2.2 POST /users

router.post("/", (req, res) => {
  console.log(req.body);
  User.create(req.body, (err, user) => {
    if (err) res.json(err);
    res.json(user);
  });
});

유저 생성 시 password와 pwConfirm이 필요하다. 유저 스키마를 살펴보면 virtual에서 pwConfirm을 생성하여 두었다.

userSchema
  .virtual("pwConfirm")
  .get(function () {
    return this._pwConfirm;
  })
  .set(function (value) {
    this._pwConfirm = value;
  });

validate 함수를 사용하여 유저 생성 시 패스워드 필드를 검증한다.

userSchema.path("password").validate(function (value) {
  // this 는 유저 모델
  const user = this;

  // 유저 생성
  if (user.isNew) {
    // user가 새로운 document인 경우 -> 생성
    if (!user.pwConfirm) {
      // 모댈.invalidate : 첫번쨰로 인자 항목이름, 두번쨰로 인자 에러메세지
      user.invalidate("pwConfirm", "비밀번호 확인 칸을 입력하세요!");
    }

    if (user.password !== user.pwConfirm) {
      user.invalidate(
        "pwConfirm",
        "비밀번호와 비밀번호 확인이 일치하지 않습니다!"
      );
    }
  • 패스워드와 패스워드 확인이 일치하지 않을 경우
  • 패스워드 확인을 작성하지 않은 경우
  • 정상적으로 모두 확인한 경우

2.3 PUT /users/:id

router.put("/:_id", (req, res) => {
  User.findOne({ _id: req.params._id })	// 1
    .select("password")					// 2
    .exec((err, user) => {
      if (err) return res.json(err);

      // 유저 업데이트하기
      user.originPw = user.password;
      user.password = req.body.newPw ? req.body.newPw : user.password;	// 3

      for (para in req.body) {		// 4
        user[para] = req.body[para];
      }

      user.save((err, user) => {	// 5
        if (err) return res.json(err);
        res.json(user);
      });
    });
});
  1. 파라미터를 전달받아서 이를 _id 변수로 넘겨서 해당 아이디를 이용하여 유저를 검색한다.

  2. 검색된 유저정보 중 패스워드만 선택한다.

  3. 요청 바디로 새로운 패스워드가 전달되었을 시 유저의 패스워드를 업데이트한다.
    3.1 이 때 유저 스키마에 지정한 검증 단계로 인해서 우선 현재 비밀번호를 (currPw) 확인한다.
    3.2 현재 비밀번호가 일치 할 시 새로운 비밀번호 (newPw) 와 비밀번호 재확인(pwConfirm)을 확인한다
    3.3 검증이 성공하면 유저 정보를 업데이트 한다.

  4. 요청 바디로 넘겨받은 데이터들로 유저의 정보를 업데이트 한다.

  5. Model.save 함수를 이용하여 정보를 저장한다.


2.4 DELETE /users/:id

router.delete("/:_id", (req, res) => {
  User.deleteOne({ _id: req.params._id }, (err) => {
    if (err) return res.json(err);
    res.status(204).end();
  });
});

삭제가 성공하면 반환하는 값이 없기 때문에 성공했다는 상태값을 반환하도록 설정한다.

profile
학생 점심을 좀 차리시길 바랍니다

0개의 댓글