본문 바로가기
프로그램 (PHP,Python)

개발 생산성은 올리고, 보안 리스크는 줄이는 AI 에이전트 설계 전략

by 날으는물고기 2025. 12. 3.

개발 생산성은 올리고, 보안 리스크는 줄이는 AI 에이전트 설계 전략

728x90

AI 에이전트 시스템을 이렇게 쪼개서 보시면 편합니다

AI 에이전트 환경을 보안/운영 관점에서 보면 보통 이렇게 4 레이어입니다.

  1. 상호작용 레이어
    • 사용자, 다른 서비스, 스케줄러(n8n, 크론 등)와 만나는 인터페이스
    • 예: Slack Bot, Webhook Endpoint, CLI, 배치 잡
  2. 에이전트 오케스트레이션 레이어
    • LLM 호출, 프롬프트, 메모리(State), 도구 선택, 재시도, 피드백 루프 등
    • 예: LangChain, Semantic Kernel, ADK, MCP 기반 툴 호출
  3. 도구/시스템 연동 레이어
    • 실제 일을 하는 영역: DB, Vault, Kubernetes, Wazuh, SIEM, 사내 API, n8n 워크플로우 등
  4. 보안/운영 거버넌스 레이어
    • 인증/인가, 로그, 모니터링, 승인(approval), 롤백, 감사(audit)

아래에서 이야기하는 State, 플로우 제어, 에러 처리, 평가, 도구 정의, 책임 분리는 전부 이 4개 레이어에 걸쳐서 적용된다고 보시면 됩니다.

State 저장 방식 – “텍스트 + 메타데이터”를 1급 시민으로 취급하기

1. 왜 중요하냐?

AI 에이전트는 “사용자 의도”와 “컨텍스트”를 자연어로 주고 받습니다.
이걸 전통 방식대로

approved = true만 남기면,
무엇이 왜 승인되었는지”를 잃어버립니다.

→ 보안/감사 관점에서 설명 가능성(Explainability), 사후 분석이 매우 중요합니다.

2. 권장 저장 형태 (예시)

예: “RDP 로그인 이벤트를 에이전트가 평가하고 처리”하는 경우

{
  "event_id": "rdp-2025-12-03-00123",
  "source": "RDP_AUDIT",
  "raw_text": "로그인 실패 3회 발생, 계정: user01, IP: 10.0.1.23",
  "llm_interpretation": {
    "risk_level": "medium",
    "reasoning": "동일 IP에서 짧은 시간 내 실패 3회. 브루트포싱 가능성 있으나,
      다른 고위험 패턴 없음.",
    "suggested_actions": [
      "해당 IP에 대해 10분간 모니터링 강화",
      "추가 실패 발생 시 알림 전송"
    ]
  },
  "decision": {
    "action": "monitor",
    "approved_by": "ai-agent:threat-analyst",
    "timestamp": "2025-12-03T09:10:20+09:00"
  },
  "context": {
    "tenant": "Pages in Korea",
    "env": "prod",
    "tags": ["RDP", "LOGIN", "SECURITY"]
  }
}

포인트

  • raw_text: 원본 메시지(자연어 / 로그)를 그대로 보관
  • llm_interpretation.reasoning: LLM이 왜 그렇게 판단했는지 텍스트로 남기기
  • decision.action: 실제 행동 (block/monitor/ignore 등)
  • context에 테넌트/환경/태그를 붙여서, 나중에 SIEM/Elasticsearch에서 검색 가능

3. 보안/운영 체크포인트

  • 민감정보(계정, IP, 세션 ID 등) 포함 시 마스킹 정책 정의
  • 로그/State 저장소(예: ES, Postgres)에 대해 접근 권한 분리
  • State 스키마에 “reasoning” 필드를 반드시 포함 (설명 가능성 확보)
  • 장기 보존 vs 요약 처리 정책 (장기적으로는 요약된 Audit 레코드만 유지 등)

플로우 제어 권한 위임 – “하드코딩 플로우” vs “에이전트 주도 플로우”

1. 전통 방식의 문제

전통 자동화

sequenceDiagram
User->>System: 요청
System->>ServiceA: call
ServiceA->>ServiceB: call
ServiceB-->>System: response
System-->>User: 결과

AI 에이전트 환경

  • “언제, 어떤 도구를, 어떤 순서로, 얼마나 많이 쓸지”가 미리 고정되지 않음
    • 먼저 RDP 로그 조회 →
    • 심각해 보이면 Wazuh 연관 이벤트 조회 →
    • 비정상적이면 Slack으로 알림 + 티켓 생성 →
    • 사용자가 “False Positive”라고 답하면 케이스 닫기

