Password Hashing (bcrypt로)

Odyssey·2025년 3월 23일
0

Next.js_study

목록 보기
39/58
post-thumbnail

2025.3.23 일요일의 공부기록

🔒 bcrypt로 비밀번호를 해시(Hash)하기 🔒

bcrypt는 비밀번호와 같은 민감한 정보를 안전하게 저장하기 위해 사용하는 대표적인 해시(Hash) 함수이다.
해시 함수는 입력값을 고정된 길이의 난수 형태로 변환하며, 단방향(One-way) 및 멱등성(idempotent)을 갖는다.

해시 함수의 특성

  • 단방향(One-way): 해시로 변환한 값을 원본으로 되돌릴 수 없다.
  • 멱등성(Idempotent): 같은 입력에 대해 항상 같은 해시 값을 출력한다.

bcrypt를 사용하는 이유는 다음과 같다.

  • 보안상 데이터가 유출되어도 해시된 비밀번호로만 존재하므로 원본 비밀번호를 알 수 없어 안전하다.
  • 해시 값은 항상 일정한 길이와 양식으로 저장되므로 데이터 관리에 유리하다.

bcrypt 설치하기

다음 명령어로 프로젝트에 bcrypt를 설치한다.

npm i bcrypt
npm i @types/bcrypt
  • 타입스크립트를 사용하는 경우 반드시 @types/bcrypt를 설치해야 한다.

bcrypt 비밀번호 해시하기 (async/await 활용법)

bcrypt는 비동기적으로 작동하는 라이브러리로, 내부적으로는 Promise 객체를 반환한다.
async/await를 사용하는 이유는 bcrypt가 비동기 연산을 기반으로 하므로, 코드가 간결해지고 Promise를 더 쉽게 관리할 수 있기 때문이다.

bcrypt를 async/await로 사용하는 예제 코드

다음은 Zod를 이용하여 데이터를 검증한 후, bcrypt로 비밀번호를 해시하여 데이터베이스에 저장하는 실습 예시이다.

import bcrypt from 'bcrypt';
import { z } from 'zod';
import db from './lib/db'; // Prisma Client import 예시

// 사용자 입력 데이터 스키마 정의 (Zod)
const formSchema = z.object({
  username: z.string().min(3).max(20),
  email: z.string().email(),
  password: z.string().min(6),
});

// 비밀번호 해시 및 데이터베이스 저장
async function registerUser(data: any) {
  const result = await formSchema.safeParseAsync(data);

  if (!result.success) {
    // 데이터 검증 실패 시, 에러 반환
    return result.error.flatten();
  } else {
    // 데이터 검증 성공 시 비밀번호 해시
    const hashedPassword = await bcrypt.hash(result.data.password, 12);
    /*
      bcrypt.hash(비밀번호, saltRounds)
      - saltRounds 값이 높을수록 보안성이 좋아지지만, 처리 속도는 느려진다.
      - 권장 값은 10~12이다.
    */

    // Prisma를 사용하여 데이터베이스에 사용자 저장
    const user = await db.user.create({
      data: {
        username: result.data.username,
        email: result.data.email,
        password: hashedPassword, // 해시된 비밀번호 저장
      },
      select: {
        id: true, // 생성된 사용자 ID만 반환
      },
    });

    console.log(user);
    // To-do : 로그인 처리 또는 홈 페이지로 리다이렉트 처리 가능 
  }
}

bcrypt 주요 메서드 정리

비밀번호 해시 (hash 메서드)

const hashedPassword = await bcrypt.hash(비밀번호, saltRounds);
  • saltRounds의 권장값은 보통 10~12이며, 높을수록 보안성이 강화된다.

비밀번호 검증 (compare 메서드)

저장된 해시값과 입력된 비밀번호를 비교할 때 사용한다.

const isCorrect = await bcrypt.compare(입력된비밀번호, 저장된해시값);

if (isCorrect) {
  // 비밀번호가 일치함
} else {
  // 비밀번호가 일치하지 않음
}

0개의 댓글