[Node.js/React] MongooseError: Model.prototype.save() no longer accepts a callback 오류 해결

·2023년 6월 30일
0

node-react 기초 공부

목록 보기
9/12
post-thumbnail

✔️오류 확인

우선 실행했을 때 떴던 오류를 확인하자.

MongooseError: Model.prototype.save() no longer accepts a callback

이 오류가 뜨는 이유는, Mongoose6 이전에는 Model.prototype.save()에 콜백 함수를 전달하여 비동기 작업이 완료될 때 실행되도록 할 수 있었는데, Mongoose 6에서는 이러한 방식의 사용이 중단되었다. 그래서 이제 이 콜백 함수 관련된 기능 제공이 불가하기 때문에 다른 방식으로 풀어내야한다.


💡해결방법

Mongoose 6에서는 async/await 또는 Promise를 사용하여 비동기 작업을 처리 하면 되기 때문에 오류가 난 부분의 콜백 함수를 수정하여 Promise를 반환하는 방식으로 변경하도록 할것이다.

✏️ User.js 코드 수정

Promise
: JavaScript에서 비동기 작업을 다루기 위한 객체

  • 비동기 작업은 일반적으로 네트워크 요청, 파일 읽기/쓰기, 데이터베이스 쿼리 등의 작업을 포함
  • Promise는 이러한 비동기 작업의 성공 또는 실패를 다루기 위한 방법을 제공
    - resolve(value): Promise를 성공적으로 처리하고 결과값을 반환할 때 호출됨.
    - reject(value): Promise 처리 중에 발생한 오류나 거부 사유를 전달하여 Promise를 거부할 때 호출됨
  • ❌수정 전 User.js❌
userSchema.methods.comparePassword = function (plainPW, cb) {
    bcrypt.compare(plainPW, this.password, function (err, isMatch) {
        if (err) return cb(err), cb(null, isMatch)
    })
}

  • ⭕수정 후 User.js⭕
    (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)
            }
        })
    })
}

✏️ index.js 코드 수정

try-catch
: JavaScript에서 예외 처리를 위해 사용

  • 비동기 코드나 예외가 발생할 수 있는 코드 블록을 감싸고, 예외가 발생하면 catch 블록에서 해당 예외를 처리
    - try 블록: 예외가 발생할 수 있는 코드를 포함하는 블록
    - catch 블록: 예외 처리를 위한 블록

async/await

  • async 키워드로 선언된 함수는 비동기 함수
    - await가 있는 부분에서 비동기 작업의 처리를 기다림
    - 항상 Promise를 반환

  • await 키워드: Promise를 처리하는데 사용
    - async 함수 내에서만 사용할 수 있으며, Promise가 처리될 때까지 해당 표현식의 실행을 일시 중단함
  • ❌수정 전 index.js❌
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: "비밀번호가 틀렸습니다." 
                })
        // 비밀번호 확인되면 토큰 생성
        })
    })
})

  • ⭕수정 후 index.js⭕
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를 사용하여 구현해야한다.


👩‍💻 깃허브 주소

node-react

0개의 댓글