본문 바로가기

AI 개발

EU AI Act 개발자 실전 가이드 — 2026년 8월부터 AI 앱 만들때 주의

반응형

"우리 서비스는 한국에 있으니까 EU 법이랑 상관없겠지." 아닙니다. EU 사용자가 한 명이라도 있으면 적용됩니다. GDPR이 그랬듯, AI Act도 전 세계 개발자에게 영향을 미칩니다. 8월 2일이 77일 남았습니다.

[핵심 요약]
→ EU AI Act: 세계 최초 포괄적 AI 규제 법안 (Regulation EU 2024/1689)
→ 시행일 타임라인:
   ✅ 2025년 2월 2일: 금지 AI 관행 즉시 적용
   ✅ 2025년 8월 2일: GPAI(범용AI) 모델 규칙 적용
   ⚠️ 2026년 8월 2일: 고위험 AI 시스템 주요 규정 적용 (D-77)
   📅 2028년 8월 2일: 규제 제품 내장 AI 시스템 (Omnibus 개정)
→ 적용 범위: EU 사용자에게 서비스하는 모든 개발자 (역외 적용, GDPR과 동일)
→ 벌금: 최대 €3,500만 또는 전 세계 연매출 7% (높은 쪽 적용)
→ 개발자 핵심 의무: 리스크 분류 → 문서화 → 인간 감독 → 투명성 공시

AI Act가 개발자에게 미치는 실제 영향

영향 없음:
→ 단순 코딩 어시스턴트 (GitHub Copilot, Claude Code 사용)
→ 개인 프로젝트, 사내 개발 도구
→ 최소 위험 AI (게임, 스팸 필터 등)

투명성 공시만 필요 (Limited Risk):
→ 사용자와 대화하는 챗봇/AI 어시스턴트
→ 딥페이크, AI 생성 콘텐츠
→ 감정 인식 시스템

고위험 (High Risk) — 8월부터 풀 컴플라이언스:
→ 채용·해고·성과 평가에 AI 사용
→ 신용 점수·대출 심사 AI
→ 교육 평가·학생 성취도 분석
→ 의료 진단 보조
→ 법 집행·국경 통제
→ 중요 인프라 (전력망, 교통)

절대 금지 (2025년 2월부터):
→ 공공장소 실시간 생체 인식 감시
→ 정부의 사회 신용 점수 시스템
→ 취약계층 심리 조작 AI
→ 범죄 예측 기반 개인 타게팅

실전 1 — 내 서비스 리스크 분류

가장 먼저 해야 할 일입니다. 잘못 분류하면 과소규제 또는 과잉 대응 중 하나입니다.

# ai_risk_classifier.py
# EU AI Act Annex III 기반 리스크 분류 체크리스트

from dataclasses import dataclass
from enum import Enum

class RiskLevel(Enum):
    UNACCEPTABLE = "금지"           # 즉시 EU 서비스 불가
    HIGH = "고위험"                  # 8월까지 풀 컴플라이언스
    LIMITED = "제한적 위험"          # 투명성 공시만
    MINIMAL = "최소 위험"            # 의무 없음

@dataclass
class AISystemProfile:
    name: str
    description: str
    affects_eu_users: bool
    use_cases: list[str]

