Note: LLM을 쓰더라도 모델이 실행 흐름을 제어하지 않는 애플리케이션(단순 챗봇, 단일 턴 응답 등)은 엄밀히 말하면 에이전트 시스템이라기보다 그냥 LLM을 호출하는 프로그램에 가깝습니다.
안녕하세요, 블룸에이아이에서 AI 에이전트를 만들고 있는 엔지니어 지엠입니다.
저희 AI 팀은 챗봇·채팅상담 솔루션 ‘해피톡’에 도입된 AI 에이전트를 만들고 있습니다. 인간 상담사를 대신해 고객을 응대하는 AI 에이전트가 받는 질문들은 매우 다양하면서도 때로는 전문적입니다.
"상품이 아직 발송되지 않은 것 같은데 배송지 변경 가능한가요?"
"방문하려고 하는데 주차 가능한가요? 요금은 어떻게 되나요?”
"공유기의 mesh 기능은 어떻게 활성화해요? 활성화하면 wifi 속도 저하는 없나요?"
어떤 문의는 저장된 지식만 찾아 답하면 되고, 어떤 문의는 주문 시스템을 조회하거나 변경해야 하고, 또 어떤 문의는 두세 가지 핵심 내용이 한 문장에 섞여 들어옵니다. 이를 응대하기 위한 에이전트를 만들기 시작하면 거의 모든 팀이 같은 갈림길 앞에 섭니다.
"문제를 푸는 흐름을 우리가 미리 정해 줄 것인가, 아니면 모델이 스스로 정하게 둘 것인가."
이 글에서는 먼저 모든 에이전트 동작 아키텍쳐의 근본이 되는 ‘워크플로우’와 ‘에이전트’의 차이, 그리고 각 방식의 장단점과 트레이드 오프(Trade-off)를 짚어봅니다. 그다음 해피톡 AI는 어떤 길을 택했는지, 그리고 그 과정에서 어떤 시행착오를 겪으며 무엇을 배웠는지, 그리고 '가드레일 시스템'이라는 우리만의 강력한 무기를 어떻게 구축했는지 솔직하게 풀어보려 합니다.
아키텍처 분류의 출발점: 워크플로우 vs 자율 에이전트
LLM 에이전트 시스템을 구축하는 아키텍처 패턴은 많지만, 모든 분류의 출발점은 단 하나의 축, 바로 ‘제어권이 누구에게 있는가’입니다.
워크플로우(Workflow): LLM과 도구가 미리 정의된 코드 경로를 따라 정해진 순서대로 동작하는 시스템입니다. 길은 사람이 깔아 두고, 모델은 각 단계에서 맡은 일만 합니다.
자율 에이전트(Agent): LLM이 자신의 프로세스와 도구 사용을 스스로, 동적으로 결정하며 제어권을 쥐는 시스템입니다. 어떤 도구를 언제 쓸지, 다음에 무엇을 할지를 모델이 직접 판단합니다.
이 구분은 단순한 용어 문제가 아닌 핵심적인 아키텍처 결정입니다. 한쪽 끝에는 "고정된 길"이, 다른 쪽 끝에는 "스스로 길을 찾는 자율성"이 있고, 실제 제품은 대개 이 두 극단 사이의 스펙트럼 위 어딘가에 놓입니다.
한 줄로 요약하면 이렇습니다.
워크플로우는 잘 정의된 작업에서 예측 가능성과 일관성을 줍니다.
자율 에이전트는 유연성과 모델 주도의 의사결정이 필요할 때 우월합니다.
단, 자율 에이전트의 자율성에는 대가가 따릅니다. 더 높은 비용, 더 긴 지연 시간(Latency), 그리고 오류가 누적될 위험입니다. 자율 시스템은 본질적으로 "지연 시간과 비용을 더 나은 작업 성능과 맞바꾸는" 선택입니다.
그래서 아키텍처 설계의 황금률은 언제나 하나로 귀결됩니다.
"시스템을 복잡하게 만드는 것은, 성능 개선이 데이터로 확실히 입증될 때만 추가한다."
가능한 가장 단순한 구조에서 시작하고, 그것으로 부족할 때만 한 단계씩 자율성을 올리는 것이 정석입니다.
📌
그럼 먼저, 레일 위를 안전하게 달리는 '워크플로우'의 구체적인 패턴부터 살펴보겠습니다.
길을 미리 깔아 두는 방식 — 결정론적 워크플로우 패턴
사람이 직접 흐름을 설계하는 워크플로우 방식입니다. 이 패턴들은 공통적으로 다음과 같은 강력한 장점을 가집니다.
예측 가능성: 정해진 경로로만 움직이므로 돌발 행동이 없습니다.
추적 및 디버깅 용이성: 문제가 발생했을 때 어느 단계에서 터졌는지 즉시 짚어낼 수 있습니다.
일관된 결과: 동일한 입력에 대해 높은 확률로 동일한 퀄리티의 출력을 보장합니다.
1. 프롬프트 체이닝 (Prompt Chaining)
작업을 고정된 단계의 연속으로 쪼개, 각 LLM 호출이 이전 호출의 출력을 입력으로 받아 처리하는 방식입니다. 앞서 든 "배송지 변경" 문의를 이 방식으로 짠다면 대략 이런 파이프라인이 됩니다.
동작 방식: 각 단계를 "더 쉬운 하나의 작업"으로 만듭니다. 한 번에 다 처리하지 않고 나눠서 하므로 단계별 정확도가 올라갑니다.
장점: 단계마다 검증·로깅이 쉽고, 어디서 무엇이 잘못됐는지 즉시 짚입니다. 동작이 결정론적이라 재현성이 높습니다.
단점: 단계가 늘수록 지연 시간이 누적됩니다. 미리 깔아 둔 경로를 벗어나는 입력은 정상적으로 처리할 수 없습니다.
핵심 트레이드오프: 지연 시간을 정확도와 맞바꿉니다. 호출을 여러 번 쪼개 정확도를 얻는 대신 전체 응답은 느려집니다.
적합한 경우: 작업이 깔끔하게 고정된 하위 작업으로 분해될 때입니다.
2. 라우팅(Routing)
입력을 분류해서 그에 맞는 전용 후속 처리로 보냅니다. "배송 문의 → 주문 처리 경로", "제품 사용법 문의 → 지식 검색 경로"처럼 나누는 식입니다.
장점: 관심사를 분리할 수 있어 각 경로를 따로 최적화할 수 있습니다. 하나의 프롬프트에 모든 경우의 수를 작성하지 않기에 attention 분산 완화로 응답 품질이 향상됩니다.
단점: 분류가 틀리면 그 뒤 모든 처리가 어긋납니다. 라우팅 정확도가 시스템 전체의 천장이 됩니다.
적합한 경우: 명확히 구분되는 범주가 있고, 그 분류를 정확하게 할 수 있을 때입니다.
3. 병렬화(Parallelization)
여러 LLM 호출을 동시에 돌리고 결과를 모읍니다. 두 가지 변형이 있습니다.
1) 섹셔닝(Sectioning): 작업을 독립적인 하위 작업으로 쪼개 병렬 실행합니다. 예를 들어 답변을 만드는 모델과 그 답변을 안전성 관점에서 검열하는 모델을 따로 돌리는 식입니다.
2) 보팅(Voting): 같은 작업을 여러 번 돌려 다양한 출력을 얻은 뒤 투표합니다. "몇 표 이상이면 통과"라는 임계값으로 거짓 양성과 거짓 음성의 균형을 맞춥니다.
장점: 속도(병렬)와 신뢰도(다수의 관점)를 동시에 노립니다.
단점: 호출 수만큼 토큰 비용이 곱으로 늘고, 결과를 합치는 취합 로직이 따로 필요합니다.
적합한 경우: 하위 작업을 병렬로 나눌 수 있어 속도가 중요하거나, 여러 관점·여러 시도로 신뢰도를 높여야 할 때입니다.
4. 평가자-최적화자(Evaluator-Optimizer) — '재생성 루프'의 원형
한 LLM이 응답을 생성하고, 다른 LLM(또는 사람)이 그 응답을 평가합니다. 기준에 못 미치면 피드백을 주고 다시 생성시키고, 통과할 때까지 이 루프를 돕니다.
장점: 출력 품질을 명시적으로 끌어올립니다. "틀린 답을 거르고 다시 쓰게 하는" 메커니즘이 구조 안에 박혀 있습니다.
단점: 매 반복마다 호출이 늘어 비용·지연이 커집니다. 평가 기준이 모호하면 루프가 수렴하지 않습니다.
적합한 경우: 평가 기준이 분명하고, 반복적인 다듬기가 측정 가능한 개선을 줄 때입니다.
📌
Note: 이 패턴은 그 자체로는 워크플로우로 분류되지만, 핵심 아이디어인 [생성 → 평가 → 재생성 루프]는 뒤에서 다룰 자율 에이전트의 가드레일과 그대로 이어집니다. 사실 저희가 택한 방식의 심장부가 바로 이 루프입니다.
모델이 스스로 길을 찾는 방식 — 자율 에이전트 패턴
이제 반대쪽입니다. 사람이 정해둔 고정된 경로를 따르는 워크플로우와 달리, 여기서는 LLM이 직접 무엇을 검색하고 어떤 도구를 호출할지, 다음에 무엇을 할지를 동적으로 결정합니다.
1. ReAct — 자율 루프의 정석
ReAct는 추론(Reasoning)과 행동(Acting)을 번갈아 엮는 방식입니다.
모델이 "생각하고 → 도구를 쓰고 → 결과를 관찰하고 → 다시 생각하는" 과정을 목표에 도달할 때까지 반복하며 접근법을 동적으로 조정합니다.
예컨대 "배송지 변경" 문의가 들어오면, 에이전트는 스스로 다음과 같이 판단하며 길을 만들어 갑니다.
"먼저 주문 상태를 조회하자 → 아직 발송 전이네 → 그럼 배송지 변경 도구를 호출하자 → 완료됐으니 안내하자”
장점: 경직된 고정 경로보다 사람처럼 유연하게 문제를 풉니다. 중간 관찰 결과에 따라 즉석에서 방향을 바꿉니다. 외부 정보와 맞물려 동작하므로, 머릿속 추론만으로 답을 지어내는 환각(Hallucination)과 오류 전파를 상당히 완화합니다.
단점: 경로가 매번 달라져 예측·재현이 어렵습니다. 잘못된 중간 판단이 다음 단계로 누적될 수 있고, 헛다리를 짚는 검색에 빠지기도 합니다.
핵심 트레이드오프: 유연성을 얻는 대신, 예측 가능성과 디버깅 용이성을 내어줍니다.
📌
Note: 자율 루프의 필수 요건: 종료 조건
ReAct 같은 자율 에이전트의 본질은 "종료 조건에 도달할 때까지 도는 루프"입니다. 시스템이 무한 루프에 빠지지 않도록 보통 다음과 같은 기준을 세워 멈추게 합니다.
모델이 더 이상 도구를 호출하지 않을 때(할 일을 다 했다고 판단한 표준 구현)
특정한 구조화된 출력이 나왔을 때
오류가 발생했거나, 설정한 최대 턴(Turn) 수에 도달했을 때 (폭주를 막는 필수 안전장치)
2. 계획 후 실행(Plan-and-Execute)
먼저 전체 작업을 작은 하위 작업으로 나누는 계획을 세우고, 그다음 그 계획에 따라 하위 작업들을 차례로 수행합니다.
장점: 다양한 작업을 복합적, 순차적으로 처리해야 하는 복잡한 요청에서 큰 그림을 먼저 잡아 일관성을 유지합니다. 매 스텝마다 즉흥적으로 판단하는 것보다 정확하고 효율적으로 실행합니다.
단점: 초기 계획이 틀리면 전체가 흔들려 재계획(Replan)이 필요합니다.
적합한 경우: 단계가 많고 순서 의존성이 큰 복합 작업입니다.
3. 리플렉션(Reflection) — 자가 개선을 위한 피드백 루프
에이전트가 자신의 결과에 대한 피드백을 검토해 반영하고(Reflect), 교훈을 기억하며 다음 시도의 의사결정을 개선합니다.
모델 가중치를 다시 학습시키는 게 아니라, 순수하게 언어적 피드백만으로 스스로를 강화한다는 점이 특징입니다.
💡
앞서 살펴본 '평가자-최적화자(Evaluator-Optimizer)'가 "한 출력물의 즉석 재생성"에 가깝다면, '리플렉션'은 시도와 시도 사이에 교훈을 누적해 나간다는 점에서 한 발 더 나아간 형태입니다.
4. 오케스트레이터-워커(Orchestrator-Workers)
중앙 LLM(오케스트레이터)이 작업을 동적으로 분해해 여러 워커 LLM에게 나눠 맡기고, 그 결과들을 종합하는 멀티 에이전트 패턴입니다.
병렬화와의 결정적 차이: 유연성입니다. 워크플로우의 '병렬화' 패턴에서는 하위 작업이 이미 정해져 있지만, 여기서는 하위 작업을 사전에 정의할 수 없고 오케스트레이터가 그때그때 입력을 보고 동적으로 결정합니다.
적합한 경우: 무엇을 어떻게 쪼갤지 사전에 알 수 없는, 입력마다 형태가 달라지는 복잡한 작업입니다.
🔎 멀티 에이전트로 확장할 때의 두 가지 선택지 — Manager vs Decentralized
작업의 규모가 커지면 에이전트를 여러 개로 나누어 협업시키는 '멀티 에이전트' 구조를 고민하게 됩니다. 이때 오케스트레이션은 크게 두 갈래로 나뉩니다.
Manager 패턴 (도구로서의 에이전트): 중앙 매니저 에이전트가 전문화된 서브 에이전트들을 '도구 호출(Tool Call)' 형태로 불러 조율합니다. 시스템의 통제와 종합이 한 곳(매니저)에 모입니다.
Decentralized 패턴 (핸드오프): 동등한 위치의 에이전트들이 각자의 전문 분야에 따라 작업을 서로에게 토스(Handoff)합니다. 인계는 기본적으로 한 방향 전달로 이루어집니다.
⚠️
Note: 멀티 에이전트로 가기 전에 단일 에이전트의 역량을 최대로 끌어올려야 합니다.
에이전트를 늘리면 그만큼 시스템의 복잡성과 통신 오버헤드가 기하급수적으로 따라옵니다. 단일 에이전트가 복잡한 지시를 제대로 따르지 못하거나, 프롬프트 한계로 도구를 계속 잘못 고를 때 — 바로 그때가 에이전트를 쪼개야 하는 시점입니다.
한눈에 보는 트레이드오프 총정리
지금까지 살펴본 두 패러다임의 핵심 특징과 트레이드오프를 표로 요약하면 다음과 같습니다.
기준 | 워크플로우 (고정 경로) | 자율 에이전트 (동적 경로) |
|---|---|---|
예측 가능성 / 일관성 | 높음 (재현성 높음) | 낮음 |
유연성 | 낮음 (경로 이탈 시 경직) | 높음 |
지연 시간 / 비용 | 상대적으로 낮음 (단계 수에 비례) | 높음 (가변적, 대체로 김) |
오류 누적 위험 | 낮음 | 높음 |
디버깅 난이도 | 쉬움 | 어려움 |
강점이 나오는 곳 | 잘 정의된 작업 | 유연성·모델 주도 판단이 필요한 작업 |
어느 한쪽이 항상 옳은 것은 아닙니다. 해결하려는 문제의 성격이 답을 정합니다. 흐름을 완벽히 예측할 수 있다면 워크플로우가, 매번 형태가 달라지는 문제라면 자율 에이전트가 유리합니다.
그렇다면 프로덕션 레벨에서 다양한 고객사의 요구사항을 처리해야 하는 해피톡은 어떤 아키텍처를 선택했을까요?
해피톡 AI의 선택: 처음부터 자율 에이전트로
블룸 AI팀은 해피톡의 AI 에이전트를 처음부터 ‘자율 에이전트’ 방식으로 설계했습니다. 고정된 파이프라인을 거쳐 옮겨 온 것이 아니라, 문제의 성격상 그쪽이 맞다고 판단했기 때문입니다.
이유는 도메인의 특성에 있습니다.
예측하기 어려운 고객 문의의 형태: 고객 문의는 매번 형태가 다릅니다. 도입부의 ‘공유기 mesh 설정 질문’처럼 ‘사용법 + 부작용’이 한 문장에 섞이기도 하고, ‘배송지 변경’처럼 조회 결과에 따라 다음 행동이 갈리기도 합니다. 무엇을 어떤 순서로 처리해야 할지를 사람이 전부 미리 짜 두기는 어렵습니다.
고객사마다 가변적인 빌드 환경: 게다가 해피톡은 고객사가 직접 에이전트를 구성하는 제품입니다. 고객사마다 가이던스와 추가 지침을 다르게 쓰고, 도구를 다르게 할당하고, 지식을 다르게 등록합니다. 검색에는 자체 구축한 지식 검색 시스템(RAG)을 쓰고, 행동에는 내부 API와 외부 시스템 연동 API, 그리고 고객사가 등록한 API까지 붙습니다.
즉 ‘상황’과’해결 방식’이 고객사마다 다릅니다. 이런 환경에서 고정 파이프라인은 애초에 성립하기 어렵고, 모델이 주어진 도구와 지식 안에서 스스로 길을 찾는 자율 방식이 자연스러운 선택이었습니다.
자율성의 그림자: 우리가 실제로 겪은 문제들
앞서 자율성에는 대가가 따른다고 말씀드렸듯이, 해피톡 AI팀도 많은 문제에 부딪혔습니다. 자율권을 넉넉히 준 에이전트는 종종 기대를 배신했습니다. 대표적으로 이런 일들이 있었습니다.
에이전트에게 제공한 도구에 포함되지 않은 도구를 임의로 만들어 호출했습니다. 제공한 도구들의 이름을 흉내 내어 존재하지 않는 도구를 호출하더군요.
검색을 하지 않거나, 검색 결과에 없는 정보로 답변했습니다. 생성형 AI의 특징인 환각(Hallucination)입니다.
도구를 호출하지도 않고 "처리했다" 혹은 "처리하겠다"고 답변했습니다. 행동 없이 거짓 보고를 합니다.
시스템 지침에 정의된 "할 수 있는 일"의 범위를 넘어, 할 수 없는 일도 할 수 있다고 답변했습니다.
상담 도메인에서 이런 오류는 단순한 품질 저하가 아니라 곧바로 고객 신뢰의 문제로 직결됩니다. 우리 팀은 두 갈래로 대응했습니다. 하나는 시스템 지침을 강화하는 것, 다른 하나는 제공한 도구 목록에 없는 도구 호출을 코드에서 정적으로 검사하고 그 결과를 피드백 루프로 되돌리는 것이었습니다.
이 피드백 루프가 다음에 이야기할 가드레일의 출발점이 됐습니다.
가드레일 피드백 루프: 자율성에 안전벨트 채우기
가드레일의 핵심 철학은 하나입니다.
“단일 방어로는 충분하지 않으며, 여러 겹의 검사를 겹쳐 쌓을 때 비로소 견고해진다.
저희는 학계와 업계에서 검증된 '평가자-최적화자(Evaluator-Optimizer)' 패턴과 '리플렉션(Reflection)' 메커니즘을 융합하여 해피톡만의 사후 가드레일(Post-guardrail) 시스템을 구축했습니다. LLM이 응답을 완료할 때마다 가드레일이 그 결과를 두 겹으로 감사하도록 구성한 것입니다.
Layer 1) 규칙 기반 검사 (코드): 에이전트에게 제공한 도구 목록에 없는 도구를 호출했는지를 코드에서 정적으로 잡아냅니다. 모델이 도구를 지어내는 문제를 값싸고 확실하게 차단하는 계층입니다.
Layer 2) LLM 심판 (의미 검사): 규칙만으로는 잡히지 않는 의미적 오류는 LLM 심판이 봅니다. 이때 심판에게는 컨텍스트 전체(시스템 지침, 도구 스키마, 대화 메시지, 에이전트의 마지막 응답)를 모두 넘겨 다음을 감사합니다.
시스템 지침을 위반했는가
컨텍스트에 없는 정보로 답했는가 (사전학습 지식에 기댄 추정이나 할루시네이션)
제공된 도구 목록에 없거나 부적절한 도구를 호출했는가
감사를 통과하면 그대로 고객에게 전달합니다. 통과하지 못하면 위반 사유를 다음 메시지로 주입해 에이전트에게 재생성을 요청(피드백 루프)합니다.
이 과정은 정해진 한도까지 반복하고, 그래도 기준을 못 넘기면 사전에 정의된 안전 응답으로 폴백(Fallback)합니다.
자율성과 안전은 이렇게 양립합니다. 에이전트에게 운전대를 맡기되, 매 응답마다 차선 이탈을 점검하고, 끝내 안 되면 비상 제동을 하는 안전장치를 걸어야 합니다.
설계하며 부딪힌 두 가지 고민
위 구조는 이상적으로 보이지만, 단점들도 있기에 팀 내에서 많은 논의가 있었습니다.
고민 1. 응답 품질 vs 실시간성
응답이 끝난 뒤에 검사하는 사후 가드레일에는 분명한 비용이 있습니다. 검사를 위해 답변이 완성된 다음에야 고객이 응답을 볼 수 있으므로, 토큰 단위로 점진적으로 채워지는 스트리밍 UX가 불가능해집니다. 실시간 응대가 생명인 음성(전화 등) 에이전트에는 적용 자체가 어렵죠.
그래서 처음에는 사후 가드레일을 빼고 진행했습니다. 그런데 장기간 PoC를 진행하며 가드레일 적용 전후의 품질을 비교해 보니, 최종 응답 품질에 큰 차이가 났습니다. 비교 자료를 앞에 두고 저희가 내린 결론은 분명했습니다.
"빠르게 응답을 전달하는 것보다, 정확하게 동작하는 것이 더 중요하다."
상담이라는 도메인에서는 이 우선순위가 흔들리면 안 된다고 봤습니다.
고민 2. 가드레일의 처리 속도와 비용
속도와 비용만 따지면, 보통은 모델의 응답만 가드레일에 넣습니다. 입력이 작을수록 빠르고 싸니까요.
하지만 해피톡은 고객사가 가이던스, 추가 지침, 도구 할당, 지식 등록을 자유롭게 설정하는 것이 제품의 특징입니다. 에이전트의 동작이 이 설정들과 깊게 맞물려 있기 때문에, 응답만 떼어 봐서는 그 응답이 정상인지 판단할 수 없었습니다.
여러 방식을 테스트한 끝에, 정상 동작 여부를 제대로 확인하려면 컨텍스트 전체를 가드레일에 전달해 검증해야 한다는 결론에 이르렀습니다. 입력이 커지는 만큼 속도와 비용 부담은 늘지만, 이 제품에서 가장 큰 가치는 신뢰도입니다. 그래서 속도와 비용이 크게 증가하지 않는 선에서 컨텍스트 전체를 검증하도록 다듬었습니다.
두 고민 모두 결국 하나의 질문에만 답하면 답이 나오는 문제였습니다. 무엇을 가장 중요한 가치로 둘 것인가. 저희에게 그 답은 신뢰도였고, 나머지 설계는 핵심 가치를 지키면서 약점을 보완하기 위한 선택이었을 뿐입니다.
마치며
정리하면, 저희가 택한 것은 "자율성과 통제 중 하나"가 아니라 "자율성을 주되, 가드레일로 그 결과를 검증하도록 하는 구조"입니다.
매번 형태가 다른 고객 문의와, 고객사마다 다른 도구·지식·지침이라는 환경에서는 모델이 스스로 길을 찾는 자율성이 필요했고, 그 자율성이 일으키는 환각·도구 오용·범위 이탈은 매 응답을 감사하고 재생성하는 가드레일 루프로 막았습니다. 그리고 그 모든 결정의 바탕에는 "빠름보다 정확함"이라는 우선순위가 있었습니다.
에이전트 아키텍처에 절대적인 정답은 없습니다. 빠르게 진화하는 분야인 만큼, 문제의 성격과 가장 지키고 싶은 가치가 무엇이냐에 따라 답은 달라집니다.
저희의 선택과 시행착오가, 비슷한 갈림길 앞에 선 분들께 작게나마 참고가 되면 좋겠습니다.
참고 자료 References