실제 사고에서 배우는 PII 보호의 중요성

개발자가 AI API에 사용자 데이터를 전송할 때 가장 흔하게 겪는 보안 사고를 살펴보겠습니다. 다음은 실제发生过하는 시나리오입니다:

실제 발생 가능한 위험 상황

user_input = """ 고객 이름: 김민수 주민등록번호: 950123-1234567 신용카드: 4532-1234-5678-9012 전화번호: 010-1234-5678 주소: 서울특별시 강남구 테헤란로 123 """

이 데이터를 그대로 AI API에 전송하면 발생하는 문제:

1. AI가 학습 데이터로 활용할 수 있음 (데이터 유출)

2. 로그 파일에 평문으로 저장됨

3. 제3자에게 노출될 수 있는 위험

ValueError: Sensitive data detected in request payload와 같은 오류 없이 민감 정보가 그대로 전달되는 상황은 심각한 개인정보 보호법 위반입니다. 특히 금융, 의료, 보험 도메인에서는 GDPR, PCI-DSS, 개인정보보호법 준수가 법적으로 의무화되어 있습니다.

PII란 무엇인가?

PII(Personal Identifiable Information)는 특정 개인를 식별할 수 있는 모든 정보를 의미합니다. 법적 관할권에 따라 분류가 다를 수 있으나, 일반적으로 다음カテゴリ를 포함합니다:

직접 식별자 (Direct Identifiers)


DIRECT_IDENTIFIERS = {
    # 한국 고유 identifiers
    "resident_registration": r"\d{6}-[1-4]\d{6}",  # 주민등록번호
    "passport_kr": r"[A-Z]{1,2}\d{8,9}",           # 여권번호
    "driver_license_kr": r"\d{2}-\d{6}",           # 운전면허번호
    
    # 글로벌 identifiers  
    "ssn_us": r"\d{3}-\d{2}-\d{4}",               # 미국 사회보장번호
    "nino_uk": r"[A-Z]{2}\d{6}[A-D]",             # 영국 NI 번호
    
    # 금융 identifiers
    "credit_card": r"\d{4}-\d{4}-\d{4}-\d{4}",    # 신용카드
    "bank_account_kr": r"\d{3}-?\d{3}-?\d{6}",   # 계좌번호
    
    # 연락처
    "phone_kr": r"01[0-9]-\d{3,4}-\d{4}",         # 휴대전화
    "email": r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"  # 이메일
}

준 식별자 (Quasi-Identifiers)

나이에 따라 통계적으로 특정 개인를 추론할 수 있는 정보들도 탈감 대상입니다:

PII 감지 아키텍처 설계


┌─────────────────────────────────────────────────────────────────┐
│                    PII Protection Pipeline                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  [User Input] ──▶ [Preprocessor] ──▶ [PII Detector]              │
│                          │                │                     │
│                          ▼                ▼                     │
│                   [Normalization]   [Classification]            │
│                          │                │                     │
│                          │         ┌──────┴──────┐              │
│                          │         ▼              ▼              │
│                          │    [Direct ID]    [Quasi-ID]          │
│                          │         │              │              │
│                          ▼         ▼              ▼              │
│                   [Masking Engine] ◀──▶ [Replacement Rules]      │
│                          │                                      │
│                          ▼                                      │
│                   [Sanitized Output] ──▶ [AI API Request]       │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

실전 PII 감지 및 탈감 구현

1단계: 기본 정규식 기반 감지


import re
from typing import Dict, List, Tuple
from dataclasses import dataclass
from enum import Enum

class PIIType(Enum):
    RESIDENT_REGISTRATION = "resident_registration"
    CREDIT_CARD = "credit_card"
    PHONE = "phone"
    EMAIL = "email"
    NAME = "name"
    ADDRESS = "address"
    BANK_ACCOUNT = "bank_account"

@dataclass
class PIIMatch:
    pii_type: PIIType
    original_value: str
    start_index: int
    end_index: int
    confidence: float