def classify_risk(system: AISystemProfile) -> tuple[RiskLevel, list[str]]:
    """
    EU AI Act Annex III 기반 리스크 분류
    반환: (리스크 레벨, 해당 근거 조항 목록)
    """
    reasons = []

    if not system.affects_eu_users:
        return RiskLevel.MINIMAL, ["EU 사용자 없음 — 적용 제외"]

    # ── 금지 AI 관행 확인 ──────────────────────────
    prohibited_keywords = [
        "사회 신용", "social scoring",
        "공공장소 실시간 생체인식",
        "취약계층 심리 조작",
        "범죄 예측 개인 타게팅"
    ]
    for keyword in prohibited_keywords:
        if any(keyword.lower() in uc.lower() for uc in system.use_cases):
            return RiskLevel.UNACCEPTABLE, [f"금지 관행: {keyword}"]

    # ── Annex III 고위험 체크 ──────────────────────
    high_risk_patterns = {
        "채용|해고|성과평가|승진|인사결정": "Annex III §4 — 고용 관리",
        "신용|대출|보험|금융심사": "Annex III §5b — 신용평가",
        "교육평가|학업|입학심사": "Annex III §3 — 교육",
        "의료진단|의료기기|임상": "Annex III §2 — 의료기기",
        "법집행|범죄|수사": "Annex III §6 — 법집행",
        "국경|비자|망명": "Annex III §7 — 이민",
        "전력망|교통|수도": "Annex III §1 — 중요 인프라",
    }

    import re
    for pattern, article in high_risk_patterns.items():
        if any(re.search(pattern, uc) for uc in system.use_cases):
            reasons.append(article)

    if reasons:
        return RiskLevel.HIGH, reasons

    # ── Limited Risk 체크 ──────────────────────────
    limited_risk_patterns = [
        "챗봇", "AI 어시스턴트", "대화형", "고객 지원",
        "콘텐츠 생성", "이미지 생성", "음성 합성",
        "딥페이크", "감정 인식"
    ]
    for pattern in limited_risk_patterns:
        if any(pattern in uc for uc in system.use_cases):
            reasons.append(f"Article 50 — 투명성 공시 필요: {pattern}")

    if reasons:
        return RiskLevel.LIMITED, reasons

    return RiskLevel.MINIMAL, ["최소 위험 — 특별 의무 없음"]


# 실제 사용 예시
systems = [
    AISystemProfile(
        name="채용 AI 스크리닝",
        description="이력서 자동 분석 및 후보자 순위 매기기",
        affects_eu_users=True,
        use_cases=["이력서 분석", "채용 결정 보조", "후보자 스크리닝"]
    ),
    AISystemProfile(
        name="고객 지원 챗봇",
        description="24시간 고객 문의 응대 AI",
        affects_eu_users=True,
        use_cases=["챗봇", "고객 지원", "FAQ 자동 응답"]
    ),
    AISystemProfile(
        name="코드 자동완성",
        description="개발자용 AI 코딩 어시스턴트",
        affects_eu_users=True,
        use_cases=["코드 제안", "버그 수정", "문서화"]
    ),
]

for system in systems:
    level, reasons = classify_risk(system)
    print(f"\n{system.name}")
    print(f"  리스크 레벨: {level.value}")
    print(f"  근거: {', '.join(reasons)}")
[분류 결과 예시]
채용 AI 스크리닝
  리스크 레벨: 고위험
  근거: Annex III §4 — 고용 관리

고객 지원 챗봇
  리스크 레벨: 제한적 위험
  근거: Article 50 — 투명성 공시 필요

코드 자동완성
  리스크 레벨: 최소 위험
  근거: 최소 위험 — 특별 의무 없음

실전 2 — Limited Risk 투명성 공시 구현

챗봇, AI 어시스턴트, 콘텐츠 생성 서비스는 8월부터 투명성 공시가 의무입니다.

// transparency.ts — Article 50 투명성 의무 구현

interface AIDisclosure {
  isAI: boolean;           // AI와 대화 중임을 알림
  aiProvider: string;      // 어떤 AI 모델 사용 중인지
  capabilities: string[];  // AI가 할 수 있는 것
  limitations: string[];   // AI의 한계
  humanEscalation: boolean; // 사람에게 연결 가능한지
}

// ✅ 챗봇 시작 시 의무 고지 메시지
function generateAIDisclosureMessage(disclosure: AIDisclosure): string {
  return `
안녕하세요! 저는 ${disclosure.aiProvider} 기반 AI 어시스턴트입니다.

📌 EU AI Act Article 50에 따라 안내드립니다:
• 저는 인공지능 시스템입니다 (사람이 아닙니다)
• 제 답변은 자동으로 생성되며 오류가 있을 수 있습니다
• 중요한 결정에는 전문가 확인을 권장합니다
${disclosure.humanEscalation ? '• 사람 상담원 연결: "상담원 연결" 입력' : ''}

무엇을 도와드릴까요?
  `.trim();
}

