본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 24. 03:51

신뢰할 수 있는 AI 에이전트의 7가지 구성 요소 (프레임워크는 건너뛰세요)

요약

신뢰할 수 있는 AI 에이전트 시스템 구축을 위해 프레임워크 의존성을 줄이고 필수적인 7가지 구성 요소에 집중할 것을 제안합니다. 특히 백그라운드 자동화 환경에서는 LLM 호출을 최소화하고 결정론적 코드를 활용한 오케스트레이션이 중요함을 강조합니다.

핵심 포인트

  • 프레임워크보다 핵심적인 7가지 빌딩 블록에 집중해야 함
  • 에이전트는 단순한 LLM 호출이 아닌 결정론적 코드의 결합체임
  • 백그라운드 자동화는 인간의 개입 없이 오류를 관리해야 함
  • 지능 계층(Intelligence Layer) 외에는 모두 소프트웨어 엔지니어링 영역임
  • 추상화 계층을 최소화하여 유지보수 부담을 줄여야 함

제가 멀티 에이전트 시스템(multi-agent systems)을 구축하기 시작했을 때, 대부분의 엔지니어가 저지르는 실수를 범했습니다. 바로 적절한 프레임워크(framework)를 찾아 헤맨 것이었습니다. LangChain, AutoGPT, 그리고 수십 가지의 다른 옵션들을 평가했습니다. 각각의 옵션으로 프로토타입을 만들었습니다. 실제 문제를 해결하는 대신 도구(tooling)를 갖추는 데 몇 주를 허비했습니다.

모든 것이 명확해진 순간은 모든 것을 기본적인 API 호출로 되돌리고 스스로에게 질문했을 때였습니다. '내가 출시한 모든 에이전트에게 실제로 필요한 것이 무엇인가?' 답은 프레임워크가 아니었습니다. 그것은 일곱 가지 구성 요소(building blocks)였습니다. 병렬 작업 실행을 구동하는 Python 오케스트레이션 프레임워크(orchestration framework)부터 프로덕션 코드를 배포하는 SDLC 에이전트 하네스(agentic harness)에 이르기까지, 제가 구축한 모든 신뢰할 수 있는 에이전트 시스템에서 나타나는 패턴들이었습니다.

이러한 시스템을 구축하고 운영하며 배운 점은 다음과 같습니다. 최고의 AI 에이전트는 데모에서 보여주는 방식처럼 '에이전트적(agentic)'이지 않습니다. 그것들은 대부분 언어 모델(language models)에 대한 정밀하고 잘 정의된 범위의 호출을 포함하는 결정론적 코드(deterministic code)입니다.

두 가지 유형의 AI 시스템 (그리고 이것이 중요한 이유)

구성 요소를 살펴보기 전에, 이 구분이 매우 중요합니다.

AI 어시스턴트 (Human-in-the-Loop): 사용자가 직접 상호작용하며, 실시간으로 실수를 수정할 수 있고, 탐색을 기대합니다. 여러 번의 LLM 호출이 합리적입니다. Cursor를 이용한 페어 프로그래밍(pair programming)이나 채팅 인터페이스를 생각하면 됩니다.

백그라운드 자동화 (No Human Oversight): 오류가 조용히 누적됩니다. 지연 시간(latency)과 비용이 증폭됩니다. 모든 LLM 호출은 정당화될 필요가 있습니다. 이것이 프로덕션 에이전트(production agents)의 영역입니다.

제가 만든 Python 오케스트레이션 프레임워크와 지원 자동화 시스템은 모두 두 번째 범주에 속합니다. 이들은 인간이 모든 단계를 지켜보지 않고 실행됩니다. 이러한 제약 조건이 모든 아키텍처 결정의 형태를 결정했으며, 이것이 이 일곱 가지 구성 요소가 중요한 이유입니다.

# 백그라운드 자동화: LLM 호출을 최소화하고 격리함
def process_support_ticket(ticket_data: dict) -> dict:
    # 우선 결정론적 라우팅 수행 — 여기에는 LLM이 필요하지 않음
...

제가 출시하는 대부분의 것은 외부 셸(outer shell), 즉 결정론적 오케스트레이션 코드입니다. LLM은 하드코딩할 수 없는 추론(reasoning)을 처리합니다.

빌딩 블록 1: 지능 계층 (The Intelligence Layer)

이것이 유일한 실제 AI 구성 요소입니다. 그 외의 모든 것은 소프트웨어 엔지니어링입니다.

