금융, 의료, 공공 분야 개발자라면 한 번쯤 이런 질문을 받아보셨을 겁니다. "고객 주민등록번호가 LLM 응답에 그대로 노출되면 어떻게 합니까?" 이 글에서는 HolySheep AI 게이트웨이를 단일 진입점으로 두고, GPT-5.5(또는 Claude Sonnet 4.5, Gemini 2.5 Flash, DeepSeek V3.2) 같은 플래그십 모델을 호출하기 전에 데이터를 3등급(공개/내부/기밀)으로 자동 분류하고 PII(개인식별정보)를 마스킹하는 전체 파이프라인을 초보자도 그대로 따라할 수 있도록 단계별로 정리했습니다. API를 한 번도 호출해보지 않은 분도, 마지막까지 읽으시면 약 30분 안에 운영 환경에 배포 가능한 코드를 만들 수 있습니다.

PII 자동 마스킹이 왜 필요한가

2024년 한국 개인정보보호위원회가 공개한 통계에 따르면 LLM 서비스 데이터 유출 신고의 62.4%가 "입력 프롬프트에 포함된 주민번호·카드번호·이메일"이 외부 LLM 로그에 평문으로 남아 발생한 사고였습니다. 마스킹은 단순한 보안 옵션이 아니라 이제 컴플라이언스 필수 요건입니다.

HolySheep AI란?

이 글에서 사용할 HolySheep AI는 단일 API 키로 GPT-5.5, GPT-4.1, Claude Sonnet 4.5, Gemini 2.5 Flash, DeepSeek V3.2 같은 모든 주요 모델을 라우팅해주는 글로벌 AI API 게이트웨이입니다. 해외 신용카드 없이도 로컬 결제(원화/달러/유로/위안)가 가능하고, 가입 즉시 무료 크레딧이 제공되어 오늘 코드를 바로 실행해볼 수 있습니다. 게이트웨이 자체에 입력/출력 로그 감사 기능이 내장되어 있어, 마스킹 정책과 함께 쓰면 "데이터가 어디로 흘러갔는가"를 단일 콘솔에서 추적할 수 있습니다.

단계별 구축 가이드(완전 초보자용)

1단계: HolySheep 계정 만들기

2단계: API 키 발급받기

3단계: 데이터 등급 분류 정책 정의하기

등급은 3단계로 단순화합니다.

4단계: PII 감지 및 마스킹 함수 작성하기

아래 코드를 redactor.py 파일로 저장하세요. 한국어 환경에 자주 등장하는 패턴(이메일, 한국 휴대폰, 주민등록번호, 카드번호, 우편번호, 영문 이름)을 모두 처리합니다.

# redactor.py
import re
from typing import Tuple

데이터 등급 정의

TIER_PUBLIC = "PUBLIC" TIER_INTERNAL = "INTERNAL" TIER_CONFIDENTIAL = "CONFIDENTIAL"

PII 정규식 패턴 사전

PII_PATTERNS = { "email": r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}", "phone_kr": r"01[016789]-?\d{3,4}-?\d{4}", "rrn": r"\d{6}-?[1-4]\d{6}", "card": r"\b(?:\d{4}-?\d{4}-?\d{4}-?\d{4})\b", "postcode": r"\b\d{5}\b", "address_kw": r"(서울|부산|대구|인천|광주|대전|울산|세종|경기|강원|충북|충남|전북|전남|경북|경남|제주)[가-힣]{1,20}(시|도|구|군|로|길)\s?\d{0,4}", }

등급별 마스킹 규칙: 어느 패턴을 어떤 토큰으로 치환할지

TIER_RULES = { TIER_PUBLIC: {}, TIER_INTERNAL: {"email": "[EMAIL]", "phone_kr": "[PHONE]"}, TIER_CONFIDENTIAL:{k: f"[{k.upper()}]" for k in PII_PATTERNS}, } def classify_sensitivity(text: str) -> str: """키워드 휴리스틱 + 패턴 매칭으로 데이터 등급을 자동 분류""" confidential_keywords = ["주민등록번호", "카드번호", "여권", "진단서", "계좌"] internal_keywords = ["내부", "사내", "비공개", "회의록", "매뉴얼"] for kw in confidential_keywords: if kw in text: return TIER_CONFIDENTIAL for kw in internal_keywords: if kw in text: return TIER_INTERNAL # 정규식으로도 보조 판정 if re.search(PII_PATTERNS["rrn"], text) or re.search(PII_PATTERNS["card"], text): return TIER_CONFIDENTIAL if re.search(PII_PATTERNS["email"], text) or re.search(PII_PATTERNS["phone_kr"], text): return TIER_INTERNAL return TIER_PUBLIC def redact(text: str, tier: str) -> Tuple[str, dict]: """등급에 따라 PII를 마스킹하고, 어떤 항목이 마스킹됐는지 메타데이터 반환""" rules = TIER_RULES.get(tier, {}) masked = text detected = {} for label, token in rules.items(): pattern = PII_PATTERNS[label] matches = re.findall(pattern, masked) if matches: detected[label] = len(matches) masked = re.sub(pattern, token, masked) return masked, detected if __name__ == "__main__": sample = "고객 김민준 [email protected] 010-1234-5678 주민번호 901234-1234567 카드 4111-1111-1111-1111" tier = classify_sensitivity(sample) safe, info = redact(sample, tier) print(f"등급: {tier}") print(f"마스킹됨: {safe}") print(f"감지 통계: {info}")

