본문 바로가기

Study

[Mongoose] pre 메소드에서 암호화를 했는데 DB에는 plain text가 저장되는 문제

userSchema.pre('save', function (next) {
    var user = this;
    if (user.isModified('password')) {
        //Encrypt password
        bcrypt.genSalt(saltRounds, function (err, salt) {
            if (err) return next(err);
            bcrypt.hash(user.password, salt, function (err, hash) {
                if (err) return next(err);
                // Store hash in your password DB.
                user.password = hash;
            });
        });
        next();
    }
});

위와 같이 Mongoose의 pre 메소드를 사용해 user 데이터를 'save'하기 전에 Bcrypt를 사용한 암호화를 실행하도록 코드를 구현하였다. 암호화된 비밀번호가 저장되길 기대하며 postman으로 리퀘스트를 날렸지만 DB를 확인해보니 아래의 사진과 같이 암호화 되지 않은 값이 저장되었다.

무엇이 문제였을까? 내가 작성한 기존 코드에서의 실수를 쉽게 이해할 수 있는 단순한 예시를 작성해 보았다.

hello world를 기대했으나 결과물은 world hello인 상황

윗 줄의 코드가 모두 실행된 후 아랫줄의 코드가 실행될 것이라는 당연한 착각을 해 버린 것이다.

world의 출력이 3000ms의 지연 시간을 기다리지 않은 것처럼, 내 소스코드의 next() 호출도 genSalt의 실행을 기다리지 않는다. 암호화를 하기도 전에 next()를 호출해 pre메소드를 마치고 다음 작업(save)으로 넘어가는 문제가 발생한다.

userSchema.pre('save', function (next) {
    var user = this;
    if (user.isModified('password')) {
        //Encrypt password
        bcrypt.genSalt(saltRounds, function (err, salt) {
            if (err) return next(err);
            bcrypt.hash(user.password, salt, function (err, hash) {
                if (err) return next(err);
                // Store hash in your password DB.
                user.password = hash;
                next();
            });
        });
    } else {
        next();
    }
});

따라서 위와 같이 next를 문제 없이 호출할 수 있는 부분으로 옮겨주고 다시 테스트를 실행했다.

짜잔! JaneDoe의 비밀번호가 성공적으로 암호화 되었다.