저는 Anthropic SDK를 직접 사용하며, 중간 추상화 계층을 두지 않습니다. API 표면(API surface)이 작고 안정적이기 때문입니다. 그 위에 쌓이는 모든 계층은 유지보수의 부담(maintenance liability)이 됩니다.

import anthropic

client = anthropic.Anthropic()
...

어려운 부분은 API 호출이 아닙니다. 그 주변의 모든 것, 즉 프롬프트(prompt)에 무엇을 넣을지, 돌아온 결과값을 어떻게 검증(validate)할지, 그리고 실패를 어떻게 처리할지입니다. 나머지 6개의 빌딩 블록이 정확히 이 부분들을 다룹니다.

빌딩 블록 2: 메모리 (상태 관리, Memory (State Management))

언어 모델은 상태가 없습니다 (stateless). 당신이 알려주지 않는 한, 모델은 이전 호출에 대해 아무것도 알지 못합니다. 메모리 관리는 전적으로 당신의 책임입니다.

Python 오케스트레이션 프레임워크에서, 저는 다단계 파이프라인(multi-step pipelines) 전반에 걸쳐 컨텍스트(context)를 명시적으로 유지합니다:

def chat_with_memory(conversation_history: list, new_message: str) -> tuple[str, list]:
    """오케스트레이션 단계 전반에 걸쳐 대화 상태를 유지합니다."""
    conversation_history.append({"role": "user", "content": new_message})
...

프로덕션 환경에서 대화 기록은 RAM이 아닌 데이터베이스에 저장됩니다. 각 메시지는 세션 ID(session ID)와 타임스탬프(timestamp)를 포함합니다. 토큰 수(Token counts)를 명시적으로 추적하여, 한계에 도달한 후가 아니라 도달하기 전에 컨텍스트 창(context windows)을 관리할 수 있도록 합니다.

참고:
SDLC 에이전트 하네스(agentic harness)에서 각 작업 워크트리(task worktree)는 자체적인 컨텍스트를 유지합니다: 사양 파일(spec file), 실행 중인 구현 보고서(implementation report), 그리고 git 히스토리(git history)입니다. 여기서 "메모리"는 인메모리(in-memory) 리스트가 아니라 디스크 상의 파일들입니다. 이를 통해 모든 단계를 감사(auditable)할 수 있고 재개(resumable)할 수 있습니다.

빌딩 블록 3: 도구 (외부 통합, Tools (External Integration))

도구는 에이전트가 세상에서 행동을 취할 수 있게 해줍니다: 파일을 읽거나, API를 호출하거나, 데이터베이스를 쿼리하는 것 등입니다. 도구는 강력하지만 비용이 많이 듭니다. 모든 도구 호출은 최소 두 번의 LLM 왕복(round trips)을 필요로 합니다.

제가 구축한 지원 자동화 (support-automation) 시스템은 도구를 보수적으로 사용합니다. 대다수의 티켓은 결정론적 (deterministically)으로 라우팅됩니다. 도구는 에이전트가 외부 정보 없이는 진정으로 진행할 수 없을 때만 활성화됩니다.

