[Backend] 로그인과 해싱

김민호·2026년 3월 24일

Backend

목록 보기
1/2

백엔드 개발을 하다 보면 CRUD 다음으로 마주하는 산이 바로 '회원 로그인' 기능이다. 로그인을 만든다는 건 곧 시스템의 보안을 다뤄야 한다는 뜻이다. 이때 다음 문장을 꼭 기억하자.

"보안은 잘하는 것이 아니라, 보안 사고가 터질 수밖에 없는 구조 자체를 만들지 않는 것이다."

암호화가 아닌 단방향 해싱

처음 로그인 기능을 구현할 때 흔히 "비밀번호를 안전하게 암호화해야지"라고 생각하기 쉽다. 하지만 이는 정답이 아니다. 정답은 '단방향 해싱(Hashing)'이다. 암호화는 복호화(원본으로 되돌림)가 가능하다는 것을 전제로 한다. 만약 DB가 털리면서 암호화 키까지 유출된다면, 모든 유저의 비밀번호 원본이 고스란히 노출되는 치명적인 사고로 이어진다. 반면 해싱은 입력값을 넣으면 항상 같은 결과가 나오지만, 원래 값으로 되돌리는 것(복호화)은 불가능하다. 즉, 비밀번호는 '확인'만 가능해야 하며 시스템 관리자조차 다시는 원본을 꺼낼 수 없어야 한다.

💡 로그인 인증 흐름
로그인 시에는 이 단방향 원리를 이용한다.
1. 사용자가 회원가입(이메일 + 비밀번호)을 한다.
2. DB에는 비밀번호 원본이 아닌, 해싱된 '해시값'이 저장된다.
3. 사용자가 다음에 로그인할 때 입력한 비밀번호를 똑같이 해싱하여, DB에 저장된 해시값과 비교한다.
4. 두 해시값이 일치하면 인증을 통과시킨다.


아무 해시 함수나 쓰면 안 되는 이유

단방향이라고 해서 SHA-256 같은 일반적인 해시 함수를 로그인에 써서는 안 된다. 일반 해시 함수는 처리 속도가 너무 빠르다. 해커가 무차별 대입(Brute Force) 공격으로 비밀번호를 순식간에 알아낼 위험이 크고, 미리 계산해 둔 해시값 표(레인보우 테이블)를 이용해 역추적할 수도 있다.

따라서 안전한 패스워드 해시 알고리즘은 다음 3가지 조건을 반드시 갖춰야 한다.

  1. 속도가 느려야 한다.
    계산 속도를 의도적으로 늦춰야 한다. 1초에 수십억 개의 해시값을 대입할 수 있는 것과 1초에 1개밖에 대입하지 못하는 것은 하늘과 땅 차이다. 공격자의 시간 비용을 기하급수적으로 늘려 해커가 스스로 공격을 포기하게 만들어야 한다.
  2. 메모리를 많이 써야 한다.
    해시값을 하나 만드는 데 막대한 자원(메모리)을 소모하게 만들면, 한 번에 생성할 수 있는 해시값의 수가 급격히 줄어든다. 이는 병렬 처리를 통한 대규모 공격을 방어하는 핵심이다.
  3. 솔트(Salt)가 포함되어야 한다.
    비밀번호 원본에 임의의 텍스트(솔트)를 덧붙여 해싱하는 방식이다. 이렇게 하면 똑같은 비밀번호를 쓰는 유저라도 DB에는 전혀 다른 해시값이 저장되어, 레인보우 테이블 공격을 완벽히 무력화할 수 있다.

이 모든 조건을 만족하는 알고리즘으로 Argon2id, bcrypt, scrypt 등이 있다. 그중에서도 현재 백엔드 실무 표준이자 가장 강력히 권장되는 알고리즘은 Argon2id다. 이걸 사용하자.


로그인 로직 구현 시 놓치면 안 되는 보안 디테일 3가지

알고리즘 선택은 끝났다. 하지만 실제 로그인 로직을 짤 때 다음 3가지 디테일을 놓치면 시스템에 빈틈이 생긴다. 꼭 기억하자.

1. 타이밍 공격(Timing Attack) 방어

로그인을 시도할 때 DB에 해당 이메일이 없으면 바로 에러를 반환하고, 이메일이 존재하면 패스워드 검증을 하느라 시간이 조금 더 걸린다고 가정해 보자. 해커는 이 미세한 '응답 시간의 차이'를 측정해 특정 이메일이 시스템에 가입되어 있는지 알아낼 수 있다.
이를 막으려면 DB에 이메일이 존재하지 않더라도 임의의 더미(Dummy) 해시 검증 로직을 실행하도록 만들어야 한다. 성공하든 실패하든 응답 시간을 동일하게 맞춰서 해커의 눈을 속이는 것이다.

2. 계정 열거(Enumeration) 방어

에러 메시지를 친절하게 "존재하지 않는 계정입니다"와 "비밀번호가 틀렸습니다"로 나누어주면, 해커는 이를 이용해 유효한 이메일 목록만 싹 수집한 뒤 집중 공격을 퍼부을 수 있다.
시스템 내부 정보가 노출되지 않도록, 계정이 없든 비밀번호가 틀렸든 응답 메시지는 무조건 "이메일 또는 비밀번호가 올바르지 않습니다"로 뭉뚱그려 통일해야 한다.

3. 재해싱(Rehashing)

시간이 흘러 컴퓨팅 파워가 발전하면 보안 정책(해싱 반복 횟수, 메모리 사용량 등)을 더 강력하게 업그레이드해야 한다. 이때 기존 유저들의 구버전 해시값은 어떻게 할까?
유저가 이전 방식으로 해싱된 비밀번호로 정상 로그인을 성공했을 때, 백그라운드에서 새로운 보안 정책이 적용된 해시값으로 DB를 조용히 업데이트해 주면 된다. 이를 재해싱이라 부르며, 유저가 모르는 사이에 시스템 보안을 알아서 최신으로 유지하는 마이그레이션 기법이다.

profile
개발자를 꿈꾸고 있어요

0개의 댓글