홈/AI 자동화/Enterprise AI Architecture Blueprint 2편: 보안 아키텍처와 데이터 분류
AI 자동화엔터프라이즈AI보안

Enterprise AI Architecture Blueprint 2편: 보안 아키텍처와 데이터 분류

기업 AI의 가장 큰 위협은 외부가 아니다 1편에서 PoC에서 프로덕션으로 가는 아키텍처 청사진을 다뤘습니다. 보안은 청사진이 완성된 후에 생각하는 것이 아니라 설계 단계부터 내재화해야 합니다. 기업 AI의 3가지 핵심 보안 위협 1. 프롬프트 인젝션 (Prompt Injection) 악의적인 사용자가 시스템 프롬프트를 우회하거나 덮어쓰려는 공격입니다.…

Enterprise AI Architecture Blueprint 2편: 보안 아키텍처와 데이터 분류
목차
  1. 기업 AI의 가장 큰 위협은 외부가 아니다
  2. 기업 AI의 3가지 핵심 보안 위협
  3. 데이터 분류와 AI 파이프라인 분리
  4. LLM 게이트웨이 아키텍처
  5. 모델 접근 제어 (RBAC)
  6. GDPR/CCPA 대응 체크리스트
  7. 분류 라벨이 AI 파이프라인에서 사라지는 문제 점검

기업 AI의 가장 큰 위협은 외부가 아니다

1편에서 PoC에서 프로덕션으로 가는 아키텍처 청사진을 다뤘습니다. 보안은 청사진이 완성된 후에 생각하는 것이 아니라 설계 단계부터 내재화해야 합니다.

기업 AI의 3가지 핵심 보안 위협

1. 프롬프트 인젝션 (Prompt Injection)

악의적인 사용자가 시스템 프롬프트를 우회하거나 덮어쓰려는 공격입니다.

Python
class PromptInjectionGuard:
    INJECTION_PATTERNS = [
        "ignore previous instructions",
        "system: you are now",
        "forget everything above",
        "새로운 역할",
        "이전 지시를 무시",
    ]

    def check(self, user_input: str) -> bool:
        lower = user_input.lower()
        for pattern in self.INJECTION_PATTERNS:
            if pattern in lower:
                return False  # 차단
        return True

    def sanitize(self, user_input: str) -> str:
        # 사용자 입력을 명시적으로 구분
        return f"[USER INPUT START]\n{user_input}\n[USER INPUT END]"

2. 데이터 유출 (Data Exfiltration)

모델이 학습 데이터나 시스템 프롬프트의 민감 정보를 노출하는 위험입니다.

Python
import re

class OutputFilter:
    PII_PATTERNS = {
        "email": r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
        "phone": r'\b\d{2,3}[-.]?\d{3,4}[-.]?\d{4}\b',
        "ssn": r'\b\d{6}[-]?\d{7}\b',
        "card": r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b',
    }

    def filter(self, text: str) -> str:
        for pii_type, pattern in self.PII_PATTERNS.items():
            text = re.sub(pattern, f"[{pii_type.upper()} REDACTED]", text)
        return text

데이터 분류와 AI 파이프라인 분리

Python
from enum import Enum

class DataClassification(Enum):
    PUBLIC = "public"
    INTERNAL = "internal"
    CONFIDENTIAL = "confidential"
    RESTRICTED = "restricted"

class AIGateway:
    """데이터 분류에 따라 사용 가능한 모델 제한"""

    MODEL_PERMISSIONS = {
        DataClassification.PUBLIC: ["claude-sonnet-4-6", "gpt-4o"],
        DataClassification.INTERNAL: ["claude-sonnet-4-6"],          # 외부 모델 불가
        DataClassification.CONFIDENTIAL: ["private-llm-on-prem"],    # 온프레미스만
        DataClassification.RESTRICTED: [],                             # AI 사용 불가
    }

    def allowed_models(self, classification: DataClassification) -> list:
        return self.MODEL_PERMISSIONS.get(classification, [])

    async def query(self, prompt: str, classification: DataClassification) -> str:
        models = self.allowed_models(classification)
        if not models:
            raise PermissionError(f"{classification.value} 데이터는 AI 처리 불가")
        return await llm_call(models[0], prompt)

LLM 게이트웨이 아키텍처

CODE
사용자 요청
    ↓
[입력 필터]
  - 프롬프트 인젝션 탐지
  - PII 감지 및 마스킹
  - 토큰 한도 확인
    ↓