// ✅ AI 생성 콘텐츠 워터마킹 (Article 50(2))
function markAIGeneratedContent(content: string, metadata: {
  model: string;
  timestamp: Date;
  contentType: 'text' | 'image' | 'audio' | 'video';
}): { content: string; watermark: string } {
  const watermark = JSON.stringify({
    generated_by: 'AI',
    model: metadata.model,
    timestamp: metadata.timestamp.toISOString(),
    eu_ai_act_compliant: true,
  });

  // 텍스트는 메타데이터에 표시
  // 이미지/오디오/비디오는 기술적 워터마킹 별도 필요
  return {
    content: content + '\n\n[이 콘텐츠는 AI가 생성했습니다]',
    watermark,
  };
}

// ✅ 딥페이크 명시적 라벨링 (Article 50(4))
function applyDeepfakeLabel(mediaUrl: string, context: {
  originalPerson?: string;
  isRealEventSimulation: boolean;
}): string {
  // 공공 이익 목적(풍자, 예술) 외 딥페이크는 명시 필수
  const label = `[AI 생성 이미지/영상 — 실제와 다를 수 있음]`;
  console.log(`딥페이크 라벨 적용: ${mediaUrl} → ${label}`);
  return label;
}

실전 3 — High Risk 핵심 기술 의무 구현

고위험 AI 시스템은 Article 9~14 의무를 모두 충족해야 합니다.

# high_risk_compliance.py
# Article 9-14 고위험 AI 의무 구현 템플릿

import json
import hashlib
from datetime import datetime
from dataclasses import dataclass, asdict
from typing import Any

# ── Article 11: 기술 문서화 ─────────────────────────────

@dataclass
class AnnexIVDocumentation:
    """Annex IV 요구 기술 문서 — 10년 보존 의무"""
    system_name: str
    version: str
    purpose: str                    # 의도된 목적
    provider_info: dict             # 개발사 정보
    training_data_description: str  # 훈련 데이터 설명
    performance_metrics: dict       # 정확도, 편향성 측정
    known_limitations: list[str]    # 알려진 한계
    intended_users: list[str]       # 의도된 사용자
    geographic_scope: list[str]     # 지리적 적용 범위
    risk_assessment: dict           # 위험 평가 결과
    human_oversight_measures: list  # 인간 감독 방법
    created_at: str = ""
    updated_at: str = ""

    def __post_init__(self):
        self.created_at = datetime.now().isoformat()
        self.updated_at = self.created_at

    def to_json(self) -> str:
        return json.dumps(asdict(self), ensure_ascii=False, indent=2)

    def get_document_hash(self) -> str:
        """문서 무결성 검증용 해시"""
        return hashlib.sha256(self.to_json().encode()).hexdigest()


# ── Article 9: 리스크 관리 시스템 ──────────────────────

class RiskManagementSystem:
    """지속적 리스크 모니터링 및 완화"""

    def __init__(self, system_name: str):
        self.system_name = system_name
        self.risk_log = []
        self.incidents = []

    def assess_risk(self, risk_type: str, severity: str,
                    probability: str, mitigation: str) -> dict:
        """리스크 평가 기록 (감사 추적용)"""
        risk_entry = {
            "timestamp": datetime.now().isoformat(),
            "risk_type": risk_type,
            "severity": severity,          # low/medium/high/critical
            "probability": probability,    # low/medium/high
            "mitigation": mitigation,
            "status": "identified",
        }
        self.risk_log.append(risk_entry)
        return risk_entry

    def report_incident(self, description: str,
                        affected_persons: int,
                        severity: str) -> dict:
        """
        Article 73: 사고 보고 의무
        심각한 사고는 72시간 내 당국 보고 필요
        """
        incident = {
            "id": f"INC-{len(self.incidents)+1:04d}",
            "timestamp": datetime.now().isoformat(),
            "description": description,
            "affected_persons": affected_persons,
            "severity": severity,
            "reporting_deadline": "72시간 내 당국 보고" if severity == "serious" else "15일 내",
            "status": "reported"
        }
        self.incidents.append(incident)

        if severity == "serious":
            print(f"⚠️ 심각한 사고 감지 — 72시간 내 당국 보고 필요: {incident['id']}")

        return incident


# ── Article 12: 로깅 및 감사 추적 ──────────────────────

