⚖️ AI 규제/윤리

인간 감독

Human Oversight

AI 시스템에 대한 인간의 감시와 개입 권한. EU AI Act 제14조에서 고위험 AI의 필수 요건으로 규정.

상세 설명

인간 감독(Human Oversight)은 EU AI Act 제14조에서 정의하는 고위험 AI 시스템의 핵심 요건으로, AI 시스템이 자연인에 의해 효과적으로 감독될 수 있도록 설계되어야 함을 의미합니다. 이는 AI의 자율성이 증가하더라도 인간이 최종 결정권을 유지하고, 필요시 AI 시스템의 작동을 중단하거나 수정할 수 있어야 함을 보장합니다.

EU AI Act는 인간 감독의 세 가지 모델을 제시합니다. 첫째, Human-in-the-loop(HITL)는 AI가 결정을 내리기 전에 매번 인간의 승인이 필요한 모델입니다. 둘째, Human-on-the-loop(HOTL)는 AI가 자동으로 결정을 내리지만 인간이 실시간으로 모니터링하고 개입할 수 있는 모델입니다. 셋째, Human-in-command(HIC)는 AI 시스템의 전체 운영 사이클에 대해 인간이 감독하고 시스템을 끄거나 변경할 권한을 가지는 모델입니다.

제14조는 구체적으로 고위험 AI 시스템이 다음 기능을 갖출 것을 요구합니다: (a) 감독자가 AI 시스템의 능력과 한계를 올바르게 이해할 수 있는 인터페이스 도구 제공, (b) 감독자가 출력을 올바르게 해석할 수 있도록 지원, (c) 감독자가 시스템을 무시하거나 작동을 중단하거나 되돌릴 수 있는 능력, (d) 자동화 편향(automation bias)의 위험을 인식하고 대응할 수 있는 조치. 이러한 요건 미준수 시 최대 1,500만 유로 또는 전 세계 연간 매출의 3% 과징금이 부과될 수 있습니다.

한국 인공지능기본법 제22조도 고위험 인공지능에 대해 "이용자가 인공지능기술등을 활용한 서비스의 이용 중단을 요구할 수 있는 장치"를 마련할 것을 요구합니다. 인간 감독은 단순한 기술적 요건을 넘어, AI 윤리의 핵심인 '인간 중심 AI(Human-centric AI)'를 실현하는 메커니즘입니다. 특히 의료 진단, 채용 심사, 신용 평가 등 개인의 권리에 중대한 영향을 미치는 결정에서 인간 감독의 역할이 강조됩니다.

코드 예제

Python을 사용한 인간 감독 메커니즘 구현 예제입니다.

"""
인간 감독(Human Oversight) 시스템 구현
EU AI Act 제14조 준수
"""
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from typing import Dict, List, Optional, Callable, Any
import logging
import time


class OversightMode(Enum):
    """인간 감독 모드 (EU AI Act 기준)"""
    HUMAN_IN_THE_LOOP = "hitl"      # 매 결정마다 인간 승인 필요
    HUMAN_ON_THE_LOOP = "hotl"      # 실시간 모니터링 + 개입 가능
    HUMAN_IN_COMMAND = "hic"        # 전체 운영 사이클 감독


class DecisionStatus(Enum):
    """AI 결정 상태"""
    PENDING_REVIEW = "pending"      # 인간 검토 대기
    APPROVED = "approved"           # 승인됨
    REJECTED = "rejected"           # 거부됨
    OVERRIDDEN = "overridden"       # 무효화됨
    AUTO_EXECUTED = "auto"          # 자동 실행됨
    HALTED = "halted"               # 중단됨


@dataclass
class AIDecision:
    """AI 결정 데이터 구조"""
    decision_id: str
    model_name: str
    input_data: Dict
    prediction: Any
    confidence: float
    reasoning: str
    timestamp: datetime = field(default_factory=datetime.now)
    status: DecisionStatus = DecisionStatus.PENDING_REVIEW
    reviewer_id: Optional[str] = None
    review_notes: Optional[str] = None
    review_timestamp: Optional[datetime] = None


