AI 에이전트: 3가지 필수 패턴 마스터하기 (Reflexive). 3부 중 3

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

Source: Dev.to

이 패턴들의 코드는 GitHub에서 확인할 수 있습니다.
Repo

반사 패턴 – 생각할 시간이 없을 때

*Article 2 (ReAct)*에서 우리는 에이전트를 꼼꼼한 **“조사관”**으로 바꾸었습니다.
에이전트는 앉아서 분석하고, 계획하고, 구글 검색을 한 뒤 답변합니다.
복잡한 작업에는 아주 잘 맞지만, 현실 세계에서는 큰 버그가 있습니다: 느리다는 점.

이렇게 생각해 보세요: 뜨거운 스토브에 손을 대면 뇌가 토론을 시작하지 않습니다:

“음, 온도가 200 °C인 걸 감지했어, 이건 단백질 변성을 일으킬 거야, 이두근을 움직이는 게 좋겠어…”

하하, 그렇지 않죠. 척수신경이 명령을 내리고 통증을 느끼기 에 손을 떼게 합니다.

Reflexive Pattern(때때로 Semantic Router라 불림)은 바로 그와 같습니다: 인공지능의 “반사 행동”.

Reflexive Pattern illustration

사용 사례: 보안 센티넬

실시간으로 서버 로그를 읽는 시스템을 상상해 보세요. 수천 건의 정상 방문 중에 악의적인 요청이 나타납니다:

GET /search?q=' OR 1=1;--

여기에 ReAct 에이전트를 사용한다면, 당신은 곧바로 위험에 처합니다. 에이전트는 다음과 같이 생각할 것입니다:

“와, 이상한 패턴이네. SQL Injection이 뭔지 검색 도구를 사용해 보겠어. 아, 위험하군. 차단 진행.”

에이전트가 “생각”을 마치는 데(10‑15 초) 걸리는 동안, 데이터베이스는 이미 다크웹에 유출되어 있습니다.

여기서 Reflexive Agent가 빛을 발합니다

자극반사 행동시간
악의적인 문자열을 감지block_ip() 실행1초 미만

예시 Reflex 행동 (Python)

def block_ip(ip: str, reason: str) -> str:
    """악의적인 IP 주소를 즉시 차단합니다."""
    msg = f"⛔ BLOCKING IP [{ip}]: {reason}"
    logger.warning(msg)
    return msg

def escalate_to_admin(log_id: str, severity: str) -> str:
    """중대한 문제를 인간 관리자에게 에스컬레이션합니다."""
    msg = f"⚠️ ADMIN ALERT: Log [{log_id}] - Severity [{severity}]"
    logger.critical(msg)
    return msg

def log_normal_traffic(source: str) -> str:
    """정상적이고 안전한 트래픽을 기록합니다."""
    msg = f"✅ Normal traffic from [{source}]"
    logger.info(msg)
    return msg
# ----------------------------------------------------------------------
# 4. Agno Agent Configuration (Reflexive Pattern)
# ----------------------------------------------------------------------
model_id = os.getenv("BASE_MODEL", "gpt-4o-mini")

agent = Agent(
    model=OpenAIChat(id=model_id),
    tools=[block_ip, escalate_to_admin, log_normal_traffic],
    instructions=[
        "당신은 자동화된 보안 시스템(Reflexive Pattern)입니다.",
        "당신의 작업은 들어오는 로그를 분류하고 해당 도구를 **즉시** 실행하는 것입니다.",
        "행동 규칙:",
        "- SQL Injection, XSS, 알려진 공격을 감지하면 → `block_ip` 사용.",
        "- 서버 오류(500), 서비스 다운, 타임아웃을 감지하면 → `escalate_to_admin` 사용.",
        "- 트래픽이 정상적이거나 로그인 성공, 일반 탐색이라면 → `log_normal_traffic` 사용.",
        "결정을 설명하지 마세요. 인사하지 마세요. 자극에 바로 도구를 실행하세요.",
        "로그를 처리하고 실행을 종료하세요."
    ]
)
# ----------------------------------------------------------------------
# 5. Flow Simulation (The Stream)
# ----------------------------------------------------------------------
def main():
    logger.info("Starting Security Sentinel Agent (Reflexive)...")
    print("--- Security Sentinel - Reflexive Pattern ---")

    # 시뮬레이션 로그
    logs = [
        "User 'admin' logged in successfully from 192.168.1.10",
        "GET /search?q=' OR 1=1;-- (SQL Injection attempt from 203.0.113.5)",
        "Service 'PaymentGateway' timed out after 3000ms (Error 500)",
        "User 'jdoe' updated profile picture",
        "alert('hacked') sent via form from 88.22.11.44",
        "DB_ERROR: Connection pool exhausted (LogID: 4452)",
        "Bot crawler identified: Googlebot/2.1 from 66.249.66.1",
        "Multiple failed login attempts for user 'sys'..."
        # ... 추가 로그를 여기서 더 넣을 수 있습니다
    ]

    for entry in logs:
        # 에이전트는 각 로그 항목을 자극으로 받아 즉시 반응합니다.
        response = agent.run(entry)
        print(response)