2. 현실적인 설계 패턴

상위 레벨은 “목표(Goal)”만 정의

“지난 1시간 동안의 RDP 로그인 실패 로그를 분석해서,
의심스러운 IP와 계정을 요약하고, 필요 시 티켓을 생성해라.”

이를 프롬프트/에이전트 설정에 다음처럼 넣습니다.

goal: >
  입력으로 받은 로그인 이벤트를 분석하여
  위험도가 medium 이상인 케이스는 TheHive 티켓을 생성하고,
  나머지는 요약 리포트만 작성하라.

tools:
  - name: get_rdp_events
  - name: create_thehive_ticket
  - name: send_slack_message
constraints:
  - never delete or modify any data
  - for high-risk actions, ask for human approval via Slack

2) 세부 플로우는 에이전트에게 위임하되, 가드레일로 통제

  • “어떤 도구를 사용해도 되지만,
    • delete_*류 도구는 무조건 사람 승인 필요
    • 외부 HTTP 호출은 특정 도메인만 허용
    • 민감도 높은 프로젝트는 읽기 전용 API만 사용”

3. 보안/운영 체크포인트

  • 에이전트가 사용할 도구 목록을 화이트리스트 방식으로 제한
  • 도구별로 “읽기 전용 / 변경 / 삭제 / 외부 전송” 구분 태그
  • 위험도가 높은 도구 호출은 무조건 Human-in-the-loop (아래 6번에서 자세히)
  • 플로우 제어는 LLM에게 위임하되, 최종 액션 전 승인/검토 단계 삽입

오류 처리 & 회복 – “에러도 입력이다”

1. 전통 개발 vs 에이전트 개발

  • 전통: 예외 발생 → 트랜잭션 롤백 → 에러 응답 → 끝
  • 에이전트
    • 도구 호출 실패 → 왜 실패했는지 자연어로 설명
    • 재시도할지? 다른 경로를 쓸지? 사용자에게 질문할지? →
    • 이것 자체가 “새로운 입력”

2. 패턴 예시 (n8n / 워크플로우와 결합)

예: “RDP 로그인 기록 → n8n Webhook → 레지스트리 기록 + Slack 알림”

    1. Webhook 호출 실패
      • 에이전트가 받은 응답: HTTP 500, "DB connection timeout"
      • 에이전트 행동
        • 1차: 30초 후 재시도
        • 2차 실패: Slack에 “Webook 장애, 수동 확인 필요” 전송 + Wazuh 로그 기록
    2. 레지스트리 기록 실패 (권한 문제)
      • 에이전트는 이 에러 메시지를 LLM에 입력으로 전달
      • 프롬프트
        다음 오류 메시지를 분석하고,
        재시도가 의미 있는지 판단해줘. 권한 문제로 보이면 사람에게 알려라.

3. 예시 코드(의사 코드)

def call_tool_with_retries(tool, args, max_retries=2):
    errors = []
    for attempt in range(max_retries):
        result = tool(args)
        if result.success:
            return result
        errors.append(result.error_message)

    # 여기서 에이전트/LLM에게 에러 히스토리를 통째로 넘겨서 다음 행동을 판단
    llm_input = {
        "tool": tool.name,
        "args": args,
        "errors": errors
    }
    next_action = ask_llm_how_to_recover(llm_input)
    return next_action

4. 체크포인트

  • 단순 try/except 로 끝내지 말고, 에러 메시지를 LLM 입력으로 전달
  • 재시도 정책(횟수, 간격)을 명시적으로 설정
  • 재시도 후에도 실패 시 Slack / SIEM / Wazuh에 장애 이벤트 기록
  • 민감/중요 작업은 “재시도 무제한”이 아닌 명시적 한계 설정

검증 및 품질 평가 – 유닛 테스트 + Eval + 로그 기반 분석

1. 유닛 테스트의 한계

  • AI 에이전트는 출력이 확률적
  • “정확히 같은 문장을 반환해야 한다” 식 테스트는 거의 의미 없음

2. 실무에서 쓸 수 있는 평가 지표

  1. Task-level 성공률 (Pass Rate)
    • 예: “1천 개의 RDP 이벤트 중 실제 고위험을 몇 % 잘 잡았나”
    • “티켓 생성 기준에 맞게 동작했는지”를 수동/반자동으로 검증
  2. 반복 실행 안정성
    • 동일 입력에 대해 3~5회 실행 시,
    • 의사결정(티켓 생성/미생성)이 일정 수준 일관적인지
  3. 출력 품질 평가(Judge LLM / 룰 기반)
    • 예: Slack에 올리는 요약 보고서에 대해
    • “핵심 항목(IP, 계정, 시간, 조치)이 모두 포함됐는지”를 룰/LLM로 체킹
  4. 중간 단계 로그 기반 분석
    • 어떤 도구를 몇 번 호출했는지
    • 에러 발생 패턴
    • Human approval 비율