class AuditTrailLogger:
    """모든 AI 결정에 대한 감사 추적 (10년 보존)"""

    def log_decision(self, input_data: dict, output: Any,
                     confidence: float, human_reviewed: bool,
                     session_id: str) -> dict:
        """
        고위험 AI의 모든 결정 기록
        - 입력 데이터 해시 (개인정보 직접 저장 금지)
        - 출력 결과
        - 신뢰도 점수
        - 인간 검토 여부
        """
        log_entry = {
            "log_id": f"LOG-{datetime.now().strftime('%Y%m%d%H%M%S%f')}",
            "session_id": session_id,
            "timestamp": datetime.now().isoformat(),
            # 개인정보 직접 저장 대신 해시값 저장 (GDPR 준수)
            "input_hash": hashlib.sha256(
                json.dumps(input_data, sort_keys=True).encode()
            ).hexdigest(),
            "output_summary": str(output)[:500],  # 요약만
            "confidence_score": confidence,
            "human_reviewed": human_reviewed,
            "model_version": "v1.0.0",
        }
        # 실제 구현에서는 DB 저장 (10년 보존 필수)
        return log_entry


# ── Article 14: 인간 감독 ──────────────────────────────

class HumanOversightSystem:
    """고위험 AI의 인간 감독 메커니즘"""

    def __init__(self, confidence_threshold: float = 0.85):
        self.confidence_threshold = confidence_threshold
        self.override_log = []

    def requires_human_review(self, ai_output: dict) -> bool:
        """인간 검토가 필요한 케이스 판단"""
        confidence = ai_output.get("confidence", 0)
        is_high_impact = ai_output.get("impact", "low") == "high"
        is_novel_case = ai_output.get("is_novel", False)

        return (
            confidence < self.confidence_threshold or
            is_high_impact or
            is_novel_case
        )

    def human_override(self, decision_id: str, original_output: Any,
                       override_value: Any, reviewer_id: str,
                       reason: str) -> dict:
        """인간이 AI 결정을 번복한 기록"""
        override = {
            "decision_id": decision_id,
            "timestamp": datetime.now().isoformat(),
            "original_ai_output": str(original_output),
            "human_override_value": str(override_value),
            "reviewer_id": reviewer_id,  # 익명화 가능
            "reason": reason,
        }
        self.override_log.append(override)
        print(f"✅ 인간 감독 번복 기록: {decision_id}")
        return override

실전 4 — 개발팀 준수 체크리스트

# compliance_checker.py — CI/CD에 통합 가능한 자동 체크

CHECKLIST = {
    "즉시 적용 (2025년 2월~)": {
        "금지 AI 관행": [
            "☐ 사회 신용 점수 시스템 없음 확인",
            "☐ 공공장소 실시간 생체인식 없음 확인",
            "☐ 취약계층 심리 조작 없음 확인",
        ],
        "AI 리터러시": [
            "☐ 팀 전체 EU AI Act 기본 교육 완료",
            "☐ AI 사용 정책 문서화",
        ]
    },
    "2026년 8월 전 완료 필요": {
        "시스템 인벤토리": [
            "☐ 서비스 내 모든 AI 시스템 목록화",
            "☐ 서드파티 SaaS AI 도구 포함",
            "☐ 각 시스템 리스크 분류 완료",
            "☐ EU 사용자 영향 여부 확인",
        ],
        "Limited Risk (챗봇/생성AI)": [
            "☐ 챗봇 시작 시 AI 고지 메시지 표시",
            "☐ AI 생성 콘텐츠 워터마킹 또는 라벨링",
            "☐ 딥페이크 명시적 라벨 적용",
        ],
        "High Risk (해당 시)": [
            "☐ Annex IV 기술 문서 작성 (Article 11)",
            "☐ 리스크 관리 시스템 구축 (Article 9)",
            "☐ 모든 AI 결정 감사 로그 (Article 12, 10년 보존)",
            "☐ 인간 감독 메커니즘 구현 (Article 14)",
            "☐ AI 정확도·편향성 정기 모니터링",
            "☐ 사고 보고 절차 수립 (72시간 보고)",
            "☐ EU AI Act 준수 선언서 작성",
        ],
    },
    "GPAI 제공자 (2025년 8월~)": {
        "LLM 서비스 제공하는 경우": [
            "☐ 기술 문서 및 학습 데이터 요약 공개",
            "☐ 저작권 정책 및 opt-out 메커니즘",
            "☐ AI 생성 콘텐츠 감지 가능성 보장",
            "☐ 시스템적 위험 모델: 적대적 테스트 의무",
        ]
    }
}