class PIIDetector:
    """한국어 PII 감지 및 탈감을 위한 기본 클래스"""
    
    # 한국 기반 PII 패턴 정의
    PATTERNS: Dict[PIIType, Tuple[str, float]] = {
        PIIType.RESIDENT_REGISTRATION: (
            r"\d{6}-[1-4]\d{6}",
            0.95
        ),
        PIIType.CREDIT_CARD: (
            r"\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}",
            0.98
        ),
        PIIType.PHONE: (
            r"01[016789][-\s]?\d{3,4}[-\s]?\d{4}",
            0.92
        ),
        PIIType.EMAIL: (
            r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}",
            0.95
        ),
        PIIType.BANK_ACCOUNT: (
            r"\d{3}-?\d{3}-?\d{6}",
            0.88
        ),
    }
    
    # 이름 데이터베이스 (범용 한국 성씨 + 이름)
    COMMON_KOREAN_SURNAMES = {
        "김", "이", "박", "최", "정", "강", "조", "윤", "장", "임",
        "한", "오", "서", "신", "권", "황", "안", "송", "류", "전"
    }
    
    def detect(self, text: str) -> List[PIIMatch]:
        """텍스트에서 PII 검색"""
        matches = []
        
        for pii_type, (pattern, confidence) in self.PATTERNS.items():
            for match in re.finditer(pattern, text):
                matches.append(PIIMatch(
                    pii_type=pii_type,
                    original_value=match.group(),
                    start_index=match.start(),
                    end_index=match.end(),
                    confidence=confidence
                ))
        
        # Confidence 기준 정렬
        matches.sort(key=lambda x: x.confidence, reverse=True)
        return matches
    
    def mask(self, text: str, matches: List[PIIMatch]) -> str:
        """감지된 PII 마스킹"""
        result = text
        offset = 0
        
        for match in matches:
            mask_char = self._get_mask_char(match.pii_type)
            masked = mask_char * len(match.original_value)
            
            start = match.start_index + offset
            end = match.end_index + offset
            result = result[:start] + masked + result[end:]
            offset += len(masked) - len(match.original_value)
        
        return result
    
    def _get_mask_char(self, pii_type: PIIType) -> str:
        """PII 유형별 마스킹 문자 반환"""
        mask_map = {
            PIIType.RESIDENT_REGISTRATION: "*",
            PIIType.CREDIT_CARD: "#",
            PIIType.PHONE: "*",
            PIIType.EMAIL: "*",
            PIIType.BANK_ACCOUNT: "#",
        }
        return mask_map.get(pii_type, "*")

사용 예시

detector = PIIDetector() test_text = """ 고객 정보如下: 이름: 김민수 주민등록번호: 950123-1234567 연락처: 010-1234-5678 이메일: [email protected] 카드정보: 4532-1234-5678-9012 """ matches = detector.detect(test_text) print("감지된 PII:") for m in matches: print(f" [{m.pii_type.value}] {m.original_value} (신뢰도: {m.confidence})") sanitized = detector.mask(test_text, matches) print("\n탈감 후 텍스트:") print(sanitized)

2단계: HolySheep AI API와 통합

실무에서는 정규식만으로는 한계가 있습니다. HolySheep AI의 Claude 기반 PII 감지 기능을 활용하면 더 정확한 분석이 가능합니다:

import os
import json
import httpx
from typing import Optional, Dict, List

HolySheep AI API 설정

https://api.holysheep.ai/v1 (base_url)

가입: https://www.holysheep.ai/register

class HolySheepPIIAnalyzer: """HolySheep AI 기반 고급 PII 감지 및 탈감""" def __init__(self, api_key: str): self.api_key = api_key self.base_url = "https://api.holysheep.ai/v1" async def analyze_with_ai( self, text: str, detection_level: str = "strict" ) -> Dict: """ HolySheep AI를 활용한 PII 분석 Args: text: 분석할 텍스트 detection_level: 'strict', 'balanced', 'permissive' """ prompt = f"""다음 텍스트에서 모든 PII(개인정보)를 식별하고 탈감하세요. 검색해야 할 정보 유형: 1. 이름 (한국어, 영어) 2. 주민등록번호 (한국) 3. 여권번호, 운전면허번호 4. 신용카드번호, 계좌번호 5. 전화번호 (휴대전화, 일반전화) 6. 이메일 주소 7. physical 주소 8. 생년월일 9. 의료 정보, 진단명 10. 금융 정보 {detection_level} 모드로 분석: - strict: 모든 가능한 PII 포함 - balanced: 명확한 PII만 - permissive: 높은 신뢰도만 응답 형식 (JSON): {{ "detected_pii": [ {{ "type": "주민등록번호", "value": "950123-1234567", "start": 10, "end": 21, "confidence": 0.98 }} ], "sanitized_text": "마스킹된 텍스트", "risk_score": 0.85, "recommendations": ["추가 보안 조치"] }} 텍스트: {text}""" async with httpx.AsyncClient(timeout=30.0) as client: response = await client.post( f"{self.base_url}/chat/completions", headers={ "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json" }, json={ "model": "claude-sonnet-4-20250514", "messages": [ {"role": "system", "content": "당신은 PII 감지 전문가입니다. 정확한 JSON 응답만 반환하세요."}, {"role": "user", "content": prompt} ], "temperature": 0.1, "max_tokens": 2000 } ) if response.status_code == 401: raise PermissionError( "HolySheep API 키가 유효하지 않습니다. " "https://www.holysheep.ai/register 에서 새 키를 발급하세요." ) response.raise_for_status() result = response.json() # AI 응답 파싱 ai_content = result["choices"][0]["message"]["content"] # JSON 추출 (마크다운 코드 블록 제거) if "```json" in ai_content: ai_content = ai_content.split("``json")[1].split("``")[0] elif "```" in ai_content: ai_content = ai_content.split("``")[1].split("``")[0] return json.loads(ai_content.strip()) async def batch_analyze( self, texts: List[str], detection_level: str = "strict" ) -> List[Dict]: """배치 처리로 여러 텍스트 동시 분석""" import asyncio tasks = [ self.analyze_with_ai(text, detection_level) for text in texts ] return await asyncio.gather(*tasks)