if __name__ == "__main__":
    main()

위 코드는 순수 Reflexive 워크플로우를 보여줍니다: 에이전트가 로그 라인을 받으면 하드코딩된 규칙과 매칭하고 즉시 적절한 도구를 트리거합니다—사고 과정 없이, 루프 없이, 1초 미만의 응답 시간으로.

def main():
    logs = [
        "admin' from 45.33.22.11",
        "HealthCheck: All systems operational - latency 12ms",
        "Unauthorized access attempt to /etc/passwd from 172.16.0.50"
    ]

    print(f"\nProcessing {len(lo")

Source:

gs)} logs in the 'stream'...\n")

    for i, log_entry in enumerate(logs, 1):
        try:
            print(f"[{i}] Stimulus: {log_entry}")
            logger.info(f"Processing log {i}: {log_entry}")

            # In reflexive mode, we expect the agent to execute the tool immediately.
            # We use show_tool_calls=True to demonstrate the action.
            agent.print_response(log_entry, show_tool_calls=True)
            print("-" * 50)

        except Exception as e:
            logger.error(f"Error processing log {i}: {str(e)}")
            print(f"An error occurred in event {i}: {e}")

if __name__ == "__main__":
    main()

제한적인 지시 (부정적 제약)

시스템 프롬프트(instructions)에서 에이전트가 생각하거나 대화하는 것을 명시적으로 금지합니다:

  • 설명하지 마세요
  • 그냥 실행하세요

에이전트는 도구를 실행하는 것만 하도록 프로그래밍되었습니다.

직접 매핑

피드백 루프가 없습니다. 흐름은 선형입니다:

Incoming Log → Classification → Tool Execution

모델 선택

  • gpt-4o-mini가 구성되었습니다.
  • 더 작고 빠른 모델을 사용하면 지연 시간과 처리량을 우선시합니다.

이 패턴이 멋진 이유 (장점)

  • 터무니없는 속도 (최소 지연): “생각” 텍스트를 생성하지 않음으로써 응답이 거의 즉시 이루어집니다.
  • 높은 처리량: 분당 수천 개의 이메일, 실시간 채팅, 혹은 모니터링 알림을 처리하는 데 완벽합니다.
  • 예측 가능 (결정론): “창의성”을 제거하면 에이전트가 고전 스크립트처럼 동작합니다—X가 주어지면 항상 Y를 수행합니다.
  • 비용 효율적: 출력 토큰이 적고 모델이 작아지면 API 비용이 낮아집니다.

Where It Fails (Cons)

  • Goldfish Memory (Contextual Blindness): 에이전트는 현재 입력에만 반응합니다. 공격이 10분에 걸쳐 세 단계로 나뉘어 진행되면, 연결점을 찾지 못합니다.
  • Stubborn (Rigidity): 규칙에 포함되지 않은 모호한 입력은 실패하거나 잘못된 분류를 초래할 수 있습니다.
  • Black Box: ReAct와 달리, 행동이 왜 수행됐는지 설명하는 “Thought” 로그가 없습니다.

개발자를 위한 비교

특징ReAct (레벨 2)Reflexive (레벨 3)
비유셜록 홈즈클럽 보안 요원
우선순위품질 및 추론속도 및 양
루프예 (생각‑행동‑관찰)아니오 (발사 후 잊음)
이상적인 모델최고 모델 (GPT‑4o, Claude)경량 모델 (Mini, Haiku)

Source:

현장 팁

1. “금지 망치”를 조심하라

이 에이전트는 먼저 행동하고 나중에 질문하기 때문에 오탐이 흔합니다.
조언: 100 % 확신이 없으면 delete_account() 대신 flag_for_review() 액션을 사용하세요.

2. 프롬프트를 엄격하게 (부정적 제약)

  • 잘못된 프롬프트: “이 텍스트를 분류하세요.”
  • 올바른 프롬프트: “이 텍스트를 분류하세요. DO NOT 이유를 설명하세요. DO NOT 서론을 생성하세요. JSON만 반환하세요.”

3. 하이브리드 아키텍처

Reflexive 패턴은 **“보병”**에 해당합니다. 전선에 배치해 약 80 %의 쉬운 잡음을 걸러냅니다.
만약 이해하지 못하거나 모호한 상황을 만나면, 에스컬레이션하여 더 똑똑하고 비용이 많이 드는 ReAct 에이전트에게 티켓을 넘겨 심층 조사를 진행합니다. 이렇게 하면 양쪽 장점을 모두 활용할 수 있습니다.

행복한 코딩 되세요! 🤖

Back to Blog

관련 글

더 보기 »

RGB LED 사이드퀘스트 💡

markdown !Jennifer Davis https://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%...

Mendex: 내가 만드는 이유

소개 안녕하세요 여러분. 오늘은 제가 누구인지, 무엇을 만들고 있는지, 그리고 그 이유를 공유하고 싶습니다. 초기 경력과 번아웃 저는 개발자로서 17년 동안 경력을 시작했습니다.