초보자를 위한 코드 품질 리포트 읽기 2편 – Bandit이 싫어하는 MD5 SHA-256으로 바꿔야 하는 이유?

1편에 이어서 이번 포스트에서는 MD5 SHA-256으로 바꿔야 하는 이유에 대해 알아보겠습니다.
“왜 MD5가 밉상이 되었는지”와 “그래서 SHA-256으로 어떻게, 어디까지 바꿔야 하는지”를 초보자 관점에서 천천히 풀어보려 합니다.
1. 품질 리포트에서 MD5가 High로 뜨는 이유
실제 품질 리포트에서 Bandit 결과를 보면 이런 문장이 나옵니다.
- High 경고 3건 – MD5 사용 위치
- 어떤 유틸 함수에서 식별자 해싱
- 뷰 로직에서
data_hash생성에 MD5 사용
Bandit 입장에서는 “MD5 = 기본적으로 위험 후보”입니다.
심지어 “약한 해시 알고리즘”이라서 High로 분류하는 경우가 많아요.
그럼 왜 이렇게까지 MD5를 싫어할까요?
2. 해시 함수, 아주 빠르게 개념만 잡고 가기

먼저 해시 함수 자체를 한 줄로 정리하면
“어떤 데이터를 고정 길이의 지문(해시)으로 바꿔주는 함수”
예를 들면
- 비밀번호 저장할 때
- 이메일 주소를 직접 저장하지 않고, 통계용으로만 쓸 때
- URL에 짧은 토큰을 쓰고 싶을 때
(예:/invite/abc123xyz/이런 느낌)
등등에 자주 씁니다.
좋은 해시 함수는
- 역추적이 매우 어려워야 하고 (원문을 추측하기 힘듦)
- 충돌(서로 다른 입력인데 같은 해시)이 거의 안 나야 in the file.
여기서 문제가 되는 게 MD5예요.
3. MD5는 왜 이제 “안전하지 않다”고 할까?
MD5는 한때 엄청 인기 많던 해시 함수였지만,
지금은 보안 업계에서 이렇게 취급됩니다.
“속도는 빠르지만,
보안용으로는 더 이상 쓰지 말자.”
그 이유는 크게 두 가지입니다.
1️⃣ 충돌 공격이 가능
- 서로 다른 두 데이터가 같은 MD5 값을 가지도록
인위적으로 만드는 공격이 이미 연구·실제 시연까지 되었음.
2️⃣ 너무 넓게 알려진 알고리즘 + 빠른 속도
- 공격자가 무차별 대입(brute force)이나
레인보우 테이블(사전 계산된 해시 목록)을 통해
특정 해시가 어떤 값인지 비교적 쉽게 유추할 수 있음.
즉, 비밀번호, 인증 토큰, 서명, 보안에 중요한 값에
MD5를 계속 쓰는 건 지금 시점에서는 위험한 선택Answer.
그래서 Bandit MD5 경고를 보면 바로
- “이건 High 레벨 보안 이슈일 수 있다”
라고 경고를 띄워주는 거죠.
4. SHA-256은 뭐가 다를까?
SHA-256은 SHA-2 계열 해시 함수 중 하나입니다.
- 출력 길이: 256비트 (보통 64자리 16진수 문자열)
- 현재 기준으로는 보안상 훨씬 강한 해시 함수로 인정받고 있음
- 비밀번호, 토큰, 서명, 메시지 무결성 등에서 널리 사용
당연히 “완전 영원히 안전” 같은 건 없지만,
지금 시점에서 MD5를 쓸 이유는 거의 없고,
MD5 SHA-256로 교체하는 것이 기본 선택.
그래서 우리가 실제로 해야 할 일은
기존 코드에서 MD5 SHA-256으로 교체
하고, 그게 어떤 의미인지 이해하는 것
5. 실전 예시 – Python 코드에서 MD5 SHA-256으로 바꾸기