사용 예시

async def main(): # HolySheep AI 키 설정 api_key = os.environ.get("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY") analyzer = HolySheepPIIAnalyzer(api_key) # 분석할 텍스트 user_data = """ === 고객 정보 === 성명: 김영희 주민등록번호: 870105-2345678 연락처: 010-9876-5432 이메일: [email protected] 주소: 부산광역시 해운대구 우동 1234번지 === 결제 정보 === 카드번호: 5123-4567-8901-2345 유효기간: 12/28 """ try: result = await analyzer.analyze_with_ai(user_data, "strict") print("=== PII 감지 결과 ===") print(f"위험 점수: {result['risk_score']}") print(f"\n감지된 PII 수: {len(result['detected_pii'])}") for pii in result['detected_pii']: print(f" - {pii['type']}: {pii['value']} " f"(신뢰도: {pii['confidence']:.0%})") print(f"\n=== 탈감 후 텍스트 ===") print(result['sanitized_text']) print(f"\n=== 권장 조치 ===") for rec in result['recommendations']: print(f" • {rec}") except PermissionError as e: print(f"인증 오류: {e}") except httpx.TimeoutException: print("HolySheep API 응답 시간 초과. 다시 시도하세요.") except Exception as e: print(f"예상치 못한 오류: {e}") if __name__ == "__main__": import asyncio asyncio.run(main())

웹 서비스에 통합하기

Flask 기반 웹 서비스에서 PII 보호 미들웨어를 구현하는 실전 예제입니다:

from flask import Flask, request, jsonify
from functools import wraps
import logging

app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

PII 감지 인스턴스 (정규식 기반)

pii_detector = PIIDetector()

HolySheep AI 분석기 (고급)

class PIIProtectionMiddleware: """Flask 요청/응답 PII 보호 미들웨어""" def __init__(self, app, holy_sheep_key: Optional[str] = None): self.app = app self.holy_sheep_analyzer = None if holy_sheep_key: self.holy_sheep_analyzer = HolySheepPIIAnalyzer(holy_sheep_key) self._install_middleware() def _install_middleware(self): """before_request/after_request 훅 등록""" @self.app.before_request def preprocess_request(): # 요청 데이터에서 PII 감지 if request.is_json: data = request.get_json() if data: request.pii_analysis = self._analyze_data(data) @self.app.after_request def postprocess_response(response): # 응답 로깅 시 PII 마스킹 if hasattr(request, 'pii_analysis'): risk_level = request.pii_analysis.get('risk_score', 0) # 위험도가 높으면 경고 로깅 if risk_level > 0.7: logger.warning( f"High PII risk detected in request. " f"Risk score: {risk_level}", extra={"sanitized": True} ) return response def _analyze_data(self, data): """요청 데이터 분석""" text_content = self._flatten_to_text(data) if self.holy_sheep_analyzer: # HolySheep AI 활용 (실시간은 비용이 발생하므로 주석) # return await self.holy_sheep_analyzer.analyze_with_ai(text_content) pass # 기본 정규식 분석 matches = pii_detector.detect(text_content) return { "pii_count": len(matches), "pii_types": [m.pii_type.value for m in matches], "sanitized": pii_detector.mask(text_content, matches) } def _flatten_to_text(self, obj) -> str: """중첩 객체를 문자열로 변환""" if isinstance(obj, dict): return " ".join(self._flatten_to_text(v) for v in obj.values()) elif isinstance(obj, list): return " ".join(self._flatten_to_text(v) for v in obj) elif isinstance(obj, str): return obj return str(obj)

