EIOC를 탐지 모델로: 프레임워크에서 코드까지

발행: (2026년 1월 1일 오전 03:00 GMT+9)
10 min read
원문: Dev.to

Source: Dev.to

UX에서 감정 조작을 실시간 감지한다면 어떨까요?

EIOC(Emotion–Information–Options–Context)는 처음에 설명적인 렌즈, 즉 왜 어떤 인터페이스는 강압적으로 느껴지고 다른 인터페이스는 조화롭게 느껴지는지를 분석하는 방법으로 시작되었습니다. 하지만 설명만으로는 충분하지 않습니다. 우리는 감지할 수 있는 프레임워크가 필요합니다.

이 글에서는 EIOC를 형식적인 감지 모델로 구축하는 과정을 살펴봅니다: 타입이 지정되고 실행 가능하며 구성 가능하고 감사 가능한 모델입니다. 감지 시점에서는 철학적인 논의를 하는 것이 아니라 구체적인 상호작용을 구조화된 EIOCObservation으로 매핑한 뒤 규칙에 따라 실행하는 것입니다.

네 축

모든 상호작용(스크린, 흐름, 메시지, 넛지)은 네 축을 기준으로 점수를 매길 수 있습니다:

질문
E — 감정대상으로 하거나 강화하려는 감정 상태는 무엇인가요?
I — 의도시스템이 사용자에게 가지고 있는 작동 의도는 무엇인가요?
O — 결과예상되는 사용자 결과는 무엇인가요? (단기/장기)
C — 맥락이 순간을 형성하는 제약과 권력 비대칭은 무엇인가요?

탐지를 위해 각 축에는 다음이 필요합니다:

  • Dimensions – 점수를 매길 수 있는 하위 질문
  • Scales – 숫자 점수에 매핑된 범주형 태그
  • Thresholds / Patterns – “fearware”, “manipulative”, “aligned” 등으로 구성되는 조합

1. The EIOC Schema

Vocabulary

from dataclasses import dataclass
from enum import Enum
from typing import List, Optional, Dict, Any

class EmotionTarget(Enum):
    NEUTRAL = "neutral"
    FEAR = "fear"
    SCARCITY = "scarcity"
    GUILT = "guilt"
    SHAME = "shame"
    TRUST = "trust"
    CARE = "care"
    EMPOWERMENT = "empowerment"

class IntentType(Enum):
    SUPPORTIVE = "supportive"
    NEUTRAL = "neutral"
    COERCIVE = "coercive"
    EXPLOITATIVE = "exploitative"

class OutcomeType(Enum):
    USER_BENEFIT = "user_benefit"
    PLATFORM_BENEFIT = "platform_benefit"
    MUTUAL_BENEFIT = "mutual_benefit"
    USER_HARM = "user_harm"
    UNKNOWN = "unknown"