초보자 입장에서 가장 궁금한 건 이거죠.
“그래서 실제 코드는 어떻게 고치는 건데요?”
아주 단순한 패턴부터 보면
5-1. 기존 MD5 코드 (예시)
import hashlib
def make_token(value: str) -> str:
return hashlib.md5(value.encode("utf-8")).hexdigest()[:8]- 문자열을 받아서
md5해시를 만들고 - 그 중 앞의 8자리만 잘라서 토큰으로 쓰는 경우입니다.
5-2. MD5 SHA-256 변경 예시
import hashlib
def make_token(value: str) -> str:
# SHA-256으로 변경
return hashlib.sha256(value.encode("utf-8")).hexdigest()[:8]겉으로 보기에는
딱 한 줄만 바뀐 것 같지만, 의미는 꽤 큽니다.
- 해시 알고리즘이 바뀌었기 때문에
같은 입력 값이라도 완전히 다른 값이 나오고, - 기존에 저장해 둔 토큰과는 호환되지 않습니다.
그래서 여기서 중요한 질문이 하나 나옵니다.
“이 토큰, 어디에 저장돼 있고,
이 값을 믿고 있는(의존하는) 시스템이 따로 있나?”
6. MD5 SHA-256 변경 전에 꼭 체크해야 할 것들
해시 교체는 코드 한 줄 수정처럼 보이지만,
데이터와 외부 시스템에 영향을 줄 수 있는 변경.
아래 네 가지를 꼭 체크해 보세요.
✅ 1) 이 해시는 어디에 쓰이나요?
- 단순히 “화면에서만 잠깐 쓰는 값”인지
- DB에 저장돼서 중복 체크, 캐시 키, 초대코드 등으로 쓰이는지
- 외부 시스템과 API 파라미터/링크로 주고받는 값인지
✅ 2) 기존 값과 “연결된” 게 있는지
- 이미 발급해 둔 링크(URL)
- 이미 사용자에게 발송된 초대코드, 인증코드
- 외부 시스템이 이 값을 키로 삼고 있는지
이게 하나라도 있으면,
MD5 SHA-256 변경을 할 때 전환 전략is required.
✅ 3) 교체 전략 예시
전략 A – 당장 교체 (내부용/캐시용)
- 내부 캐시 키, 통계용 익명 식별자 등
“새로 만들어도 상관 없는 값”이면 그냥 바꿔도 됩니다. - Example:
- “이 해시는 오늘부터 새로 찍는 데이터에만 쓸게요”
- 예전 데이터는 안 써도 상관없거나, 자동으로 갱신됨
전략 B – 점진 교체 (사용자에게 노출된 토큰)
- 초대코드처럼 이미 사용자에게 나간 값이면
- 일정 기간 동안은
- “MD5로 만든 코드도 받기 + 새 코드는 SHA-256로 발급”
- 이후에는 MD5 코드는 만료시키고
SHA-256만 받도록 정책 변경
- 일정 기간 동안은
전략 C – 버전 정보 추가
- 해시를 저장할 때 “버전” 컬럼을 추가해서
version = 'md5'version = 'sha256'
- 인증/검증 시
- 버전을 보고 어떤 알고리즘으로 검증할지 결정
- 나중에 md5 버전만 따로 제거 가능
7. Bandit MD5 경고를 실제 작업 계획으로 바꾸는 법

Bandit MD5 경고를 실제 작업 계획으로 바꾸는 법으로 브랜치 생성-머지 전략을 제안드립니다.
- MD5 → SHA-256 교체용 별도 브랜치 생성 (예:
quality/security-md5-change) - MD5 사용하는 모든 위치를 찾아서
- SHA-256으로 교체
- 해시 길이/토큰 길이(슬라이싱)를 어떻게 할지 정리
- 그 후에
- flake8, bandit, 테스트(
manage.py check등)를 실행 - 문제가 없는지 확인 후 메인 브랜치에 머지
- flake8, bandit, 테스트(
이 방식은 초보자에게도 정말 안전한 패턴.
“보안 관련 큰 변경은 항상
👉 별도 브랜치 → 체크 → 리뷰 → 머지
이 루틴을 타는게 좋다.”
특히 Bandit가 High로 찍는 경우는
“그냥 지나가면 언젠가 사고 난다”에 가까워요.
MD5 SHA-256 변경 작업은
“귀찮지만 피하면 안 되는 최소한의 보안 투자”라고 생각하면 됩니다.
8. 용어 정리
- MD5
예전에 많이 쓰이던 해시 함수.
지금은 충돌 공격 등으로 인해
비밀번호·토큰 등 보안 민감 용도에는
사용하지 말라고 권고되는 알고리즘입니다. - SHA-256
SHA-2 계열 해시 함수 중 하나.
현재 기준으로는 안전성이 검증되어
토큰, 서명, 무결성 검증 등에 널리 사용됩니다. - 해시 충돌
서로 다른 두 데이터가
같은 해시 값을 가지는 현상.
보안 관점에서는 치명적입니다. - 토큰(Token)
사용자를 구분하거나,
특정 요청을 인증하기 위해 쓰는
짧은 문자열(키 값). - Bandit MD5 경고
Bandit가 MD5 사용을 발견했을 때
보안 이슈 가능성이 높다고 판단해 띄우는 High 레벨 경고.
다음 포스트에서는 mark_safe, raw SQL, urllib 관련 보안 경고를 실제 Django 관점에서 어떻게 이해하고, 어떤 기준으로 “위험/안전”을 구분할지 정리해볼게요.






