Django 개인정보 암호화 시스템 완벽 적용 가이드: Fernet + HMAC-SHA256 (2026 최신)

Django 개인정보 암호화가 왜 중요한가요? 사번, 이름 등과 같은 민감 개인정보를 DB에 저장할 때 반드시 암호화가 필수입니다. 이 포스트에서는 기존 프로젝트에서 실제 적용한 Django 개인정보 암호화 시스템을 상세히 공개합니다.

HMAC-SHA256 해시 + Fernet(AES-128) 대칭 암호화 + Custom EncryptedCharField를 조합한 실전 아키텍처를 코드와 함께 설명합니다. Django 개인정보 암호화를 처음 도입하는 중이시라면 이 가이드 하나로 끝낼 수 있습니다.

1. 프로젝트에서 Django 개인정보 암호화가 필요한 이유

일반적으로 기업에서 개발하는 대부분의 앱은 내부 직원(사번 기반) 인증 시스템입니다. 사번과 이름은 개인정보로 취급되며, DB 탈취 시 복호화가 불가능해야 개인정보보호법을 만족합니다.

Django 개인정보 암호화 전략 요약

  • employee_no: HMAC-SHA256 해시 (복호화 불가, 인증·고유성 조회용)
  • employee_no_plain: Fernet 암호화 (표시용, 복호화 가능)
  • 名字: Fernet 암호화 (표시용)
  • password: Django 기본 PBKDF2-SHA256 단방향 해시

이렇게 하면 DB가 유출되어도 키 없이는 어떤 정보도 복구할 수 없습니다.

Django 개인정보 암호화 시스템 아키텍처 프로젝트 HMAC Fernet

2. Django 개인정보 암호화 핵심 전략 상세 비교

字段저장 방식용도복호화 가능?
employee_noHMAC-SHA256 해시로그인·조회불가
employee_no_plainFernet 암호문관리자 화면 표시
名字Fernet 암호문표시·검색
passwordPBKDF2-SHA256로그인 인증불가

Django 개인정보 암호화의 핵심은 “조회용은 해시, 표시용은 대칭 암호화”를 분리하는 것입니다.

3. HMAC-SHA256 구현 (employee_no 보호)

# apps/accounts/encryption.py
# HMAC-SHA256을 이용한 employee_no 해시 생성 함수
# 목적: 사번을 평문으로 DB에 저장하지 않고 단방향 해시로 저장
#       → DB가 유출되어도 원본 사번을 복구할 수 없도록 보안 강화

import hashlib
import hmac as _hmac
from django.conf import settings


def hmac_of(value: str) -> str:
    """
    입력된 평문 사번을 HMAC-SHA256 해시로 변환하여 반환합니다.
    
    - KEY: settings.FIELD_HMAC_KEY (환경변수로 관리, Git에 절대 커밋 금지)
    - 복호화가 불가능한 단방향 해시 → 로그인 시 조회용으로만 사용
    - 동일한 사번은 항상 동일한 해시값이 생성되어 중복 가입 방지
    """
    # 설정에서 HMAC 키를 가져옴 (str 또는 bytes 모두 지원)
    key = settings.FIELD_HMAC_KEY
    
    return _hmac.new(
        key.encode() if isinstance(key, str) else key,   # 키를 bytes로 변환
        value.encode(),                                  # 입력 사번을 bytes로 변환
        hashlib.sha256                                   # SHA256 알고리즘 사용
    ).hexdigest()                                        # 64자리 hex 문자열로 반환

회원가입 시 employee_no = hmac_of(plain_no)로 저장해 복호화 불가능하게 만듭니다.

4. Fernet 암호화 + Custom EncryptedCharField (가장 강력한 Django 개인정보 암호화 기법)

# apps/accounts/fields.py
# Fernet 암호화를 Django 모델 필드에서 투명하게 사용할 수 있게 해주는 커스텀 필드
# 특징: 모델 코드에서는 평문처럼 사용해도 DB에는 자동으로 암호문이 저장됨

from django.db import models
from .encryption import encrypt_value, decrypt_value


class EncryptedCharField(models.TextField):
    """
    Django에서 개인정보(이름, 사번 평문 등)를 Fernet으로 암호화해서 저장하는 커스텀 필드
    
    - DB에는 암호문(ciphertext)만 저장
    - Python 코드에서는 평문(plaintext)으로 자동 변환되어 사용 가능
    - NSCG 준수에 필수적인 투명 암호화(Transparent Encryption) 구현
    """

    def from_db_value(self, value, expression, connection):
        """
        DB에서 데이터를 읽어올 때 자동으로 복호화하는 메서드
        - value: DB에 저장된 암호문
        - decrypt_value() 호출 → 평문 반환
        """
        return decrypt_value(value) if value is not None else value

    def get_prep_value(self, value):
        """
        DB에 저장하기 직전에 자동으로 암호화하는 메서드
        - value: 모델에서 입력된 평문
        - encrypt_value() 호출 → 암호문으로 변환 후 DB에 저장
        """
        if value is None or value == '':
            return value
        return encrypt_value(value)