def print_checklist(category: str = None):
    for phase, items in CHECKLIST.items():
        if category and category not in phase:
            continue
        print(f"\n{'='*50}")
        print(f"📋 {phase}")
        for section, tasks in items.items():
            print(f"\n  [{section}]")
            for task in tasks:
                print(f"    {task}")

print_checklist()
[위반 시 벌금 체계]
금지 AI 관행 위반:
→ 최대 €3,500만 또는 전 세계 연매출 7% (높은 쪽)

고위험 AI 의무 위반:
→ 최대 €1,500만 또는 전 세계 연매출 3%

당국에 허위 정보 제공:
→ 최대 €750만 또는 연매출 1.5%

참고: GDPR 2018~2025년 7년간 €45억 벌금 부과 전례
→ AI Act도 동일 수준 적극 집행 예고

마무리

✅ 지금 당장 해야 하는 것
→ 내 서비스의 AI 시스템 전체 목록 작성
→ EU 사용자 존재 여부 확인
→ 각 AI 시스템 리스크 분류 (금지/고위험/제한/최소)
→ 챗봇이 있으면 AI 고지 메시지 추가 (8월 전)
→ 채용·신용·의료 관련 AI면 Annex IV 문서 착수

❌ 하면 안 되는 것
→ "우리는 한국 회사라서 관계없다" (역외 적용)
→ "아직 시간 있다" (8월 2일 D-77)
→ AI 생성 콘텐츠에 라벨 없이 배포
→ 고위험 AI 의사결정 로그 미보존
→ 오픈소스 모델이라고 의무 면제 착각
   (오픈소스 배포자도 고위험 시스템 배포 시 동일 의무)

관련 글

https://cell-devlog.tistory.com/161

 

5개국 "에이전트 AI 보안 가이드" 완전 분석 — 정부가 경고한 AI 에이전트 5가지 위험과 개발자 체

CISA, NSA, 영국, 호주, 캐나다, 뉴질랜드가 함께 경고했습니다. AI 에이전트는 이미 핵심 인프라에서 돌아가고 있고, 대부분의 조직이 아무도 실시간으로 감사할 수 없을 만큼 많은 권한을 줬다고.[

cell-devlog.tistory.com

https://cell-devlog.tistory.com/98

 

AI 코딩 툴 보안 실전 — Claude Code 소스 유출 이후 달라진 공격 지형

2026년 3월 31일, Claude Code 소스코드가 npm에 실수로 노출됐어요.유출 규모:→ 51만 2천 줄 TypeScript→ 1,906개 파일→ 24시간 만에 GitHub 포크 41,500개공격자들의 반응 속도:→ 유출 24시간 이내: 악성 "leak

cell-devlog.tistory.com

https://cell-devlog.tistory.com/66

 

MCP 서버 보안 설정 완전 가이드 — 인증, 권한 제한, 위험 차단

MCP 연동하고 나서 이 생각 한 번쯤 해봤을 거예요."Claude가 우리 DB에 직접 접근하는데... 혹시 DROP TABLE 날리면 어떡하지?""Slack 토큰이 .env에 있는데 유출되면?""GitHub 토큰으로 레포 삭제도 되는 거

cell-devlog.tistory.com

https://cell-devlog.tistory.com/27

 

AI 에이전트 보안 완전 정리 — Prompt Injection 공격과 방어 완전 가이드

AI 에이전트를 프로덕션에 올리면 이런 일이 생겨요."에이전트가 갑자기 이상한 행동을 해. 아무도 그런 지시를 안 했는데."이건 버그가 아니에요. 공격이에요. OWASP 2025 LLM Top 10에서 Prompt Injection

cell-devlog.tistory.com

 

반응형