회원가입 부분은 틀은 대략 잡혔으므로, 로그인 api를 생성해볼것이다.
UserSchema
의 값 중 email
값을 통해 유저를 조회하고, 해당 password
가 맞을 경우, 로그인에 성공하도록 할 것이다. 즉, email
과 password
값이 로그인을 할 때 필수값이 된다.
우선 여기 포스팅된 코드는 오류가 발생하는 코드이다 - 해당 오류를 해결한 과정은 다음 포스팅에 작성할 예정이다.
login
에서는 3가지의 과정을 거친다.
- 사용자가 입력한 이메일의 계정이 DB에 존재하는가
- 해당 이메일 계정의 비밀번호가 일치하는가
- 비밀번호가 일치한다면 token 생성
우선은 1번, 2번까지만 해결해보자.
이메일 조회하는 코드는 아래와 같다.
mongoDB
에서 제공되는 findOne
함수를 통해 사용자가 입력한 email
값을 조회한다. 만약 해당 값이 존재하지 않다면 loginSuccess
는 false
값을, message
는 해당 유저가 없다는 메시지를 json
형식으로 전달한다.
// index.js
app.post('/login', (req, res) => {
// 요청된 이메일이 DB에 있는지 조회
User.findOne({ email: req.body.email }, (err, user) => {
if (!user) {
return res.json({
loginSuccess: false,
message: "제공된 이메일에 해당하는 유저가 없습니다."
})
}
// 해당 이메일이 있다면 비밀번호가 맞는지 확인
// 비밀번호 확인되면 토큰 생성
})
})
비밀번호는 그 전의 포스팅을 보면 알겠지만, DB에 비밀번호의 값이 그대로 보이지 않도록 설정했기 때문에, 해시 값과 사용자가 입력한 비밀번호가 일치하는지 확인하는 과정의 코드가 필요하다.
comparePassword
함수를 생성하여 plainPW
와 this.password
를 비교한다.
plainPW
: 사용자가 회원가입할 때 입력했던 값 this.password
: 입력한 비밀번호(+salt)의 해시값 이 두 값을 bcrypt.compare
을 통해 비교하여 일치하지 않으면 err
값을 반환하고, 일치하면 isMatch
값이 true
임을 반환한다.
// User.js
userSchema.methods.comparePassword = function (plainPW, cb) {
bcrypt.compare(plainPW, this.password, function (err, isMatch) {
if (err) return cb(err)
cb(null, isMatch) //isMatch == true
})
}
index.js
에선 반환된 isMatch
값이 true
가 아니라면 loginSuccess
값은 false
, message
에는 비밀번호가 틀렸다는 메시지를 반환한다.
isMatch
가 true
라면 해당 비밀번호에 대한 token을 생성한다.
// index.js
// 해당 이메일이 있다면 비밀번호가 맞는지 확인
user.comparePassword(req.body.password, (err, isMatch) => {
if (!isMatch)
return res.json({ loginSuccess: false, message: "비밀번호가 틀렸습니다." })
app.post('/login', (req, res) => {
// 요청된 이메일이 DB에 있는지 조회
User.findOne({ email: req.body.email }, (err, user) => {
if (!user) {
return res.json({
loginSuccess: false,
message: "제공된 이메일에 해당하는 유저가 없습니다."
})
}
// 해당 이메일이 있다면 비밀번호가 맞는지 확인
user.comparePassword(req.body.password, (err, isMatch) => {
if (!isMatch)
return res.json({ loginSuccess: false, message: "비밀번호가 틀렸습니다." })
// 비밀번호 확인되면 토큰 생성
})
})
})
userSchema.methods.comparePassword = function (plainPW, cb) {
bcrypt.compare(plainPW, this.password, function (err, isMatch) {
if (err) return cb(err), cb(null, isMatch)
})
}
자.. 이제 내가 하면서 약간 스트레스 받았던 오류가 발생한다😩🥹
위와 같이 코드를 입력하고 서버를 키면 아래와 같은 오류가 발생한다
오류 발생 이유
Mongoose 6 버전 이전에는 Model.prototype.save()에 콜백 함수를 전달하여 비동기 작업이 완료될 때 실행되도록 할 수 있었지만, Mongoose 6에서는 이러한 방식의 사용이 중단되었다.
// Error
MongooseError: Model.prototype.save() no longer accepts a callback at model.save
이 error는 async/await 또는 Promise를 사용하여 비동기 작업을 처리해야 한다.
근데 다음 작업이 jwt를 이용하여 비밀번호를 저장하는 것이기 때문에 그를 하면서, 고칠 예정이었기 때문에 다음 포스팅에 정리하도록 하겠다 !
(정리해서 올리게 되면 아래에 링크를 달아둘것이다)
오류 해결 포스팅