3. 예시 – 간단한 Eval 레코드 구조

{
  "eval_id": "rdp-2025-12-03-batch1",
  "input_batch_size": 1000,
  "pass_rate": 0.87,
  "metrics": {
    "precision": 0.82,
    "recall": 0.91
  },
  "notes": "고위험 IP는 잘 잡았으나 특정 내부망 IP에 false positive 다수.",
  "suggested_rule_updates": [
    "내부망 10.0.0.0/8 은 별도 기준으로 평가",
    "야간 근무자 계정 화이트리스트 관리 필요"
  ]
}

4. 체크포인트

  • “에이전트가 만든 결과”에 대해 일정 기간 샘플링 + 수동 리뷰
  • Pass Rate, Precision/Recall 등을 대략이라도 정의
  • 오탐/미탐 케이스를 수집해서, 프롬프트/룰/도구를 개선하는 루프 구축

API/도구 정의 명확화 – “도구가 곧 권한 경계”

1. 에이전트에게 보여지는 세계 = 도구 목록

도구는 곧 에이전트의 손과 입입니다. 이걸 정교하게 설계하면 보안 경계를 자연스럽게 만들 수 있습니다.

좋은 예

def delete_user_by_uuid(uuid: str):
    """
    지정한 UUID를 가진 사용자를 비활성화하고,
    관련 세션을 모두 종료한 후, 감사 로그에 기록합니다.

    ⚠️ 고위험 작업입니다.
    - 반드시 human approval을 거친 후에만 호출해야 합니다.
    - 사유(reason)를 필수로 입력받아야 합니다.
    """

나쁜 예

def dangerous_op(s: str):
    # 내부적으로 뭔가 많이 함 (삭제/변경/외부 전송 등)
    pass

2. 민감도 수준에 따라 도구 분리

예: Vault + Kubernetes 시크릿 관리 + AI 자동화 연동

  • get_secret_readonly(key) : 읽기 전용, 특정 네임스페이스만
  • create_secret(namespace, key, value) : 신규 생성 (제한된 네임스페이스)
  • rotate_db_password(db_name) : 고위험, 반드시 승인 필요
300x250

이렇게 행위별로 명확히 분리된 도구를 에이전트에 노출하고,
“일반 도구 세트”와 “관리자 전용 도구 세트”를 나누는 것이 좋습니다.

3. 체크포인트

  • 도구 이름은 “동사 + 목적어” 형태로 구체적으로 (예: suspend_user_session)
  • 도구 설명(docstring)에 위험도/전제조건/로깅정책/승인 필요 여부 명시
  • “만능 관리 API”는 에이전트에 직접 노출하지 말고, 에이전트용 래퍼(wrapper) 도구로 쪼개서 제공

책임 분리 & 거버넌스 – 사람 승인, 로그, 롤백 구조

1. Human-in-the-loop 패턴

패턴 예: 고위험 작업은 항상 Slack 승인

  1. 에이전트가 rotate_db_password("billing-db")가 필요하다고 판단
  2. 바로 실행하지 않고, 승인 메시지를 Slack에 전송
    {
      "type": "approval_request",
      "action": "rotate_db_password",
      "target": "billing-db",
      "reason": "의심스러운 로그인 시도 감지, 세션 무효화를 위해 비밀번호 교체 제안",
      "risk_level": "high",
      "requester": "ai-agent:sec-ops",
      "expires_at": "2025-12-03T10:00:00+09:00"
    }
  3. 보안팀/운영자가 Slack에서 “Approve / Reject” 버튼 클릭
  4. 승인 결과를 Webhook으로 에이전트에게 전달 → 그때 실제 도구 실행

2. 감사 로그(Audit Trail)

고위험/중요 작업에 대해 최소한 다음 필드는 남겨야 합니다.

  • 누가: ai-agent:sec-ops + 실제 승인자 ID
  • 언제: timestamp
  • 무엇을: 도구 이름, 파라미터 (민감 값은 마스킹)
  • 왜: LLM reasoning + 사람이 입력한 사유
  • 결과: success/fail, 후속 조치

3. 롤백 전략

  • RDP / Wazuh / SIEM 연동과 같은 읽기/알림 위주의 워크플로우는 롤백 부담 적음
  • Vault/Kubernetes/DB 패스워드 변경처럼 상태 변화가 있는 경우:
    • 이전 값 백업(예: 시크릿 이전 버전 저장)
    • 일정 시간 내 자동 복원 옵션
    • 문제가 발생하면 “AI 에이전트가 수행한 변경만 되돌리는” 절차 문서화