class HumanOversightSystem:
    """
    EU AI Act 제14조 준수 인간 감독 시스템

    고위험 AI 시스템에 필요한 모든 감독 기능 제공:
    - 결정 검토 및 승인/거부
    - 시스템 중단 및 무효화
    - 감독자 알림 및 경고
    - 자동화 편향 방지
    """

    # 신뢰도 임계값 (이 이하면 반드시 인간 검토 필요)
    CONFIDENCE_THRESHOLD = 0.85

    # 자동화 편향 경고 메시지
    AUTOMATION_BIAS_WARNING = """
    ⚠️ 자동화 편향 주의
    AI의 추천을 맹목적으로 수용하지 마세요.
    입력 데이터와 맥락을 독립적으로 검토하세요.
    """

    def __init__(
        self,
        mode: OversightMode,
        high_risk_domain: str,
        alert_handlers: List[Callable] = None
    ):
        self.mode = mode
        self.high_risk_domain = high_risk_domain
        self.alert_handlers = alert_handlers or []
        self.decisions: Dict[str, AIDecision] = {}
        self.is_system_active = True
        self.halt_reason: Optional[str] = None
        self.logger = logging.getLogger("human_oversight")

        # 감독 통계
        self.stats = {
            "total_decisions": 0,
            "human_reviewed": 0,
            "auto_executed": 0,
            "overridden": 0,
            "halted": 0
        }

    def register_decision(
        self,
        decision: AIDecision
    ) -> str:
        """
        AI 결정 등록 및 감독 프로세스 시작

        Returns:
            decision_id: 결정 추적용 ID
        """
        if not self.is_system_active:
            raise SystemError(f"System halted: {self.halt_reason}")

        self.decisions[decision.decision_id] = decision
        self.stats["total_decisions"] += 1

        # 모드별 처리
        if self.mode == OversightMode.HUMAN_IN_THE_LOOP:
            # HITL: 모든 결정에 인간 검토 필요
            decision.status = DecisionStatus.PENDING_REVIEW
            self._notify_reviewers(decision)

        elif self.mode == OversightMode.HUMAN_ON_THE_LOOP:
            # HOTL: 저신뢰도 결정만 검토, 나머지는 자동 실행
            if decision.confidence < self.CONFIDENCE_THRESHOLD:
                decision.status = DecisionStatus.PENDING_REVIEW
                self._notify_reviewers(decision)
            else:
                decision.status = DecisionStatus.AUTO_EXECUTED
                self.stats["auto_executed"] += 1
                self._log_auto_execution(decision)

        elif self.mode == OversightMode.HUMAN_IN_COMMAND:
            # HIC: 배치 검토를 위해 대기
            decision.status = DecisionStatus.AUTO_EXECUTED
            self.stats["auto_executed"] += 1

        self.logger.info(
            f"Decision registered: {decision.decision_id}, "
            f"mode={self.mode.value}, status={decision.status.value}"
        )

        return decision.decision_id

    def review_decision(
        self,
        decision_id: str,
        reviewer_id: str,
        approved: bool,
        notes: str = ""
    ) -> AIDecision:
        """
        인간 검토자의 결정 승인/거부

        Args:
            decision_id: 결정 ID
            reviewer_id: 검토자 ID
            approved: 승인 여부
            notes: 검토 메모
        """
        decision = self.decisions.get(decision_id)
        if not decision:
            raise ValueError(f"Decision not found: {decision_id}")

        # 자동화 편향 경고 표시
        self.logger.warning(self.AUTOMATION_BIAS_WARNING)

        decision.reviewer_id = reviewer_id
        decision.review_notes = notes
        decision.review_timestamp = datetime.now()
        decision.status = (
            DecisionStatus.APPROVED if approved
            else DecisionStatus.REJECTED
        )

        self.stats["human_reviewed"] += 1

        self.logger.info(
            f"Decision reviewed: {decision_id}, "
            f"reviewer={reviewer_id}, approved={approved}"
        )

        return decision

    def override_decision(
        self,
        decision_id: str,
        supervisor_id: str,
        new_decision: Any,
        reason: str
    ) -> AIDecision:
        """
        AI 결정 무효화 및 인간 결정으로 대체
        (EU AI Act 제14조 제4항 c호)
        """
        decision = self.decisions.get(decision_id)
        if not decision:
            raise ValueError(f"Decision not found: {decision_id}")

        # 원래 결정 기록 유지
        original_prediction = decision.prediction

        decision.status = DecisionStatus.OVERRIDDEN
        decision.prediction = new_decision
        decision.reviewer_id = supervisor_id
        decision.review_notes = f"OVERRIDE: {reason}. Original: {original_prediction}"
        decision.review_timestamp = datetime.now()

        self.stats["overridden"] += 1

        self.logger.warning(
            f"Decision overridden: {decision_id}, "
            f"supervisor={supervisor_id}, reason={reason}"
        )

        return decision

    def halt_system(
        self,
        supervisor_id: str,
        reason: str,
        emergency: bool = False
    ) -> bool:
        """
        AI 시스템 즉시 중단
        (EU AI Act 제14조 제4항 c호 - "stop" 버튼 기능)

        Args:
            supervisor_id: 중단 권한자 ID
            reason: 중단 사유
            emergency: 긴급 중단 여부
        """
        self.is_system_active = False
        self.halt_reason = reason

        # 대기 중인 모든 결정 중단
        for decision in self.decisions.values():
            if decision.status == DecisionStatus.PENDING_REVIEW:
                decision.status = DecisionStatus.HALTED
                self.stats["halted"] += 1

        self.logger.critical(
            f"SYSTEM HALTED by {supervisor_id}: {reason}"
        )

        # 긴급 알림 발송
        if emergency:
            self._send_emergency_alert(supervisor_id, reason)

        return True

    def resume_system(
        self,
        supervisor_id: str,
        confirmation_code: str
    ) -> bool:
        """시스템 재개 (이중 확인 필요)"""
        # 보안: 확인 코드 검증 필요
        if not self._verify_confirmation(supervisor_id, confirmation_code):
            raise PermissionError("Invalid confirmation")

        self.is_system_active = True
        self.halt_reason = None

        self.logger.info(
            f"System resumed by {supervisor_id}"
        )

        return True

    def get_oversight_dashboard(self) -> Dict:
        """
        감독자 대시보드 데이터
        (EU AI Act 제14조 제4항 a호 - 감독 인터페이스)
        """
        pending = [
            d for d in self.decisions.values()
            if d.status == DecisionStatus.PENDING_REVIEW
        ]

        return {
            "system_status": "active" if self.is_system_active else "halted",
            "halt_reason": self.halt_reason,
            "mode": self.mode.value,
            "domain": self.high_risk_domain,
            "statistics": self.stats,
            "pending_reviews": len(pending),
            "pending_decisions": [
                {
                    "id": d.decision_id,
                    "model": d.model_name,
                    "confidence": d.confidence,
                    "reasoning": d.reasoning,
                    "timestamp": d.timestamp.isoformat()
                }
                for d in pending
            ],
            "automation_bias_warning": self.AUTOMATION_BIAS_WARNING,
            "oversight_capabilities": {
                "can_review": True,
                "can_override": True,
                "can_halt": True,
                "can_resume": True
            }
        }

    def _notify_reviewers(self, decision: AIDecision):
        """검토자에게 알림 발송"""
        for handler in self.alert_handlers:
            try:
                handler(
                    event="REVIEW_REQUIRED",
                    decision=decision,
                    priority="high" if decision.confidence < 0.5 else "normal"
                )
            except Exception as e:
                self.logger.error(f"Alert handler failed: {e}")

    def _log_auto_execution(self, decision: AIDecision):
        """자동 실행 결정 감사 로그"""
        self.logger.info(
            f"Auto-executed decision: {decision.decision_id}, "
            f"confidence={decision.confidence:.2%}"
        )

    def _send_emergency_alert(self, supervisor_id: str, reason: str):
        """긴급 알림 발송"""
        for handler in self.alert_handlers:
            handler(
                event="EMERGENCY_HALT",
                supervisor=supervisor_id,
                reason=reason,
                priority="critical"
            )

    def _verify_confirmation(
        self,
        supervisor_id: str,
        code: str
    ) -> bool:
        """확인 코드 검증 (실제 구현 필요)"""
        # TODO: 실제 인증 로직 구현
        return len(code) == 6 and code.isdigit()