미들웨어 초기화

HolySheep 가입: https://www.holysheep.ai/register

PIIProtectionMiddleware(app, holy_sheep_key=os.environ.get("HOLYSHEEP_API_KEY")) @app.route("/api/user/support-ticket", methods=["POST"]) def create_support_ticket(): """ 고객 지원 티켓 생성 API - 입력 데이터 자동 PII 감지 - AI 처리 전 민감 정보 보호 """ data = request.get_json() # 티켓 내용에 PII 분석 결과 첨부 analysis = getattr(request, 'pii_analysis', {}) if analysis.get('pii_count', 0) > 0: logger.info( f"Support ticket contains {analysis['pii_count']} PII items. " f"Types: {analysis['pii_types']}" ) # PII가 포함된 티켓은 별도 보안 처리 return jsonify({ "ticket_id": generate_ticket_id(), "status": "requires_review", "pii_notice": "민감 정보가 감지되었습니다. 수동 검토 후 처리됩니다.", "analysis": analysis }), 202 # PII 없음 - 즉시 처리 return jsonify({ "ticket_id": generate_ticket_id(), "status": "created" }), 201 @app.route("/api/ai/process", methods=["POST"]) def ai_process(): """ AI 처리 전용 엔드포인트 - HolySheep AI Gateway를 통한 안전한 데이터 전송 """ data = request.get_json() user_message = data.get("message", "") # PII 감지 matches = pii_detector.detect(user_message) if matches: # 원본 메시지를 HolySheep API에 보내지 않고 탈감 처리 sanitized_message = pii_detector.mask(user_message, matches) # HolySheep AI Gateway로 전송 # base_url: https://api.holysheep.ai/v1 # model: claude-sonnet-4-20250514 return jsonify({ "ai_response": "고객님의 요청을 확인했습니다. " f"요청에서 {len(matches)}개의 민감 정보가 자동으로 " "보호处理되었습니다.", "processing_note": "PII protection enabled", "pii_masked": True }) # PII 없음 - 정상 처리 return jsonify({ "ai_response": "요청을 처리합니다.", "pii_masked": False }) def generate_ticket_id() -> str: import uuid return f"TKT-{uuid.uuid4().hex[:8].upper()}" if __name__ == "__main__": app.run(debug=True, port=5000)

자주 발생하는 오류와 해결책

1. HolySheep API 401 Unauthorized 오류


❌ 잘못된 접근

api.openai.com 또는 api.anthropic.com 직접 호출 시

response = requests.post( "https://api.anthropic.com/v1/messages", headers={"x-api-key": "sk-ant-..."} )

결과: 401 Unauthorized

✅ 올바른 접근 - HolySheep Gateway 사용

base_url은 반드시 https://api.holysheep.ai/v1

response = requests.post( "https://api.holysheep.ai/v1/chat/completions", headers={ "Authorization": f"Bearer {os.environ.get('HOLYSHEEP_API_KEY')}", "Content-Type": "application/json" }, json={ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "분석 요청"}] } )

해결 방법

1. HolySheep Dashboard에서 API 키 재발급

2. 환경 변수에 올바른 키 설정 확인

3. 키가 유효期内인지 확인

2. PII 감지 누락 - 정규식 한계


❌ 정규식만으로는 감지 불가능한 사례

text = """ 제 이름은 김철수입니다. 현금으로 5만 원 받고 계좌에 입금해주세요. 제 계좌는 국민은행 123-456-789 이고요. """

단순 정규식: 계좌번호 형식만 탐지

하지만 "현금으로 5만 원" 같은 암시적 금융 정보 누락

✅ 해결: HolySheep AI 기반 컨텍스트 인식

async def enhanced_detection(text: str, api_key: str): analyzer = HolySheepPIIAnalyzer(api_key) result = await analyzer.analyze_with_ai(text, "strict") # 다음과 같은隐含적 정보도 감지: # - 금융 거래 관련 금액 언급 # - 계좌 정보 암시적 표현 # - 의료 정보 contextual mention return result # HolySheep AI가 문맥을 이해하여 누락 최소화

3. 마스킹 후 텍스트 길이 불일치


❌ 길이 기반 단순 치환의 문제

def naive_mask(text, pattern, mask_char="#"): matches = list(re.finditer(pattern, text)) # 뒤에서부터 처리하지 않으면 인덱스 오류 for match in reversed(matches): # 인덱스 계산 오류 가능 pass

✅ 올바른 오프셋 기반 마스킹