Django 개인정보 암호화의 핵심 Custom Field입니다. 모델에서 평문처럼 사용해도 DB에는 자동 암호문이 저장됩니다.

Django 개인정보 암호화 Custom EncryptedCharField 코드 KARIS

5. encryption.py 전체 유틸리티 (실전 코드)

# apps/accounts/encryption.py
# Fernet (AES-128 기반) 대칭 암호화 관련 핵심 유틸리티 모음
# 모든 개인정보 암호화·복호화 작업은 이 파일을 통해 중앙 집중 관리

from cryptography.fernet import Fernet, InvalidToken
from django.conf import settings


def _fernet() -> Fernet:
    """
    Fernet 인스턴스를 생성하는 내부 헬퍼 함수
    - settings.FIELD_ENCRYPTION_KEY를 사용해 Fernet 객체 생성
    - 매번 새로 생성하지 않고 필요할 때마다 호출 (성능과 보안 균형)
    """
    key = settings.FIELD_ENCRYPTION_KEY
    # 키가 str이면 bytes로 변환 (Fernet은 bytes 키만 허용)
    return Fernet(key.encode() if isinstance(key, str) else key)


def encrypt_value(plain: str) -> str:
    """
    평문 데이터를 Fernet으로 암호화하여 반환
    - 빈 문자열이나 None은 그대로 반환 (오류 방지)
    - 실제 DB에 저장될 암호문 생성
    """
    if not plain:
        return plain
    return _fernet().encrypt(plain.encode()).decode()   # bytes → str 변환


def decrypt_value(cipher: str) -> str:
    """
    Fernet 암호문을 복호화하여 평문으로 반환
    - InvalidToken 예외 발생 시 원본 암호문을 그대로 반환
      → 마이그레이션 전 기존 평문 데이터와의 호환성을 위해 필수
    """
    if not cipher:
        return cipher
    try:
        return _fernet().decrypt(cipher.encode()).decode()
    except (InvalidToken, Exception):
        # 복호화 실패 시 (키 변경, 마이그레이션 전 데이터 등) 원본 반환
        return cipher

6. .env + settings.py 설정 (키 관리 필수)

FIELD_ENCRYPTION_KEY=your_44char_fernet_key_here==
FIELD_HMAC_KEY=your_64char_hex_hmac_key_here

Django 개인정보 암호화에서 가장 중요한 것은 키를 절대 Git에 커밋하지 말고 환경변수 또는 secrets manager에 보관하는 것입니다.

7. DB 정기 백업도 Fernet으로 암호화 (완전 보안)

python manage.py backup_db 커맨드로 MySQL/SQLite를 Fernet 암호화된 .enc 파일로 백업합니다.
cPanel Cron으로 매일 새벽 자동 실행 → DB 백업 파일도 안전用于以下方面

 Django DB 백업 암호화 개인정보 암호화 시스템

8. CustomUser 모델과 Admin 검색/승인 기능

CustomUser 모델에서 EncryptedCharField를 사용하고, Admin에서 get_search_results 오버라이드하여 평문 검색이 가능하도록 구현했습니다.

Django Admin에서  개인정보 암호화 필드 표시 및 관리

결론: Django 개인정보 암호화로 개인정보보호법 완벽 준수

Django 개인정보 암호화 시스템을 프로젝트에 적용하면 DB 유출 사고에도 개인정보가 안전하게 보호됩니다. HMAC + Fernet + Custom Field + 암호화 백업 조합은 현재 Django에서 가장 실전적이고 강력한 방법입니다.

오늘 바로 Django 개인정보 암호화를 여러분 프로젝트에 도입해 보세요. 개인정보보호법, GDPR 준수까지 한 번에 해결할 수 있습니다!

출처 리스트

  • Django Official Documentation: Password management and hashing (PBKDF2-SHA256)
  • Medium: “How to Encrypt Sensitive Data with Python/Django” (Anil Kumar Valluru)
  • Django Forum: Encryption techniques in database using Fernet (2025)
  • GitHub: jazzband/django-fernet-encrypted-fields 공식 저장소 및 문서
  • Stack Overflow: Creating custom Django encrypted field with Fernet
  • Medium: “Encrypt Sensitive Data in Django REST APIs” (Fahim Ad)
  • Reintech: Working with File Encryption in Django
  • Django-fernet-fields Official Docs: Field-level encryption best practices

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注