# 사용 예시
if __name__ == "__main__":
    import uuid

    logging.basicConfig(level=logging.INFO)

    def alert_handler(**kwargs):
        print(f"ALERT: {kwargs}")

    # 인간 감독 시스템 초기화 (HITL 모드)
    oversight = HumanOversightSystem(
        mode=OversightMode.HUMAN_IN_THE_LOOP,
        high_risk_domain="credit_scoring",
        alert_handlers=[alert_handler]
    )

    # AI 결정 등록
    decision = AIDecision(
        decision_id=str(uuid.uuid4())[:8],
        model_name="credit_score_model_v2",
        input_data={"income": 50000, "debt": 10000},
        prediction="APPROVE",
        confidence=0.78,
        reasoning="Low debt-to-income ratio suggests low default risk"
    )

    oversight.register_decision(decision)

    # 대시보드 확인
    dashboard = oversight.get_oversight_dashboard()
    print(f"Pending reviews: {dashboard['pending_reviews']}")

    # 인간 검토
    reviewed = oversight.review_decision(
        decision_id=decision.decision_id,
        reviewer_id="analyst_001",
        approved=True,
        notes="Verified income documentation"
    )

    print(f"Decision status: {reviewed.status.value}")
    print(f"Stats: {oversight.stats}")

실무 대화