def correct_mask(text: str, matches: List[PIIMatch]) -> str: """오프셋을 고려한 정확한 마스킹""" result = text offset = 0 # 인덱스 기준 정렬 (앞쪽 먼저 처리) for match in sorted(matches, key=lambda x: x.start_index): # 오프셋 누적 계산 start = match.start_index + offset end = match.end_index + offset mask = match.masked_value result = result[:start] + mask + result[end:] # 치환 후 길이 차이만큼 오프셋 업데이트 offset += len(mask) - len(match.original_value) return result

✅ 오버랩 방지 처리

def mask_non_overlapping(text: str, matches: List[PIIMatch]) -> str: """오버랩되는 PII 먼저 병합 후 마스킹""" # Confidence 높은 것 우선 정렬 sorted_matches = sorted(matches, key=lambda x: -x.confidence) non_overlapping = [] for match in sorted_matches: overlaps = False for existing in non_overlapping: if (match.start_index < existing.end_index and match.end_index > existing.start_index): overlaps = True break if not overlaps: non_overlapping.append(match) return correct_mask(text, non_overlapping)

4. 다국어 PII 감지 실패


❌ 한국어 패턴만 정의 시

PATTERNS = { "phone_kr": r"01[0-9]-\d{3,4}-\d{4}", # 영어 이름, 중국어 이름 등 누락 }

✅ 다국어 지원 확장

MULTILINGUAL_PATTERNS = { # 한국 "phone_kr": r"01[016789][-\s]?\d{3,4}[-\s]?\d{4}", "name_kr": r"[김이박최정강조윤장임한]|...", # 영어 (글로벌) "name_en": r"\b([A-Z][a-z]+\s?){1,3}\b", "ssn_us": r"\d{3}-\d{2}-\d{4}", "phone_us": r"\(\d{3}\)\s?\d{3}[-\s]?\d{4}", # 중국어 이름 (간체/번체 혼재 방지) "name_zh_simple": r"[\u4e00-\u9fa5]{2,4}", # 한자 2-4자 # 일본어 "name_jp": r"[ぁ-んァ-ン一-龯]{2,4}", }

HolySheep AI를 활용한 자동 언어 감지

async def detect_language_and_pii(text: str, api_key: str): analyzer = HolySheepPIIAnalyzer(api_key) result = await analyzer.analyze_with_ai( f"다국어 PII 감지를 수행하세요. 언어:auto, 텍스트:{text}" ) return result

기업 환경용 완전한 솔루션

대규모 데이터 처리에는 HolySheep AI의 배치 처리 기능과 결합된 Kafka 또는 Redis 기반 실시간 파이프라인이 필요합니다:

docker-compose.yml (프로덕션 인프라)

version: '3.8' services: pii-processor: build: ./pii-service environment: HOLYSHEEP_API_KEY: ${HOLYSHEEP_API_KEY} REDIS_URL: redis://pii-redis:6379 KAFKA_BROKERS: pii-kafka:9092 depends_on: - pii-redis - pii-kafka pii-redis: image: redis:7-alpine volumes: - redis-data:/data pii-kafka: image: confluentinc/cp-kafka:7.4.0 environment: KAFKA_ZOOKEEPER_CONNECT: pii-zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://pii-kafka:9092

Kubernetes Deployment

apiVersion: apps/v1 kind: Deployment metadata: name: pii-protection-service spec: replicas: 3 selector: matchLabels: app: pii-protection template: metadata: labels: app: pii-protection spec: containers: - name: pii-processor image: myregistry/pii-service:v1.2.0 env: - name: HOLYSHEEP_API_KEY valueFrom: secretKeyRef: name: holy-sheep-credentials key: api-key resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1Gi" cpu: "500m" livenessProbe: httpGet: path: /health port: 8080

모범 사례 및 체크리스트


.env.production 설정

HOLYSHEEP_API_KEY=hs_live_your_api_key_here PII_DETECTION_MODE=strict PII_LOG_ENABLED=true PII_AUDIT_TRAIL=true PII_MASK_CHAR=* PII_MAX_REQUESTS_PER_MINUTE=100

결론

PII 데이터 탈감은 AI 서비스 개발에서 선택이 아닌 필수입니다. HolySheep AI 게이트웨이를 활용하면 단일 API 키로 다양한 AI 모델의 강력한 PII 감지 기능을安全하게利用할 수 있습니다. 정규식 기반 기본 감지부터 HolySheep AI의 문맥 인식 분석까지, 요구사항에 맞는 적합한 레이어를 조합하여 개인정보 보호와 AI 서비스 품질을 동시에 달성하세요. 👉 HolySheep AI 가입하고 무료 크레딧 받기