[CS300 #292] 개인정보 보호와 법 — 개발자가 설계에서 지켜야 할 것
컴퓨터공학 300 주제 시리즈의 292번째 글이다. 전체 지도는 여기.
한 줄 요약
개인정보 보호법은 “개인을 알아볼 수 있는 정보”를 정당한 근거와 목적 안에서 최소한으로 처리하고, 안전하게 지키고, 정보주체의 권리를 보장하라고 요구한다. 이 요구의 상당수는 결국 테이블 설계, 로그 정책, 접근 제어 같은 코드로 구현된다.
왜 필요한가
개인정보 사고는 대개 거창한 해킹보다 평범한 설계 결정에서 시작된다.
- “혹시 몰라서” 주민등록번호와 생년월일을 다 받아 둔다.
- 디버깅하려고 요청 본문 전체를 로그에 남겼는데 비밀번호와 전화번호가 들어 있다.
- 탈퇴한 회원 데이터가 백업과 분석용 복제 DB 에 그대로 남는다.
- 운영 DB 를 그대로 복사해 개발 환경에서 쓴다.
법은 이것들을 “처리자의 의무 위반”으로 본다. 그리고 그 의무를 실제로 이행하는 사람은 시스템을 만드는 개발자다. 이 글은 법률 자문이 아니며, 구체적 판단은 조항 원문과 전문가 검토로 확인해야 한다.
핵심 개념
개인정보의 범위
한국 「개인정보 보호법」 제2조는 개인정보를 살아 있는 개인에 관한 정보로서 다음 중 하나에 해당하는 것으로 정의한다.
- 성명, 주민등록번호, 영상 등으로 개인을 알아볼 수 있는 정보
- 그 자체로는 알아볼 수 없더라도 다른 정보와 쉽게 결합해 알아볼 수 있는 정보
- 가명처리해 추가 정보 없이는 특정 개인을 알아볼 수 없는 정보(가명정보)
2번이 개발자에게 중요하다. 회원 ID, 기기 식별자, IP 주소, 쿠키 ID 는 그 자체로 이름이 없어도 다른 테이블과 조인하면 사람이 특정된다. EU 일반개인정보보호규정(GDPR) 제4조도 온라인 식별자와 위치 데이터를 개인정보의 예로 명시한다.
처리 원칙
GDPR 제5조의 원칙은 각국 법에 공통적으로 나타나는 뼈대다.
| 원칙 | 뜻 | 개발에서의 모습 |
|---|---|---|
| 적법성·공정성·투명성 | 근거가 있고, 알리고 처리한다 | 처리방침, 수집 시점 고지 |
| 목적 제한 | 정한 목적으로만 쓴다 | 마케팅 동의 없는 데이터를 마케팅에 쓰지 않음 |
| 최소화 | 필요한 만큼만 | 필요 없는 필드를 스키마에서 뺌 |
| 정확성 | 정확하게 유지 | 수정 기능 제공 |
| 보관 기간 제한 | 필요 기간이 끝나면 파기 | TTL, 파기 배치, 백업 보존 주기 |
| 무결성·기밀성 | 안전하게 보호 | 암호화, 접근 통제, 접근 기록 |
| 책임성 | 지키고 있음을 증명 | 처리 기록, 감사 로그 |
처리의 법적 근거
동의만이 유일한 근거가 아니다. GDPR 제6조는 동의, 계약 이행, 법적 의무, 생명 등 중대한 이익, 공익 업무, 정당한 이익의 여섯 가지를 둔다. 한국 개인정보 보호법 제15조도 동의 외에 법률의 특별한 규정, 계약 체결·이행 등 여러 근거를 둔다. 어떤 데이터를 어떤 근거로 처리하는지 데이터 항목별로 정리해 두면, 근거가 사라졌을 때(예: 동의 철회) 무엇을 멈춰야 하는지 알 수 있다.
가명처리와 익명처리
| 구분 | 되돌릴 수 있나 | 법적 지위 |
|---|---|---|
| 가명처리 | 추가 정보(키·매핑표)가 있으면 가능 | 여전히 개인정보 |
| 익명처리 | 합리적으로 불가능 | 개인정보가 아님 |
GDPR 전문(Recital) 26 은 가명처리된 데이터도 개인정보이고, 익명 정보에는 규정이 적용되지 않는다고 설명한다. 한국 법은 가명정보를 통계 작성, 과학적 연구, 공익적 기록 보존 목적으로 일정 조건 아래 동의 없이 처리할 수 있게 하는 특례(제28조의2 등)를 둔다. 대신 추가 정보를 분리 보관하고 재식별을 금지한다.
이름을 지웠다고 익명이 되지 않는다. 나이대, 지역, 성별 같은 준식별자(quasi-identifier)의 조합이 한 사람만 가리키면 재식별된다.
정보주체의 권리
열람, 정정·삭제, 처리 정지, 동의 철회 같은 권리를 보장해야 한다. GDPR 은 삭제권(제17조)과 이동권(제20조)도 명시한다. 시스템 관점의 질문은 이것이다. “한 사람의 데이터를 모든 저장소에서 찾아 지울 수 있는가?” 운영 DB, 검색 색인, 캐시, 로그, 분석 웨어하우스, 백업을 모두 포함한다.
설계 단계부터: Privacy by Design
GDPR 제25조는 설계 및 기본설정에 의한 데이터 보호를 요구한다. 기본값이 가장 보호적인 설정이어야 한다는 뜻이다. 공개 범위 기본값은 “비공개”, 위치 수집 기본값은 “꺼짐”이다.
사고 대응과 제재
GDPR 제33조는 개인정보 침해를 인지한 뒤 원칙적으로 72시간 안에 감독기관에 신고하도록 한다. 제83조는 위반 유형에 따라 최대 2천만 유로 또는 전 세계 연간 매출의 4% 중 큰 금액까지 과징금을 정한다. 한국 법도 유출 시 통지·신고 의무와 과징금 규정을 두며, 개인정보보호위원회가 감독한다. 국내 세부 기한과 기준은 법령 원문과 시행령으로 확인한다.
GDPR 은 EU 밖의 사업자라도 EU 안의 사람에게 재화·서비스를 제공하면 적용될 수 있다(제3조). 해외 사용자가 있는 서비스는 확인이 필요하다.
직접 해 보기
가명처리의 흔한 실수 두 가지를 확인한다. 하나는 “해시만 하면 된다”는 착각, 다른 하나는 “이름만 빼면 익명”이라는 착각이다.
import hashlib, hmac, secrets, time
from collections import Counter
phone = "01012345678"
# 1) 단순 해시: 입력 공간이 작으면 전수 대입으로 되돌린다
h = hashlib.sha256(phone.encode()).hexdigest()
start = time.time()
found = None
for n in range(12340000, 12350000): # 실제 공격자는 0000-0000 ~ 9999-9999 전체를 돈다
cand = f"010{n:08d}"
if hashlib.sha256(cand.encode()).hexdigest() == h:
found = cand
break
print("단순 SHA-256 역추적:", found, f"({time.time() - start:.3f}s)")
# 2) 비밀 키를 쓰는 HMAC: 키가 없으면 대입 공격을 할 수 없다. 키는 데이터와 분리 보관
key = secrets.token_bytes(32)
pseudo = hmac.new(key, phone.encode(), hashlib.sha256).hexdigest()[:16]
print("HMAC 가명:", pseudo)
# 3) k-익명성 점검: 준식별자 조합이 같은 사람이 최소 k 명인가
rows = [
("30대", "서울", "남"), ("30대", "서울", "남"), ("30대", "서울", "여"),
("40대", "부산", "남"), ("40대", "부산", "남"), ("40대", "부산", "남"),
("20대", "제주", "여"),
]
groups = Counter(rows)
k = min(groups.values())
print("k =", k, "/ 유일하게 식별되는 조합:", [g for g, c in groups.items() if c == 1])
실행 결과의 예다. HMAC 값은 키가 매번 새로 만들어지므로 실행마다 다르고, 시간은 기계마다 다르다.
단순 SHA-256 역추적: 01012345678 (0.018s)
HMAC 가명: 79cabd20d2ae48b0
k = 1 / 유일하게 식별되는 조합: [('30대', '서울', '여'), ('20대', '제주', '여')]
1만 개를 0.02초 안에 대입했다. 휴대폰 번호 뒷자리 8자리 전체는 1억 개라 이 속도로도 수 분이면 끝난다. 전화번호·생년월일처럼 경우의 수가 작은 값의 단순 해시는 사실상 가명처리가 아니다. 비밀 키를 쓰는 HMAC 이나 별도 매핑표를 쓰고, 키는 데이터와 다른 곳(KMS 등)에 둔다.
k-익명성 점검에서 k=1 이다. “20대·제주·여”는 한 명뿐이라 다른 정보와 결합하면 바로 특정된다. 범주를 넓히거나(20~30대), 해당 행을 억제하거나, 통계로만 공개해야 한다. k-익명성만으로 충분하지 않은 공격(동질성 공격 등)도 있어 차분 프라이버시 같은 기법이 연구·적용되고 있다.
현업에서는
- 로그 마스킹은 라이브러리 수준에서 강제한다. 요청 본문 전체 로깅을 금지하고, 이메일·전화번호·토큰 필드는 직렬화 단계에서 가린다. 로그는 생각보다 많은 사람이 보고, 오래 남고, 여러 시스템으로 복제된다.
- 개발·스테이징 환경에는 운영 데이터를 그대로 복사하지 않는다. 합성 데이터나 가명처리된 데이터를 쓴다. 홈랩 클러스터에서 실험할 때도 실제 지인의 연락처 같은 데이터는 넣지 않는다.
- 스키마 리뷰 체크리스트에 “이 컬럼은 개인정보인가, 근거는 무엇인가, 보존 기간은 얼마인가, 삭제 요청 시 어떻게 지우는가”를 넣는다.
- 개인정보 처리 시스템의 접근 기록(누가 언제 무엇을 조회했나)을 남기고 주기적으로 점검한다. 내부자 조회가 사고의 큰 부분을 차지한다.
- 외부 SaaS(분석, 고객지원, 이메일 발송)에 데이터를 넘기면 위탁이나 제3자 제공, 국외 이전 문제가 된다. 계약과 처리방침에 반영해야 한다.
확인 문제
- 이름 없이 회원 ID 와 접속 IP 만 있는 로그는 개인정보가 아닌가?
- 가명정보와 익명정보의 차이를 법적 지위와 함께 설명하라.
- 전화번호를 SHA-256 으로만 해시해 저장하는 것이 가명처리로 부족한 이유는?
- “삭제 요청을 처리했다”고 말하려면 어떤 저장소들을 확인해야 하는가?
풀이
- 다른 정보(회원 테이블 등)와 쉽게 결합해 개인을 알아볼 수 있으면 개인정보다.
- 가명정보는 추가 정보가 있으면 재식별 가능하며 여전히 개인정보로 법의 적용을 받는다. 익명정보는 합리적으로 재식별할 수 없어 개인정보 보호 규정의 적용 대상이 아니다.
- 입력 공간이 작아 전수 대입으로 원래 값을 쉽게 찾을 수 있다. 비밀 키 기반 HMAC 이나 분리 보관한 매핑표가 필요하다.
- 운영 DB, 복제본, 캐시, 검색 색인, 로그, 분석 웨어하우스, 외부 위탁 시스템, 백업(보존 주기에 따른 파기 정책)까지다.
더 읽을거리 (References)
- 국가법령정보센터, 개인정보 보호법
- European Commission, Legal framework of EU data protection — GDPR(Regulation (EU) 2016/679) 안내와 원문 링크
- 개인정보보호위원회, pipc.go.kr
- NIST, De-Identification of Personal Information (NISTIR 8053)