tools = [
    {
        "name": "lookup_account_status",
...

제가 따르는 규칙은 다음과 같습니다: 만약 도구 호출을 LLM이 프롬프트를 보기 전의 사전 쿼리 (pre-query)로 대체할 수 있다면, 대신 그렇게 하는 것입니다. 더 저렴하고, 빠르며, 결정론적 (deterministic)입니다.

구성 요소 4: 검증 (Structured Output)

비구조화된 (Unstructured) LLM 출력은 프로덕션 시스템에서 리스크 요인입니다. 해결책은 구조화된 응답 (structured responses)을 강제하고, 하류 (downstream) 코드가 이를 처리하기 전에 검증하는 것입니다.

Anthropic의 API는 도구 사용 (tool use) 패턴을 통해 구조화된 출력을 네이티브로 지원합니다. 저는 Pydantic을 사용하여 스키마 (schemas)를 정의하며, 이를 통해 타입 안정성 (type safety)과 검증 로직을 한 곳에서 관리할 수 있습니다.

from pydantic import BaseModel
from typing import Literal
import json
...

SDLC 하네스 (harness)에서 모든 구현 (implement) 단계는 구조화된 보고서를 반환합니다. 오케스트레이터 (orchestrator)는 해당 보고서를 산문 (prose)이 아닌 데이터로 읽습니다. 에이전트가 예상된 형태와 일치하지 않는 출력을 생성하면, 하류에서 조용히 오류가 발생하는 것이 아니라 빠르고 명확하게 실패합니다.


구조화된 출력 (Structured output)은 제가 에이전트 시스템에 적용한 신뢰성 개선 사항 중 가장 레버리지가 높은 단일 요소입니다. 이는 확률적인 텍스트 생성 (probabilistic text generation)을 하류 코드가 의존할 수 있는 결정론적인 데이터 추출 (deterministic data extraction)으로 전환합니다.

구성 요소 5: 제어 흐름 (Deterministic Routing)

이것은 제가 지원 자동화 시스템을 프로덕션화했을 때 가장 큰 차이를 만들어낸 패턴입니다. 제어권을 LLM에 넘겨주는 대신, LLM은 분류 (classification) 용도로 사용하고 라우팅은 결정론적인 코드 (deterministic code)가 수행하도록 합니다.

def handle_support_request(ticket: dict) -> str:
    """분류를 위한 한 번의 LLM 호출; 이후 결정론적 라우팅 수행."""
    classification = classify_ticket(ticket["body"])
...

핵심 통찰: LLM의 역할은 입력을 _이해(understand)_하는 것이지, 실행을 _주도(drive)_하는 것이 아닙니다. 의도(intent)가 분류되고 신뢰도(confidence)가 임계값(threshold)을 넘어서면, 나머지는 상태 머신(state machine)의 영역입니다.

SDLC 하네스(harness)에서 이 패턴은 엔드 투 엔드(end-to-end)로 실행됩니다. 각 파이프라인 단계는 이전 에이전트가 생성한 결과물을 분류(PASS / FAIL / PARTIAL)한 다음, 구현(implement), 테스트(test), 검토(review), 문서화(document) 또는 재시도(retry)로 결정론적 라우팅(deterministic routing)을 수행합니다. 어떤 에이전트도 자신의 다음 단계를 스스로 결정하지 않습니다.

빌딩 블록 6: 복구 (에러 핸들링 (Error Handling))

프로덕션 환경의 에이전트는 실패합니다. API 타임아웃(timeout)이 발생하거나, 속도 제한(rate limits)에 걸리거나, 모델이 잘못된 형식의 출력(malformed output)을 반환할 수 있습니다. 문제는 실패가 발생하는지 여부가 아니라, 시스템이 우아하게 성능 저하(degrade gracefully)를 처리하는지 여부입니다.

Python 오케스트레이션 프레임워크(orchestration framework)는 지수 백오프(exponential backoff)와 결합된 서킷 브레이커(circuit-breaker) 패턴을 사용합니다. 개별 작업의 실패가 연쇄적으로(cascade) 발생하지 않습니다.

import time
import logging
from typing import Optional
...

경고:
AI 경로를 구축하기 전에 폴백(fallback) 경로를 먼저 구축하십시오. LLM이 실패했을 때 시스템이 어떻게 작동하는지 설명할 수 없다면, 아직 제품을 출시할 준비가 되지 않은 것입니다.

빌딩 블록 7: 인간의 감독 (Human Oversight)

모든 결정이 완전히 자동화되어서는 안 됩니다. 고객에게 메시지를 보내거나, 중요한 데이터를 수정하거나, 되돌릴 수 없는 작업을 트리거하는 것과 같이 중대한 결과가 따르는 작업의 경우, 인간의 체크포인트(checkpoint)를 두는 것이 지연 시간(latency)을 감수할 만큼의 가치가 있습니다.

SDLC 하네스는 이를 검토(review) 단계에서 구현합니다. 에이전트가 작업을 구현하고 테스트한 후, 검토 단계에서 수락 기준(acceptance criteria)에 따라 결과를 평가합니다. 깔끔하게 통과(pass)되면 자동으로 계속 진행되며, 모호하거나 실패한 결과는 재시도(자동화)하거나 인간에게 에스컬레이션(escalate)합니다. 자동화는 규모(scale)를 처리하고, 인간은 책임(accountability)을 처리합니다.

from enum import Enum
from dataclasses import dataclass, field
from datetime import datetime
...

지원 자동화 시스템(support-automation system)에서 긴급도가 높은 에스컬레이션(escalations)은 사람의 검토 대기열(human review queue)로 전달됩니다. 에이전트가 답변 초안을 작성하면, 팀원이 전송하기 전에 이를 승인하거나 수정합니다. 자동화는 속도(velocity)를 제공하고, 사람은 중요한 지점에서 책임성(accountability)을 제공합니다.

모두 결합하기

이러한 구성 요소들은 결합되어 완전한 프로덕션 루프(production loop)를 형성합니다:

class ReliableAgent:
    def __init__(self):
        self.conversation_memory: dict[str, list] = {}
...

이 아키텍처가 가능하게 하는 것

제가 구축한 지원 자동화 시스템은 이 패턴을 사용하여 매일 대량의 요청을 처리합니다. 이를 운영하며 알게 된 점은 다음과 같습니다. 결정론적 라우팅 계층(deterministic routing layer)이 LLM 호출을 전혀 하지 않고도 대부분의 요청을 처리한다는 것입니다. 진정한 언어 이해가 필요한 경우—미묘한 불만 사항, 모호한 다중 질문, 규칙이 커버하지 못하는 예외 케이스(edge cases)—에만 모델 호출이 포함됩니다.

비용 대비 가치가 있는 곳에만 LLM 호출을 사용해야 한다는 이러한 제약은 전반적으로 더 나은 시스템 설계를 강제했습니다. "추론(reasoning)이 필요함"이 실제로 무엇을 의미하는지 정의해야 했기에 분류 계층(classification layer)이 더 정교해졌습니다. 모든 실패 모드(failure mode)를 고민해야 했기에 폴백 경로(fallback paths)가 더 완벽해졌습니다. 어떤 경로가 사용되고 왜 사용되는지 확인해야 했기에 관측성 계층(observability layer)이 필수적이 되었습니다.

SDLC 에이전트 하네스(agentic harness)도 동일한 방식으로 작동합니다. 각 파이프라인 단계는 대부분 결정론적인 오케스트레이션(orchestration) 코드입니다. 에이전트들은 특정 추론 작업으로 범위가 제한됩니다: 구현 작성, 테스트 결과 평가, 기준에 따른 검토 등입니다. 그 외의 모든 것은 파일 I/O, git 작업, 그리고 제어 흐름(control flow)입니다.

7가지 구성 요소

신뢰할 수 있는 프로덕션 에이전트를 구축하려면 다음 7가지가 모두 필요합니다:

  1. Intelligence (지능): 언어 모델(Language Model)에 대한 직접적인 API 호출 — 범위가 제한되고, 목적이 분명하며, 최소한으로 이루어져야 함
  2. Memory (메모리): 명시적인 상태 관리 (State Management) — 대화 기록, 세션 컨텍스트, 지속적 저장소 (Persistent Storage)
  3. Tools (도구): 외부 통합 (External Integrations) — 결정론적인 사전 가져오기 (Deterministic Pre-fetching)가 불가능한 경우에만 절제하여 사용
  4. Validation (검증): 스키마 강제(Schema Enforcement)를 통한 구조화된 출력 — 텍스트 생성을 데이터 추출(Data Extraction)로 변환
  5. Control Flow (제어 흐름): 분류(Classification)를 위한 LLM, 라우팅(Routing)을 위한 결정론적 코드 — 모델이 실행을 주도하게 두지 말 것
  6. Recovery (복구): 재시도 로직 (Retry Logic), 지수 백오프 (Exponential Backoff), 우아한 성능 저하 (Graceful Degradation) — 항상 폴백(Fallback)을 마련할 것
  7. Human Oversight (인간의 감독): 결과의 영향력이 큰 작업에 대한 승인 체크포인트 — 자동화는 규모(Scale)를 처리하고, 인간은 책임(Accountability)을 처리함

프레임워크는 필요 없습니다. Anthropic SDK를 직접 사용하여 깔끔하게 구현된 이러한 패턴들이 필요할 뿐입니다.

하나의 워크플로우(Workflow)부터 시작하세요. 분류 로직을 매핑하세요. 결정론적 라우팅을 구축하세요. LLM 없이는 정말로 라우팅할 수 없는 경우에만 LLM 호출을 추가하세요. 프레임워크는 이러한 패턴들로부터 나타날 것이며, 그것은 당신이 완전히 이해하고 있는 형태가 될 것입니다.


만약 지금 프레임워크를 평가하고 있다면, 잠시 멈추세요. 시스템 내의 실제 워크플로우 하나를 선택하여, 직접적인 SDK 호출과 이 7가지 빌딩 블록(Building Blocks)만을 사용하여 작성해 보세요. 그 과정을 통해 얻는 명확함이 이후의 모든 아키텍처 결정의 토대가 될 것입니다.

이 내용이 유용했다면, 저는 learn-agentic-ai.com에서 프로덕션 AI 및 에이전트 시스템(Agentic Systems) 구축에 대해 글을 쓰고 있습니다. 영어와 브라질 포르투갈어로 제공되는 실습 학습 경로도 포함되어 있습니다. 진짜 무언가를 함께 만들어 봅시다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0