우선 실행했을 때 떴던 오류를 확인하자.
MongooseError: Model.prototype.save() no longer accepts a callback
이 오류가 뜨는 이유는, Mongoose6 이전에는 Model.prototype.save()에 콜백 함수를 전달하여 비동기 작업이 완료될 때 실행되도록 할 수 있었는데, Mongoose 6에서는 이러한 방식의 사용이 중단되었다. 그래서 이제 이 콜백 함수 관련된 기능 제공이 불가하기 때문에 다른 방식으로 풀어내야한다.
Mongoose 6에서는 async/await 또는 Promise를 사용하여 비동기 작업을 처리 하면 되기 때문에 오류가 난 부분의 콜백 함수를 수정하여 Promise
를 반환하는 방식으로 변경하도록 할것이다.
Promise
: JavaScript에서 비동기 작업을 다루기 위한 객체
- 비동기 작업은 일반적으로 네트워크 요청, 파일 읽기/쓰기, 데이터베이스 쿼리 등의 작업을 포함
- Promise는 이러한 비동기 작업의 성공 또는 실패를 다루기 위한 방법을 제공
- resolve(value): Promise를 성공적으로 처리하고 결과값을 반환할 때 호출됨.
- reject(value): Promise 처리 중에 발생한 오류나 거부 사유를 전달하여 Promise를 거부할 때 호출됨
userSchema.methods.comparePassword = function (plainPW, cb) {
bcrypt.compare(plainPW, this.password, function (err, isMatch) {
if (err) return cb(err), cb(null, isMatch)
})
}
plainPW
로 되어있던 변수명은 plainPassword
로 변경했다)userSchema.methods.comparePassword = function (plainPassword) {
return new Promise((resolve, reject) => {
bcrypt.compare(plainPassword, this.password, (err, isMatch) => {
if (err) {
reject(err)
} else {
resolve(isMatch)
}
})
})
}
try-catch
: JavaScript에서 예외 처리를 위해 사용
- 비동기 코드나 예외가 발생할 수 있는 코드 블록을 감싸고, 예외가 발생하면 catch 블록에서 해당 예외를 처리
- try 블록: 예외가 발생할 수 있는 코드를 포함하는 블록
- catch 블록: 예외 처리를 위한 블록
async/await
- async 키워드로 선언된 함수는 비동기 함수
- await가 있는 부분에서 비동기 작업의 처리를 기다림
- 항상 Promise를 반환
- await 키워드: Promise를 처리하는데 사용
- async 함수 내에서만 사용할 수 있으며, Promise가 처리될 때까지 해당 표현식의 실행을 일시 중단함
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: "비밀번호가 틀렸습니다."
})
// 비밀번호 확인되면 토큰 생성
})
})
})
app.post('/login', async (req, res) => {
try {
// 요청된 이메일이 DB에 있는지 조회
const user = await User.findOne({ email: req.body.email })
if (!user) {
return res.json({
loginSuccess: false,
message: "제공된 이메일에 해당하는 유저가 없습니다."
})
}
// 비밀번호가 맞는지 확인
const isMatch = await user.comparePassword(req.body.password)
if (!isMatch) {
return res.json({
loginSuccess: false,
message: "비밀번호가 틀렸습니다."
})
}
// 비밀번호 확인되면 토큰 생성
} catch (err) {
return res.status(400).send(err)
}
})
이렇게 수정하면 이제 callback 관련 오류는 뜨지 않는다 ! 그리고 그 이후에 구현하는 부분들도 cb
대신 Promise
, async/await
를 사용하여 구현해야한다.