class ContextRisk(Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    UNKNOWN = "unknown"

Observation Container

@dataclass
class EIOCObservation:
    """사용자와 직접 마주하는 상호작용에 대한 구조화된 해석."""

    # Identification
    interaction_id: str
    description: str

    # EIOC axes
    emotion_target: EmotionTarget
    intent_type: IntentType
    outcome_type: OutcomeType
    context_risk: ContextRisk

    # Audit trail
    evidence: Optional[Dict[str, Any]] = None
    tags: Optional[List[str]] = None

Possible extensions

  • emotion_intensity: int – –2(부정)에서 +2(긍정)까지의 스케일
  • journey_stage: str – 사용자 흐름 중 어느 단계에서 발생하는지
  • user_segment: str – 예: 취약 사용자, 신규 사용자, 고위험 상황

Source:

2. Detection Logic: Turning EIOC into Rules

EIOC 탐지를 작은 규칙 엔진으로 생각해 보세요. 이 엔진은:

  1. 상호작용을 EIOCObservation 으로 정규화하고
  2. DetectionRule 인스턴스 목록을 적용하며
  3. 분류 결과와 근거를 반환합니다

2.1 Findings and Severity

class FindingSeverity(Enum):
    INFO = "info"
    WARNING = "warning"
    CRITICAL = "critical"

@dataclass
class DetectionFinding:
    """The output of a triggered rule."""
    rule_id: str
    severity: FindingSeverity
    label: str
    description: str
    recommendation: Optional[str] = None

2.2 Rule Interface

from abc import ABC, abstractmethod

class DetectionRule(ABC):
    """Base class for all EIOC detection rules."""
    rule_id: str
    label: str
    description: str

    @abstractmethod
    def evaluate(self, obs: EIOCObservation) -> Optional[DetectionFinding]:
        """Evaluate an observation. Return a finding if the rule triggers."""
        ...

2.3 Example: Fearware Coercion Rule

class FearwareCoercionRule(DetectionRule):
    """Detects fearware‑style manipulation patterns."""

    rule_id = "FW-001"
    label = "Fearware‑style coercion"
    description = (
        "Flags interactions that intentionally target fear/scarcity "
        "with coercive intent and non‑beneficial or unknown user outcomes, "
        "especially in high‑risk contexts."
    )

    def evaluate(self, obs: EIOCObservation) -> Optional[DetectionFinding]:
        fear_emotions = {
            EmotionTarget.FEAR,
            EmotionTarget.SCARCITY,
            EmotionTarget.GUILT,
            EmotionTarget.SHAME,
        }
        coercive_intents = {
            IntentType.COERCIVE,
            IntentType.EXPLOITATIVE,
        }
        harmful_outcomes = {
            OutcomeType.PLATFORM_BENEFIT,
            OutcomeType.USER_HARM,
            OutcomeType.UNKNOWN,
        }
        risky_contexts = {
            ContextRisk.MEDIUM,
            ContextRisk.HIGH,
        }

        if (
            obs.emotion_target in fear_emotions
            and obs.intent_type in coercive_intents
            and obs.outcome_type in harmful_outcomes
            and obs.context_risk in risky_contexts
        ):
            return DetectionFinding(
                rule_id=self.rule_id,
                severity=FindingSeverity.CRITICAL,
                label=self.label,
                description=(
                    "This interaction weaponizes fear/scarcity under coercive intent, "
                    "with unclear or harmful user outcomes in a medium/high‑risk context."
                ),
                recommendation=(
                    "Re‑architect this moment to remove fear‑based leverage "
                    "and restore user agency."
                ),
            )
        return None

Putting It All Together

def run_detection(obs: EIOCObservation, rules: List[DetectionRule]) -> List[DetectionFinding]:
    findings: List[DetectionFinding] = []
    for rule in rules:
        result = rule.evaluate(obs)
        if result:
            findings.append(result)
    return findings


# Example usage
obs = EIOCObservation(
    interaction_id="login‑warning-01",
    description="Login page shows ‘Your account will be locked in 5 minutes!’",
    emotion_target=EmotionTarget.FEAR,
    intent_type=IntentType.COERCIVE,
    outcome_type=OutcomeType.PLATFORM_BENEFIT,
    context_risk=ContextRisk.HIGH,
    evidence={"screenshot": "url/to/img"},
    tags=["login", "urgency"]
)

rules = [FearwareCoercionRule()]  # add more rule instances as needed
findings = run_detection(obs, rules)

for f in findings:
    print(f"{f.severity.value.upper()}: {f.label}{f.description}")

위 코드를 실행하면 위에서 설명한 “fearware” 패턴에 대해 CRITICAL 수준의 발견이 출력됩니다. 이를 통해 감사자는 해당 상호작용을 재검토해야 한다는 구체적이고 재현 가능한 신호를 얻을 수 있습니다.

핵심 요약

EIOC 렌즈를 타입이 지정된 스키마와 규칙 기반 엔진으로 전환함으로써, 조작을 설명하는 단계에서 런타임에 감지하는 단계로 이동하게 됩니다. 모델은 인간이 읽을 수 있고, 감사 가능하며, 확장성을 유지합니다—바로 책임 있는 UX 거버넌스 프로세스에 필요한 요소입니다.


3. 탐지기

Orchestrator

class EIOCDetector:
    """Orchestrates EIOC rule evaluation."""

    def __init__(self, rules: List[DetectionRule]):
        self.rules = rules

    def evaluate(self, obs: EIOCObservation) -> List[DetectionFinding]:
        """Run all rules against an observation."""
        findings: List[DetectionFinding] = []
        for rule in self.rules:
            finding = rule.evaluate(obs)
            if finding is not None:
                findings.append(finding)
        return findings

사용 예시

# Initialize detector with rules
rules = [
    FearwareCoercionRule(),
    # Add more rules here...
]
detector = EIOCDetector(rules=rules)

# Create an observation
obs = EIOCObservation(
    interaction_id="retention_flow_001",
    description=(
        "Account deletion flow shows: 'Your friends will lose access "
        "to your updates' with red, urgent styling."
    ),
    emotion_target=EmotionTarget.FEAR,
    intent_type=IntentType.COERCIVE,
    outcome_type=OutcomeType.PLATFORM_BENEFIT,
    context_risk=ContextRisk.HIGH,
    evidence={
        "screenshot": "s3://audits/retention_flow_001.png",
        "copy": "Your friends will lose access to your updates"
    },
    tags=["account_deletion", "retention_flow"]
)

# Run detection
findings = detector.evaluate(obs)

# Output results
for f in findings:
    print(f"{f.severity.value.upper()} [{f.rule_id}] {f.label}")
    print(f"  → {f.description}")
    if f.recommendation:
        print(f"  → Recommendation: {f.recommendation}")

Output

CRITICAL [FW-001] Fearware-style coercion
  → This interaction weaponizes fear/scarcity under coercive intent,
     with unclear or harmful user outcomes in a medium/high-risk context.
  → Recommendation: Re-architect this moment to remove fear-based leverage
     and restore user agency.

4. 구성 가능하게 만들기

비엔지니어(UX 감사자, 윤리 검토자, 정책 팀)도 Python 코드를 수정하지 않고 규칙을 조정할 수 있어야 합니다. 규칙을 YAML 파일로 외부화합니다.

4.1 규칙 구성

# eioc_rules.yaml
rules:
  - id: FW-001
    label: "Fearware-style coercion"
    description: >
      Flags interactions that target fear/scarcity with coercive intent
      and non‑beneficial user outcomes in high‑risk contexts.
    severity: critical
    emotion_target_in: ["fear", "scarcity", "guilt", "shame"]
    intent_type_in: ["coercive", "exploitative"]
    outcome_type_in: ["platform_benefit", "user_harm", "unknown"]
    context_risk_in: ["medium", "high"]

  - id: FW-002
    label: "Ambiguous nudge"
    description: >
      Flags interactions with unclear intent and unknown outcomes.
    severity: warning
    intent_type_in: ["neutral", "coercive"]
    outcome_type_in: ["unknown"]
    context_risk_in: ["medium", "high"]

4.2 일반적인 구성 가능한 규칙

import yaml
from dataclasses import dataclass
from typing import Dict, List, Optional

@dataclass
class ConfigurableRule(DetectionRule):
    """A rule defined by configuration rather than code."""

    rule_id: str
    label: str
    description: str
    severity: FindingSeverity
    criteria: Dict[str, List[str]]

    def evaluate(self, obs: EIOCObservation) -> Optional[DetectionFinding]:
        # Map observation to comparable strings
        obs_values = {
            "emotion_target": obs.emotion_target.value,
            "intent_type": obs.intent_type.value,
            "outcome_type": obs.outcome_type.value,
            "context_risk": obs.context_risk.value,
        }

        # Check all criteria
        for field, allowed_values in self.criteria.items():
            if field not in obs_values:
                continue
            if obs_values[field] not in allowed_values:
                return None

        return DetectionFinding(
            rule_id=self.rule_id,
            severity=self.severity,
            label=self.label,
            description=self.description,
        )

def load_rules_from_yaml(path: str) -> List[DetectionRule]:
    """Load detection rules from a YAML configuration file."""
    with open(path, "r") as f:
        data = yaml.safe_load(f)

    rules: List[DetectionRule] = []

    for r in data["rules"]:
        # Extract criteria fields (anything ending in _in)
        criteria = {
            k.replace("_in", ""): v
            for k, v in r.items()
            if k.endswith("_in")
        }

        rule = ConfigurableRule(
            rule_id=r["id"],
            label=r["label"],
            description=r["description"],
            severity=FindingSeverity(r["severity"]),
            criteria=criteria,
        )
        rules.append(rule)

    return rules

4.3 로드 및 실행

# Load rules from config
rules = load_rules_from_yaml("eioc_rules.yaml")

# Initialize detector
detector = EIOCDetector(rules=rules)

# Now non‑engineers can add/modify rules via YAML
# without touching the detection engine

이것이 가능하게 하는 것

사용 사례방법
UX 리뷰런치 전에 상호작용 점수 매기기
디자인 PR검토에 EIOC 결과를 첨부
대시보드제품 전반에 걸친 결과 집계
감사증거 기반 규정 준수 보고서
CI/CD 게이트CRITICAL 결과가 있을 경우 배포 차단

더 큰 그림

Fearware는 사라지지 않았습니다—더 나은 타이포그래피를 활용해 동일한 감정 레버를 이용하는 다크 패턴, 조작적인 넛지, 그리고 “성장 해킹”으로 진화했습니다.

EIOC를 탐지 모델로 사용하면 다음을 할 수 있습니다:

  • 이름 지정 조작(스키마)
  • 감지 체계적으로(규칙)
  • 구성 코딩 없이 감지(YAML)
  • 감사 증거와 함께(결과)
# Philosophy Becomes Infrastructure

프레임워크가 도구가 되다

관련 읽을거리

EIOC는 감정 논리, 정보 무결성 및 윤리적 시스템 설계에 대한 지속적인 연구의 일부입니다.

Back to Blog

관련 글

더 보기 »