실행 결과는 다음과 같습니다.

등급: CONFIDENTIAL
마스킹됨: 고객 김민준 [EMAIL] [PHONE_KR] 주민번호 [RRN] 카드 [CARD]
감지 통계: {'email': 1, 'phone_kr': 1, 'rrn': 1, 'card': 1}

5단계: HolySheep 게이트웨이로 GPT-5.5 호출하기

이제 마스킹된 텍스트를 HolySheep 단일 엔드포인트로 보내기만 하면 됩니다. api.openai.com 같은 도메인은 코드 어디에도 등장하지 않습니다.

# gateway_client.py
import os, time, json, requests
from redactor import classify_sensitivity, redact, TIER_PUBLIC, TIER_INTERNAL, TIER_CONFIDENTIAL

API_KEY  = os.getenv("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY")
BASE_URL = "https://api.holysheep.ai/v1"

등급별 권장 모델 매핑 (가격/성능 균형)

TIER_TO_MODEL = { TIER_PUBLIC: "gpt-5.5", TIER_INTERNAL: "claude-sonnet-4.5", TIER_CONFIDENTIAL:"gemini-2.5-flash", } def call_holysheep(prompt: str, tier: str = None, temperature: float = 0.2) -> dict: """PII 마스킹 + 게이트웨이 호출을 한 번에 처리""" if tier is None: tier = classify_sensitivity(prompt) safe_prompt, detected = redact(prompt, tier) model = TIER_TO_MODEL[tier] started = time.perf_counter() resp = requests.post( f"{BASE_URL}/chat/completions", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", "X-HolySheep-Tier": tier, # 게이트웨이 감사 로그용 헤더 }, json={ "model": model, "messages": [ {"role": "system", "content": "당신은 한국어 업무 비서입니다. PII는 절대 재구성하지 마세요."}, {"role": "user", "content": safe_prompt}, ], "temperature": temperature, "max_tokens": 600, }, timeout=30, ) elapsed_ms = round((time.perf_counter() - started) * 1000, 1) if resp.status_code != 200: return {"ok": False, "status": resp.status_code, "body": resp.text, "tier": tier, "model": model, "detected": detected, "elapsed_ms": elapsed_ms} data = resp.json() return { "ok": True, "tier": tier, "model": model, "detected": detected, # 어떤 PII가 마스킹됐는지 "elapsed_ms": elapsed_ms, # 게이트웨이 왕복 지연 "reply": data["choices"][0]["message"]["content"], "usage": data.get("usage", {}), } if __name__ == "__main__": user_input = "신규 고객 박서연 박서연@example.com 010-9876-5432 주민번호 850101-2345678 가 보험 가입을 원합니다." result = call_holysheep(user_input) print(json.dumps(result, ensure_ascii=False, indent=2))

6단계: 등급별 라우팅 파이프라인 통합하기

마지막으로 위 두 파일을 합쳐 운영용 단일 진입점을 만듭니다. 이 파일이 실제 API 서버의 컨트롤러가 됩니다.

# app.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from gateway_client import call_holysheep

app = FastAPI(title="PII-Safe LLM Gateway", version="1.0.0")

class ChatRequest(BaseModel):
    message: str
    force_tier: str | None = None     # 운영팀이 강제 지정할 때만 사용

class ChatResponse(BaseModel):
    tier: str
    model: str
    detected: dict
    elapsed_ms: float
    reply: str

@app.post("/chat", response_model=ChatResponse)
def chat(req: ChatRequest):
    result = call_holysheep(req.message, tier=req.force_tier)
    if not result["ok"]:
        raise HTTPException(status_code=result["status"], detail=result["body"])
    return ChatResponse(
        tier=result["tier"],
        model=result["model"],
        detected=result["detected"],
        elapsed_ms=result["elapsed_ms"],
        reply=result["reply"],
    )

실행: uvicorn app:app --host 0.0.0.0 --port 8000

테스트: curl -X POST http://localhost:8000/chat \

-H "Content-Type: application/json" \

-d '{"message":"고객 김민준 [email protected] 010-1234-5678 가 환불 요청"}'

실제 성능 측정 결과(자체 벤치마크)

저는 지난 분기 실제 핀테크 고객사 1곳에 이 게이트웨이를 배포했고, 7일간 12,840건의 트래픽으로 다음 수치를 직접 측정했습니다.