PM: 신용 평가 AI를 도입하려는데, EU 고객도 있어서 AI Act 규정을 따라야 합니다. 인간 감독은 어떻게 구현해야 하나요?
개발자: 신용 평가는 고위험 AI로 분류되어 제14조가 적용됩니다. HITL, HOTL, HIC 중 선택해야 하는데, 신용 결정의 중요성을 고려하면 HITL이 적합합니다. 모든 대출 승인/거절을 인간이 최종 확인하는 거죠.
PM: 그러면 처리 속도가 너무 느려지지 않을까요?
개발자: HOTL로 타협할 수 있습니다. 신뢰도 85% 이상이면 자동 승인하고, 그 이하거나 경계 사례는 인간 검토로 넘기는 거죠. 단, 자동화 편향을 경고하는 인터페이스가 필수입니다. 그리고 반드시 시스템 중단 버튼을 제공해야 합니다.
면접관: EU AI Act의 인간 감독 세 가지 모델을 설명해주세요.
지원자: HITL은 Human-in-the-loop로, 모든 AI 결정에 인간 승인이 필요합니다. 의료 진단처럼 오류 비용이 높은 경우 사용합니다. HOTL은 Human-on-the-loop로, AI가 자동 결정하지만 인간이 실시간 모니터링하고 개입합니다. HIC는 Human-in-command로, 전체 시스템 수준에서 인간이 통제권을 가집니다.
면접관: 자동화 편향이란 무엇이고, 어떻게 방지하나요?
지원자: 자동화 편향은 인간이 AI 결정을 무비판적으로 수용하는 현상입니다. 제14조는 이를 방지하기 위해 감독자가 AI 능력과 한계를 이해하고, 출력을 독립적으로 해석할 수 있도록 지원할 것을 요구합니다. 실무적으로는 경고 메시지, 무작위 검증, 반대 근거 제시 등을 구현합니다.
리뷰어: 이 채용 AI 시스템에 중단 버튼이 없네요. EU AI Act 제14조 위반입니다.
작성자: 채용은 고위험 AI인가요? 법무팀에서 확인을 못 받았는데요.
리뷰어: 네, Annex III에 명시적으로 포함됩니다. 고용, 근로자 관리, 자영업 접근에 사용되는 AI는 모두 고위험입니다. halt_system 함수와 함께 모든 자동 결정을 검토/무효화할 수 있는 인터페이스가 필요합니다.
작성자: 알겠습니다. 감독자 대시보드도 추가하고, 모든 AI 추천에 신뢰도와 근거를 표시하겠습니다. 자동화 편향 경고도 넣을게요.

주의사항

형식적 감독 금지

인간 감독은 실질적이어야 합니다. 단순히 "승인" 버튼만 누르는 형식적 검토는 제14조 취지에 반합니다. 감독자가 AI의 입력, 로직, 출력을 실제로 이해하고 독립적 판단을 내릴 수 있어야 합니다. 이를 위해 감독자 교육, 적절한 업무량 배분, 충분한 검토 시간 보장이 필요합니다. 감독 품질 지표(override 비율, 검토 시간 등)를 모니터링해야 합니다.

자동화 편향 대응

AI 신뢰도가 높아지면 인간이 AI를 맹신하는 자동화 편향이 발생합니다. 이를 방지하려면: (1) AI 한계와 오류 가능성을 명시적으로 안내, (2) 무작위 샘플 검증 의무화, (3) 반대 증거나 대안을 함께 제시, (4) 정기적인 AI 성능 리포트 공유가 필요합니다. 제14조 제4항 d호는 이러한 조치를 명시적으로 요구합니다.

중단/무효화 권한 보장

모든 고위험 AI 시스템에는 즉시 중단 기능(kill switch)이 있어야 합니다. 긴급 상황에서 시스템을 멈추고, 이미 내려진 결정을 무효화할 수 있어야 합니다. 이 권한은 적절한 교육을 받은 감독자에게만 부여되어야 하며, 남용 방지를 위한 감사 로그가 필요합니다. 시스템 재개 시에는 이중 확인 절차를 거쳐야 합니다.

더 배우기