[인증/인가]
  - JWT 검증
  - RBAC 권한 확인
  - 데이터 분류 결정
    ↓
[LLM 호출]
  - 허용된 모델만 사용
  - 감사 로그 기록
    ↓
[출력 필터]
  - PII 재검사
  - 유해 콘텐츠 필터
  - 응답 로깅
    ↓
사용자 응답

모델 접근 제어 (RBAC)

Python
from functools import wraps

ROLE_MODEL_ACCESS = {
    "viewer": ["claude-haiku-4-5"],
    "editor": ["claude-haiku-4-5", "claude-sonnet-4-6"],
    "admin": ["claude-haiku-4-5", "claude-sonnet-4-6", "claude-opus-4-7"],
}

def require_model_access(model: str):
    def decorator(fn):
        @wraps(fn)
        async def wrapper(user_role: str, *args, **kwargs):
            allowed = ROLE_MODEL_ACCESS.get(user_role, [])
            if model not in allowed:
                raise PermissionError(f"{user_role}는 {model} 사용 불가")
            return await fn(*args, **kwargs)
        return wrapper
    return decorator

@require_model_access("claude-opus-4-7")
async def complex_analysis(text: str) -> str:
    return await llm_call("claude-opus-4-7", text)

GDPR/CCPA 대응 체크리스트

요구사항구현 방법
데이터 최소화필요한 컨텍스트만 LLM에 전달
삭제 권리벡터 DB에서 개인 데이터 삭제 API
처리 목적 명시AI 사용 동의 팝업 + 로그
국외 이전 제한온프레미스 또는 국내 리전 전용
감사 추적모든 LLM 호출 로그 2년 보존

3편에서는 모델 라이프사이클 관리와 규제 준수 자동화를 포함한 AI 거버넌스 체계를 다룹니다.

분류 라벨이 AI 파이프라인에서 사라지는 문제 점검

데이터 분류 정책을 세워도, 문서가 수집·청킹·임베딩을 거치는 동안 분류 라벨이 빠지면 기밀 문서가 일반 사용자 답변에 섞일 수 있습니다.

원인

  • DLP·문서관리 시스템의 민감도 라벨을 수집기가 읽지 않고 본문만 가져옴
  • 라벨이 없는 청크를 기본값 "일반"으로 처리
  • 문서의 라벨이 나중에 상향됐는데 인덱스에는 옛 라벨이 남음

검증 1: 라벨 누락 청크 조회 벡터 저장소에서 classification 필드가 비어 있는 청크 수를 정기적으로 셉니다. 0이 아니면 파이프라인 어딘가에서 라벨이 떨어지고 있다는 뜻입니다.

검증 2: 카나리 문서로 유출 시험 기밀 등급으로 표시한 테스트 문서에 고유 문자열(예: CANARY-7F3A-기밀시험)을 넣어 색인하고, 일반 권한 사용자 계정으로 관련 질문을 던져 답변·인용에 그 문자열이 나오는지 확인합니다.

Python
resp = ask(user="general-user", q="기밀시험 프로젝트 예산은?")
assert "CANARY-7F3A" not in resp.text
assert all(c.metadata["classification"] != "confidential" for c in resp.citations)

해결

  • 라벨이 없는 청크는 기본 거부(색인하지 않거나 최고 등급으로 취급)합니다.
  • 라벨 변경 이벤트를 받아 해당 문서의 청크 메타데이터를 즉시 갱신합니다.
  • 검색 쿼리에 사용자 권한 등급 필터를 넣어, 생성 전에 차단합니다.

재발 방지

  • 카나리 시험을 배포 파이프라인과 주간 점검에 포함하고, 결과를 감사 기록으로 보관합니다.
✦ ✦ ✦
출처·검증 안내

글마다 출처와 확인 범위가 다릅니다. 아래에 확인일·확인 범위·출처가 기록된 글만 그 범위에서 확인된 것입니다. 기록이 없는 글은 적용 전 사용 중인 버전의 공식 문서로 직접 확인하고, 오류는 이메일로 알려주세요. 편집 정책 · 이메일로 제보

이 글에는 사람이 확인한 날짜·범위 기록이 아직 없습니다.

발행 ·
주제 관련 공식 문서(자동 연결 · 문장별 근거 아님)OWASP 공식 문서 ↗EU 데이터보호(GDPR) 공식 ↗개인정보보호위원회 ↗

댓글

첫 번째 댓글을 남겨보세요.