로그 마스킹은 운영 로그·예외 트레이스·3rd party 로그에 기록되는 개인정보(주민번호·카드번호·전화번호·이메일·API 키)를 자동으로 가명화·치환하는 필터링 절차다.
한국 개인정보보호법 제29조와 PCI DSS 3.4는 로그에 평문 PII 저장을 금지하지만, AI 코딩 도구가 만든 SaaS에서 마스킹 누락이 가장 자주 발견된다.
이 글은 표준 Django 로깅 필터 코드, 5가지 실수 패턴, 30초 자가진단 절차를 정리했다.
한눈에 보는 로그 마스킹
Q. 로그에 카드번호·주민번호가 그대로 찍히면 어떻게 되나요? A. 한국 개인정보보호법 과징금 최대 매출 3%, PCI DSS 부적합으로 카드사 계약 해지 위험이 있습니다. 로그 백업·3rd party SaaS 로그(Sentry, DataDog)에도 평문 노출됩니다. Q. exception trace에 평문이 새는 이유는? A. Django는 기본적으로 view 함수 인자를 traceback에 포함합니다. 결제 처리 함수에 카드번호 인자가 있으면 예외 발생 시 stack frame에 그대로 노출됩니다. Q. 3rd party 로깅 SaaS도 마스킹해야 하나요? A. 필수입니다. Sentry·DataDog·CloudWatch에 평문 PII가 전송되면 데이터 처리자 위탁 계약 + 개인정보 국외 이전 동의가 필요합니다. 전송 전 필터링이 표준입니다. Q. AI 코딩 도구는 왜 마스킹을 빠뜨리나요? A. LLM 학습 데이터의 평균 예제 코드는 logger.info(f"카드: {card_number}") 같은 디버깅 코드입니다. 운영용 필터링은 별도 미들웨어가 필요한데 AI는 이를 생략합니다.5가지 자주 발생하는 실수 패턴
| # | 패턴 | 위험도 |
|---|---|---|
| 1 | print()·logger.info()로 객체 전체 덤프 (request.POST, payment_data) | 치명 |
| 2 | exception traceback에 함수 인자(카드번호, 비번) 포함 | 치명 |
| 3 | 3rd party SDK(Sentry)에 BeforeSend 필터 미설정 | 치명 |
| 4 | 웹서버 access log에 URL 쿼리(token, password) 포함 | 높음 |
| 5 | DB 쿼리 로그(DEBUG=True 잔존)에 평문 카드번호 | 높음 |
Django 표준 로깅 필터
import re
import logging
PATTERNS = [
(re.compile(r'\b\d{6}-?\d{7}\b'), '[주민번호]'), # 901231-1234567
(re.compile(r'\b\d{4}-?\d{4}-?\d{4}-?\d{4}\b'), '[카드번호]'), # 1234-5678-...
(re.compile(r'\b01[0-9]-?\d{3,4}-?\d{4}\b'), '[전화번호]'),
(re.compile(r'\b[\w._%+-]+@[\w.-]+\.[A-Z]{2,}\b', re.I), '[이메일]'),
(re.compile(r'(sk|pk|api[_-]?key)[_-]?[a-z0-9]{20,}', re.I), '[API키]'),
]
class PIIMaskingFilter(logging.Filter):
def filter(self, record):
msg = str(record.getMessage())
for pattern, replacement in PATTERNS:
msg = pattern.sub(replacement, msg)
record.msg = msg
record.args = () # 포맷 args 제거 — 재치환 방지
return True
# settings.py
LOGGING = {
'version': 1,
'filters': {'pii_mask': {'()': 'config.filters.PIIMaskingFilter'}},
'handlers': {
'console': {'class': 'logging.StreamHandler', 'filters': ['pii_mask']},
'file': {'class': 'logging.FileHandler', 'filename': 'logs/app.log', 'filters': ['pii_mask']},
},
'root': {'handlers': ['console', 'file'], 'level': 'INFO'},
}
핵심 3요소: (1) 정규식 5종 이상 (2) 모든 handler에 필터 부착 (3) record.args 제거.
3rd party는 Sentry before_send, DataDog scrubber로 별도 처리.
DEBUG=True 운영 금지는 기본이다.
30초 자가진단
# 1. 로그 파일 PII 검색
grep -rE "[0-9]{6}-?[0-9]{7}|[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{4}" logs/ | head -5
# 2. Sentry/DataDog 대시보드 — 최근 1시간 이벤트 평문 PII 검색
# 3. DEBUG=True 운영 노출 확인
curl https://yourdomain.com/notfound | grep -i "traceback\|debug"
하나라도 매칭되면 마스킹 결함이다. OWASP A09: 로깅·모니터링 실패 범주에 해당한다.
24시간 패치 절차
| 순위 | 조치 |
|---|---|
| 1 | PIIMaskingFilter 작성 + 모든 handler 적용 |
| 2 | Sentry before_send / DataDog scrubber 추가 |
| 3 | 기존 로그 파일 정리 (rotate + 평문 PII 삭제) |
| 4 | DEBUG=False 운영 강제 + 시크릿 .env 분리 |
| 5 | 웹서버(nginx/waitress) access log 쿼리 제외 설정 |
지금 해야 할 것
실무자: CodeScan 무료 스캔으로 노출 파일·DEBUG 점검.
CISO·임원: 로그 + 백업 + 3rd party 전체 PII 흐름 점검은 SENTRIX 30분 1:1 상담.
개인정보 유출 사고 발생 시 24시간 내 신고 의무가 있다.