안녕하세요, 이번 글에서는 실무에서도 많이 사용하는 BCrypt 해시 알고리즘에 대해 정리해보려고 합니다.
단순히 라이브러리만 사용하는 것을 넘어서, 왜 써야 하는지, 어떻게 동작하는지 까지 이해하는 것이 목표입니다.
비밀번호 저장은 "암호화"가 아니라 "해시"로
많은 분들이 비밀번호를 암호화해서 저장한다고 말하지만, 정확히는 "해시(Hash)" 해야 합니다.
| 방향성 | 단방향 (복호화 불가) | 양방향 (복호화 가능) |
| 사용 목적 | 비교용, 위조 방지 | 데이터 보호 |
| 비밀번호 저장에 적합? | 예 | 아니오 |
암호화는 키가 유출되면 누구나 복호화할 수 있기 때문에 비밀번호 저장용으로는 부적절합니다.
따라서 우리는 복호화가 불가능한 단방향 해시 함수를 사용해야 합니다.
해시(Hash)란?
입력값(비밀번호 등)을 고정된 길이의 문자열로 변환하는 함수
- 복호화가 불가능함
- 같은 입력 → 항상 같은 출력
- 대표 알고리즘: SHA-256, SHA-1, MD5, BCrypt
하지만 SHA-256, MD5는 빠르게 계산되기 때문에 Brute-force 공격에 취약합니다.


그래서 나온 것이 BCrypt
BCrypt는 Blowfish 알고리즘을 기반으로 만든 비밀번호 저장용 해시 함수입니다.
다음과 같은 특징을 가집니다:
| Salt 내장 | 매번 다른 salt를 생성하여 같은 비밀번호도 다른 해시 생성 |
| Cost factor 지원 | 연산 횟수를 조절해 공격을 어렵게 함 |
| 복호화 불가능 | 철저한 단방향 해시 |
| 결과 문자열에 정보 포함 | salt, cost, 해시값을 모두 문자열에 포함 |
| Spring Security 기본값 | BCryptPasswordEncoder로 바로 사용 가능 |
Salt란?
Salt는 해시 전에 붙이는 무작위 문자열입니다.
같은 비밀번호라도 다른 salt를 사용하면 완전히 다른 해시값이 생성됩니다.
| userA | password123 | abc123 | XYZ... |
| userB | password123 | zxc987 | QWE... |
이렇게 하면 해커가 사전 만들어둔 레인보우 테이블로 역추적하는 것을 방지할 수 있습니다.

레인보우 테이블이란?
자주 사용되는 비밀번호에 대한 해시값을 미리 계산해서 저장해둔 테이블
예:
123456 → e10adc3949ba59abbe56e057f20f883e
qwer1234 → ab56b4d92b40713acc5af89985d4b786
→ 해시만 보고도 어떤 비밀번호인지 알아낼 수 있음
→ Salt를 쓰지 않으면 이 공격에 매우 취약합니다.

그런데 궁금하죠?
"같은 비밀번호라도 매번 해시값이 달라진다며?
그럼 로그인할 때 어떻게 비교해요?"
여기서부터가 BCrypt의 핵심 기술입니다.
BCrypt는 해시 안에 salt를 포함시킨다!
BCrypt로 비밀번호를 해싱하면 다음처럼 생긴 문자열이 나옵니다:
$2a$10$WqRf8g1D33tX6SPZzAsT0OZADZ5POZNUKj2HNGIrBxkOcLCUo3GcK
구간 의미
| $2a$ | 알고리즘 버전 |
| 10$ | Cost factor (2¹⁰ = 1024번 반복) |
| WqRf8g1D33tX6SPZzAsT0O | 22자리 salt |
| 나머지 | 최종 해시값 (salt + 비밀번호 해싱 결과) |
로그인할 때 비교는 어떻게 하나? (스프링 JAVA)
passwordEncoder.matches("입력한 비밀번호", "DB에 저장된 해시값");
matches() 내부에서는 다음 과정을 수행합니다:
- 저장된 해시값에서 salt, cost 정보를 추출
- 입력한 비밀번호 + 추출된 salt → 같은 방식으로 다시 해싱
- 새로 계산한 해시값과 기존 해시값이 일치하면 로그인 성공
✔️ 즉, BCrypt는 비교에 필요한 모든 정보(salt 포함)를 해시 문자열에 내장해놓습니다.
❌ 별도로 salt를 저장하거나 비교할 필요가 없습니다.
정리
| 왜 비밀번호는 암호화가 아니라 해시해야 하나요? | 복호화되면 안 되니까 |
| 해시만 저장해도 괜찮나요? | salt를 쓰면 안전합니다 |
| 같은 비밀번호인데 해시값이 매번 다른 이유는? | salt가 무작위로 들어가기 때문입니다 |
| 그럼 어떻게 비교하나요? | 해시 안에 salt가 포함되어 있고, 이를 기반으로 재해싱하여 비교합니다 |
BCrypt는 단순히 "라이브러리를 쓰면 되는 기술"이 아닙니다.
원리까지 이해해야 보안 사고 없이 안전한 서비스를 설계할 수 있습니다.
오늘 포스팅이 여러분의 보안 지식에 도움이 되었길 바랍니다!