Files
jongryangje/docs/기본 개발계획/19-db-personal-data-encryption.md
2026-04-08 00:23:55 +09:00

5.8 KiB

DB 개인정보 보안·암호화 방안 (개발자도 알 수 없게)

“DB 보안을 중요시하고, 개발자도 사용자 개인정보를 알 수 없게 꼼꼼히 암호화한다”는 요구에 맞춘 설계·구현 방향입니다.


1. 목표

  • DB에 저장되는 개인정보암호화해, DB만 접근하는 사람(개발자, DBA, 백업 유출 시)이 평문을 볼 수 없게 한다.
  • 암호화 키는 DB나 소스코드 저장소에 두지 않고, 환경 변수·시크릿 관리에만 둔다.
  • 비밀번호는 해시만 저장(복호화 불가). 이름·휴대전화·이메일 등 복구가 필요한 값대칭키 암호화로 저장한다.

2. 무엇을 어떻게 다룰지

데이터 종류 처리 방식 이유
비밀번호 해시만 (password_hash / bcrypt·argon2) 복호화 불필요. 로그인 시 password_verify만 하면 됨. DB 유출돼도 평문 복원 불가.
이름, 휴대전화, 이메일 저장 전 암호화, 조회 시 애플리케이션에서만 복호화 DB에는 암호문만 저장. 키가 없으면 개발자도 평문을 알 수 없음.
로그·감사 이력 개인정보 필드는 암호화 저장 또는 마스킹만 저장 로그에 평문 개인정보가 쌓이지 않게 함.

3. 필드 단위 암호화 (이름·전화·이메일)

3.1 방식

  • 대칭키 암호화(예: AES-256-GCM 또는 AES-256-CBC + HMAC) 사용.
  • 는 PHP openssl 등으로 생성해, 애플리케이션만 사용. DB에는 키를 저장하지 않음.
  • IV(초기화 벡터) 는 암호화할 때마다 랜덤 생성하고, 암호문과 함께 저장 (IV는 공개돼도 됨, 키만 비밀).

3.2 키 보관 (개발자도 알 수 없게)

  • 로컬/개발: .envENCRYPTION_KEY=... 형태로 둠. .env는 Git에 넣지 않고, .env.example에는 키 없이 변수명만 예시로 둠.
  • 운영: 서버 환경 변수 또는 시크릿 관리(AWS Secrets Manager, HashiCorp Vault, 네이버 클라우드 시크릿 등)에 넣고, 앱 기동 시에만 읽어 씀.
  • 규칙: 키가 소스코드·DB·백업 파일에 들어가지 않도록 한다. 개발자에게 DB만 주면 암호문만 보이고, 키 없이는 복호화 불가.

3.3 적용 위치 (CI4 예시)

  • 옵션 A: 암호화 헬퍼/라이브러리를 두고, Model에서 member 등 저장·조회 시:
    • INSERT/UPDATE 전: mb_name, mb_phone, mb_email 등을 암호화해 DB에 넣음.
    • SELECT 후: 화면·비즈니스 로직에 넘기기 직전에만 복호화. 로그에는 복호화된 값이나 평문을 남기지 않음.
  • 옵션 B: Entity에서 mb_name 등 접근 시 자동 암·복호화(Getter/Setter에서 처리). Model은 Entity를 쓰므로, 저장·조회 시 일관되게 암호화된 값만 DB에 쌓이게 함.

이렇게 하면 DB 덤프를 열어도 이름·전화·이메일은 암호문으로만 보이고, 키를 모르는 개발자는 평문을 알 수 없다.

3.4 키 로테이션(선택)

  • 주기적으로 새 키로 다시 암호화하는 정책. 구현 시 키 버전을 필드에 두고, 복호화 시 버전별 키로 풀 수 있게 하면 된다. 초기에는 단일 키로 시작해도 됨.

4. 비밀번호는 암호화가 아니라 해시

  • 저장: password_hash($password, PASSWORD_DEFAULT) (bcrypt 등)로 해시만 저장.
  • 검증: password_verify($input, $storedHash).
  • 복호화하지 않음. 따라서 “개발자가 DB만 보고 비밀번호를 알 수 없다”는 건 해시를 쓰는 것만으로 만족됨. 이미 11번 문서 등에서 password_verify 전제로 되어 있음.

5. 비식별화(마스킹)와의 관계

  • PWB-010201-001 “이름·휴대전화 가림”은 화면·로그에 보여줄 때 마스킹(홍동, 010-***-5678)하는 비식별화이다.
  • DB 보안을 위해선 그에 더해 위처럼 저장 단계에서 암호화를 하는 것이 좋다.
    • 저장: 암호화 → DB에는 암호문만.
    • 표시: 필요한 경우에만 복호화 후, 권한에 따라 마스킹해서 보여줌 (관리자만 전체 보기 등 정책에 따라).

6. 접근 제어·운영

  • DB 계정: 애플리케이션 전용 계정만 최소 권한(SELECT/INSERT/UPDATE/DELETE 등 필요한 것만) 부여. 개발·운영 DB는 역할별로 분리하고, 개인정보가 있는 테이블에 대한 직접 조회를 제한할 수 있으면 좋음.
  • 백업: 백업 파일도 암호문만 포함하므로, 키가 유출되지 않는 한 개인정보 평문이 노출되지 않음. 백업 파일 자체도 암호화 저장 권장.
  • 감사 로그: 개인정보 조회/복호화 이벤트를 로그에 남기면, 나중에 “누가 언제 복호화했는지” 추적 가능. (구현 여부는 정책에 따라.)

7. 구현 시 체크리스트

  • 개인정보 필드(mb_name, mb_phone, mb_email 등) 저장 전 AES-256 등으로 암호화.
  • 암호화 키.env 또는 시크릿 관리에만 두고, Git/DB에 포함하지 않음.
  • 비밀번호는 해시만 저장, 복호화 로직 없음.
  • 복호화는 애플리케이션에서만, 필요한 권한이 있을 때만 수행. 로그에는 평문·복호화 결과를 남기지 않음.
  • 화면·로그에는 필요 시 마스킹(비식별화) 적용.
  • (선택) 키 로테이션·감사 로그 설계.

이렇게 하면 “개발자도 사용자 개인정보를 알 수 없게” DB 보안을 꼼꼼히 맞추는 방향이 됩니다. 구현은 Phase 1 후반 또는 Phase 2에서 암호화 라이브러리/헬퍼 도입member 등 개인정보 테이블 적용부터 진행하면 됩니다.