4. 체크포인트

  • 고위험 작업 목록 정의 (계정 차단, 시크릿 변경, 방화벽 정책 변경 등)
  • 각 항목에 대해 “AI가 직접 수행 가능 / 승인 필요 / 금지” 구분
  • 승인/거부 로그를 SIEM/Wazuh에 전송해 중앙 집계
  • 롤백 가능한 변경만 에이전트에 맡긴다는 원칙 유지

3가지 예시 워크플로우에 적용해보기

1. RDP 로그인 기록 → n8n Webhook → 레지스트리 기록 + Slack 알림

설계 관점

  • State
    • 각 로그인 이벤트에 대해 raw_event + llm_interpretation + decision 저장
  • 플로우
    • n8n Webhook 오류 → 에이전트 재시도 + Slack 장애알림 + Wazuh에 장애 로그
  • 보안
    • 레지스트리(HKLM\SOFTWARE\Symantec) 기록은 읽기/쓰기 권한 분리
    • 에이전트는 “로그 기록 도구”만 가지고, 실제 레지스트리 액세스는 별도 서비스가 수행

체크포인트

  • RDP 이벤트에 포함된 계정/호스트 정보 마스킹 규칙
  • 에이전트의 판단이 잘못되어도 계정 차단/락은 사람 승인 필요
  • 실패한 Webhook/레지스트리 기록은 별도 큐에 넣고 재처리 가능하게 설계

2. “OCR → PDF → Slack 전송 → Wazuh 연동 → SIEM 기록” 워크플로우

설계 관점

  • State
    • 파일 메타데이터, OCR 결과 텍스트, 분류 결과(예: 중요도, 문서 유형) 저장
  • 플로우
    • 각 단계(OCR, 전송, 연동, 기록)의 실패를 별도 이벤트로 저장
    • 에이전트가 재시도 or 관리자에게 “재처리 필요” 알림

보안 관점

  • OCR된 텍스트가 개인정보/민감정보 포함 가능 →
    • 민감도 분류 도구(PII Detector 등)와 연계
    • 민감도가 높을 경우, Slack 채널 제한 / 암호화 저장 / 접근 로그 강화

체크포인트

  • OCR 결과 저장소에 대한 암호화/접근통제
  • SIEM에 저장되는 필드 중 민감한 것 마스킹
  • “에이전트가 문서 내용을 요약해서 Slack에 보내는 경우” → 민감도 체크 후 전송

3. Vault + Kubernetes 비밀 관리 + AI 자동화 연동

설계 관점

  • 에이전트가 직접 Vault root token을 아는 구조는 절대 금지
  • 에이전트는 오직 제한된 정책을 가진 Vault role로만 접근
  • “시크릿 조회”와 “시크릿 변경/회전” 도구를 분리

보안 관점

  • 시크릿 변경 요청은 반드시 Human approval
  • 변경 로그는
    • Vault audit 로그
    • 에이전트 내부 audit
    • SIEM/Wazuh로 전송
  • 변경된 시크릿이 실제로 반영되었는지(Kubernetes에 적용) 헬스체크 도구 별도 구현

체크포인트

  • Vault 정책에 에이전트 전용 role 정의 (최소 권한)
  • 시크릿 rotate 작업은 항상 “이전 값 백업 + 롤백 절차” 포함
  • 에이전트가 시크릿 값을 그대로 Slack/로그에 찍지 않도록 프롬프트/도구 레벨에서 차단

“개발 생산성 증가” 이후에 반드시 붙여야 할 것들

AI 에이전트로 개발/운영 자동화가 잘 되기 시작하면, 그 다음 단계는 반드시 “거버넌스와 보안”입니다.

  1. State 설계
    • 자연어 + 메타데이터 + reasoning을 구조화해서 저장
  2. 플로우 위임 + 가드레일
    • 세부 플로우는 에이전트에, 경계와 제한은 사람이
  3. 에러를 입력으로 처리
    • 실패를 중단이 아니라 “피드백 → 재시도/우회/알림”으로 활용
  4. Eval 기반 품질 관리
    • Pass Rate, 오탐/미탐 분석, 중간 로그를 기반으로 개선 루프
  5. 도구를 경계로 하는 권한 설계
    • 도구 이름/설명/위험도/범위를 명확히 하고 화이트리스트 방식으로 노출
  6. Human-in-the-loop + Audit Trail
    • 고위험 작업은 승인 + 로깅 + 롤백 구조를 반드시 포함
728x90
그리드형(광고전용)

댓글