오늘 뭐했냐/개발에 대한 주저리

23.10.05 콜백헬

스스로에게 2023. 10. 11. 13:49

NestJS 강의에서 비크립트를 사용했었다. 사용한 경험이 있었기 때문에 어렵지 않았는데 내가 사용한 방법과 달라서 찾아보던 중에 갑자기 예전에 그냥 아 이런거구나 하고 넘어갔던 콜백헬을 파고들게 되었다.

 

콜백함수 사용

const bcrypt = require('bcrypt');

// 솔트의 라운드 수를 정합니다. 라운드 수가 높을수록 보안이 강화되지만 처리 시간이 늘어납니다.
const saltRounds = 10;

// 사용자로부터 받은 비밀번호
const myPlaintextPassword = 'my_password';

// 솔트를 생성하고 비밀번호를 해시화합니다.
bcrypt.genSalt(saltRounds, function(err, salt) {
    if (err) throw err;

    // 비밀번호 해시화
    bcrypt.hash(myPlaintextPassword, salt, function(err, hash) {
        if (err) throw err;

        // 해시화된 비밀번호를 출력하거나 데이터베이스에 저장합니다.
        console.log(hash);
    });
});

bcrypt.genSalt에 콜백이 있고 그 콜백 안에 다시 bcrypt.hash가 있고 다시 또 콜백으로 암호화가 된다. 

bcrypt.genSalt -> 콜백1 -> bcrypt.hash -> 콜백2 

 

전체 과정 

  1. bcrypt.genSalt(saltRounds, callback) 함수를 호출합니다.
  2. 이 함수는 saltRounds 값을 기반으로 솔트를 생성합니다.
  3. 생성된 솔트는 콜백 함수의 두 번째 인자로 전달됩니다.
  4. 콜백 함수 내에서, 이 salt 값을 사용하여 bcrypt.hash() 함수를 호출하고, 평문 비밀번호를 해시화하려고 시도합니다.
  5. bcrypt.hash() 함수는 전달된 평문 비밀번호와 솔트 값을 결합합니다.
  6. 결합된 값에 대해 bcrypt는 내부적으로 해시 알고리즘을 실행하여 안전한 해시 값을 생성합니다.
  7. 생성된 해시 값은 bcrypt.hash() 함수의 콜백의 두 번째 인자로 전달됩니다.
  8. 콜백 함수 내에서, 이 hash 값을 사용하여 원하는 작업 (예: 콘솔에 출력, 데이터베이스에 저장 등)을 수행할 수 있습니다.

 

async/await을 사용한 경우

const bcrypt = require('bcrypt');

const saltRounds = 10;

const myPlaintextPassword = 'my_password';

async function hashPassword(plaintextPassword) {
    try {
        const salt = await bcrypt.genSalt(saltRounds);
        const hash = await bcrypt.hash(plaintextPassword, salt);
        console.log(hash);
        return hash;
    } catch (err) {
        console.error(err);
        throw err;
    }
}

hashPassword(myPlaintextPassword); // 함수를 호출해야 실제로 실행됩니다.

 

 

콜백이 아닌 await를 통해서 처리하는데 흐름을 보기가 쉽다. 이걸 보고 콜백헬이라고 하는 구나 좀 더 명확하게 알 수 있었다. 

 

  1. 기존 콜백 패턴:
    • 코드를 실행하면 bcrypt.genSalt 함수가 바로 실행되고, 그 함수의 결과에 따라 콜백 함수가 실행됩니다. 이 콜백 함수 내에서는 bcrypt.hash가 실행되며, 그 결과에 따라 또 다른 콜백 함수가 실행됩니다.
  2. 리팩토링된 비동기 패턴:
    • async로 선언된 hashPassword 함수를 먼저 정의만 합니다. 이 함수 내에서는 await를 사용하여 bcrypt.genSaltbcrypt.hash의 완료를 순차적으로 기다리고 실행합니다. 하지만, 이 함수는 정의만 되어 있고 아직 실행되지 않았습니다.
    • 따로 함수 호출 hashPassword(myPlaintextPassword);를 사용하여 hashPassword 함수를 실행하게 됩니다. 이 함수 호출을 하지 않으면 hashPassword 내부의 코드는 실행되지 않습니다.