DB/데이터 관리

개인 식별 정보 암호화 방법

dddzr 2026. 1. 25. 11:53

 

비밀번호를 암호화하는 것은 당연하지만 다른 개인 식별 정보에 대해서는 어떻게 보호해야할 지 깊이 생각해 본 적이 없는 것 같다!!

개인정보 유출 시 피싱/사칭 등 범죄에 이용될 가능성이 있기 때문에 보호가 필요하다.

주로 DB, 로그 등을 통해 외부로 유출 되거나 또는 내부자 위험도 있다.

암호화 해두면 유출되더라도 바로 식별 불가능하기 때문에 암호화가 필수다!!

 

📌 개인 식별 정보 보호 방법 정리

개인 식별 정보는 검색이나 화면에 일부 노출이 필요한 경우도 있다!!

그렇기 때문에 복호화가 가능한 암호화를 이용해야한다.

조회 성능을 위해 해시/마스킹/토큰화 방법을 같이 이용한다.

 

대상

  • 이메일
  • 휴대폰 번호
  • 주소
  • 사번 / 고객번호

💫 비밀번호는 예외 처리 (검색 대상 아님)

비밀번호는 조회·조건 검색이 필요하지 않으므로 단방향 해시만 저장(BCrypt 등), 복호화 가능한 방식 금지.


📌 1. 기본 개념 정리 🔍

✅ 1-1. 암호화가 필요한 이유

암호화를 안 하면 → 평문 데이터가 내부/외부 공격 둘 다에 취약
암호화를 하면 → 유출되더라도 “바로 식별 불가능한 상태”로 만드는 것

✅ 1-2.  왜 “전체 암호화”만 쓰면 안 되나?

  • AES로 전체 암호화 → ❌ WHERE email = ? 검색 불가
  • 복호화 후 비교 → ❌ 성능·보안 모두 나쁨

👉 그래서 보조 컬럼을 둔다.


📌 2. 가장 많이 쓰는 구조

✅ 구조 요약

email_enc        ← AES 암호화 (복호화 가능)

email_hash       ← 검색용 단방향 해시

email_mask       ← 화면 표시용

 


📌 3. 데이터 별 예시

3-1. 이메일

🔹 DB 컬럼 설계

EMAIL_ENC   VARCHAR(512)  -- AES 암호화

EMAIL_HASH  CHAR(64)      -- SHA-256

EMAIL_MASK  VARCHAR(100) -- 화면용

 

🔹 저장 시 로직

1️⃣ 사용자 입력

abc.def@gmail.com

 

2️⃣ 애플리케이션 처리

String email = inputEmail;

 

String emailEnc  = aesEncrypt(email);              // 복호화용

String emailHash = sha256(email.toLowerCase());    // 검색용

String emailMask = maskEmail(email);                // 화면 표시

 

3️⃣ DB 저장

EMAIL_ENC   = "Q9A8D..."

EMAIL_HASH  = "b4c9a289..."

EMAIL_MASK = "ab***@gmail.com"

 

🔹 검색 시

SELECT *

FROM USER_PRIVATE

WHERE EMAIL_HASH = :sha256(email)

 

✔ 복호화 불필요
✔ 인덱스 가능
✔ 성능 좋음

 

 3-2. 휴대폰 번호

🔹 정규화 후 처리 (형식 통일)

  • 010-1234-5678
  • 01012345678
  • +82-10-1234-5678

 

🔹 처리 흐름

String phone = normalizePhone(input); // 01012345678

 

phoneEnc  = aesEncrypt(phone);

phoneHash = sha256(phone);

phoneMask = "010-****-5678";

 

🔹 DB 설계

PHONE_ENC

PHONE_HASH

PHONE_MASK

 

 3-3.  주소 🏠

❓ 주소는 해시만으로 부족한 이유

  • 부분 검색 필요
  • 시/도, 구 단위 검색

🔹 실무 패턴

ADDR_ENC        ← 전체 주소 AES

ADDR_SIDO       ← 서울특별시

ADDR_SIGUNGU    ← 강남구

ADDR_DONG       ← 역삼동

 

✔ 행정단위는 평문
✔ 상세주소만 암호화

 

🔹 검색 예시

WHERE ADDR_SIDO = '서울특별시'

  AND ADDR_SIGUNGU = '강남구'

 

 3-4. 사번 / 고객번호 (외부 노출 기준) 

🔥 내부용 vs 외부용 분리

EMP_NO_INTERNAL   ← 평문 (PK)

EMP_NO_EXTERNAL   ← 토큰화

 

🔹 토큰화 예시

EMP-2024-000123  →  X9FQ-82KD-P0

 

✔ 외부 API
✔ URL 노출
✔ 로그 노출

👉 절대 내부 사번 그대로 쓰지 말 것


📌 4. 로그 & 백업 보호 규칙 ⚠️

❌ 개인 정보 전체 출력

log.info("email={}", email);

 

✔️ 올바른 로그 -> 마스킹

log.info("email={}", emailMask);

또는

log.info("emailHash={}", emailHash);

 


📌 5. 키 관리 핵심 🔐

❌ 금지

  • 소스코드에 AES 키 하드코딩
  • git에 키 업로드

✅ 권장

  • 환경변수
  • Vault / KMS
  • 키 로테이션

📌 6. 결론 🚀

“원본은 암호화, 검색은 해시, 화면은 마스킹, 외부는 토큰”

목적 방식
저장 AES 암호화
검색 SHA-256 해시
화면 표시 마스킹
외부 노출 토큰화
로그 마스킹 / 해시

'DB > 데이터 관리' 카테고리의 다른 글

Elasticsearch > analyzer  (0) 2026.01.25
CTE(Common Table Expression)란?  (0) 2025.11.29
Elasticsearch란?  (0) 2025.04.10
JDBC / SQL Mapper / ORM (JPA, Hibernate, MyBatis)  (0) 2024.09.25