ACT 실행 단계

AI 에이전트란? 챗봇을 넘어 스스로 도구를 쓰는 AI의 원리와 한계

AI 에이전트란? 챗봇을 넘어 스스로 도구를 쓰는 AI의 원리와 한계

AI 에이전트(AI agent)는 한 번 시키면 알아서 끝까지 처리해 오는 일꾼입니다. '한 번 물으면 한 번 답하고 멈추는 챗봇'과 달리, 사람이 던진 목표 하나를 받으면 그 목표에 이를 때까지 스스로 여러 단계를 계획하고 실행하며 필요한 도구를 골라 씁니다. 속에서 도는 것은 대규모 언어 모델(LLM, 방대한 글을 읽고 다음에 올 말을 예측하도록 학습한 AI)이고, 에이전트는 이를 바탕으로 만든 실행 시스템입니다.

한눈에 보기

  • AI 에이전트는 목표를 받으면 생각하고, 도구를 쓰고, 결과를 보고 다시 생각하는 과정을 스스로 되풀이해 일을 끝까지 처리합니다.
  • 이 루프를 떠받치는 부품은 계획, 도구, 메모리 세 가지이고, 속에서 도는 것은 여전히 다음 말을 확률로 예측하는 언어 모델입니다.
  • 단계가 길어질수록 작은 실수가 쌓이므로, 결제나 메일 발송처럼 되돌릴 수 없는 일 앞에는 사람이 확인하는 관문을 둡니다.

이런 상황을 떠올려 보세요. 작은 여행사에서 일하는데 아침마다 "예약한 여행 일정에 바뀐 게 있나요?"라는 문의가 스무 통씩 쌓입니다. 답장 하나를 쓰려면 예약 관리 화면에서 예약 번호를 찾고, 항공사 사이트에서 항공편 시각이 바뀌었는지 조회하고, 바뀌었으면 안내 문구를 붙여 답장을 씁니다. 챗봇에게 "답장 써 줘"라고 하면 그럴듯한 문장은 주지만, 실제 항공편 상태는 모르니 결국 사람이 세 곳을 오가야 합니다. 에이전트는 이 오가는 일을 대신합니다. 예약을 찾아보고, 항공편을 조회하고, 결과에 맞춰 답장 초안을 만든 뒤 보내기 전에 담당 직원에게 확인을 받습니다.

이 글은 에이전트가 안에서 어떻게 움직이는지를 차근차근 푸는 해설입니다. 언어 모델이 어떤 단계를 거쳐 에이전트로 발전했는지, 에이전트를 실제 서비스로 만들 때 무엇이 필요한지 같은 큰 그림은 AI 에이전트와 에이전틱 서비스 글에서 다룹니다.

챗봇과 에이전트는 어디서 갈리나

먼저 구분을 또렷이 해 두겠습니다. 챗봇은 보통 한 번의 요청에 한 번 답하고 멈춥니다. 반면 에이전트는 '이 주제로 자료를 조사해 표로 정리해 줘' 같은 목표를 받으면 곧바로 답하고 끝내지 않습니다. 검색을 돌리고, 결과를 읽고, 부족하면 다시 찾고, 정리한 뒤 표로 만드는 여러 단계를 스스로 이어 갑니다.

그러나 겉모습이 화려해도 에이전트 역시 챗봇처럼 매 순간 그럴듯한 다음 말을 예측하는 언어 모델로 움직입니다. 달라진 것은 모델의 본질이 아니라, 모델을 감싸고 여러 번 돌리는 바깥의 제어 구조입니다. 이 점을 놓치면 에이전트를 '스스로 생각하는 지능'으로 오해하기 쉽습니다.

그래서 에이전트를 제대로 이해하려면 두 축을 같이 봐야 합니다. 하나는 도구를 호출하는 능력, 다른 하나는 그 호출을 사람이 매번 지시하지 않아도 스스로 되풀이하는 자율성입니다. 이 두 가지가 결합하면서 AI는 묻는 말에 답하는 데서 그치지 않고 일을 직접 처리할 수 있게 됐습니다.

챗봇은 질문 하나에 답 하나로 끝나고, 에이전트는 목표를 받아 계획, 검색, 분석, 실행, 결과 검증을 거쳐 최종 보고까지 이어 가는 차이를 나란히 보여 주는 그림

왜 지금 에이전트가 등장했나

에이전트라는 발상 자체는 인공지능 연구에서 오래된 것입니다. 다만 최근 몇 년 사이에 실제로 쓸 만해진 이유가 있습니다. 언어 모델의 추론 능력이 올라가면서, 자연어로 된 목표를 잘게 쪼개고 다음에 무엇을 할지 스스로 계획하는 일이 어느 정도 가능해졌기 때문입니다.

언어 모델 단독의 한계도 등장의 배경입니다. LLM은 학습 시점에 갇힌 지식만 갖고 있고, 계산이나 최신 정보 조회에 약하며, 무엇보다 '자신 있게 틀리는' 환각(hallucination, 사실이 아닌 내용을 그럴듯하게 지어내는 현상)에서 자유롭지 못합니다. 이 약점을 모델 바깥의 도구로 메우자는 흐름이 자연스럽게 이어졌습니다. 검색 엔진, 계산기, 코드 실행기, 데이터베이스를 모델이 직접 부르게 하면, 모델은 모르는 것을 찾아보고 계산은 계산기에 맡길 수 있습니다.

여기에 프롬프트 기법의 발전이 결정적으로 맞물렸습니다. 답을 내기 전에 풀이 과정을 한 줄씩 말로 적게 하는 사고 사슬(chain-of-thought)과, 추론과 행동을 번갈아 수행하는 ReAct 계열의 기법이 나오면서, 모델이 '무엇을 할지 판단하고 → 실제로 실행하고 → 결과를 보고 다시 판단하는' 절차를 언어로 표현할 길이 열렸습니다.

요약하면 에이전트는 세 흐름이 만나는 자리에서 태어났습니다. 추론이 강해진 언어 모델, 그 약점을 메우는 외부 도구, 그리고 이 둘을 반복 절차로 엮는 프롬프트·제어 기법입니다. 어느 하나만으로는 부족했고, 셋이 만나면서 '스스로 여러 단계를 처리하는 실행기'가 현실이 됐습니다.

사고-행동-관찰이 스스로 도는 자율 루프

에이전트가 수행하는 '여러 단계'의 중심에는 하나의 반복 구조가 있습니다. 생각하고(Reason), 행동하고(Act), 결과를 관찰하고(Observe), 다시 생각하는 사이클입니다. 추론(Reasoning)과 행동(Acting)의 앞 글자를 합쳐 흔히 ReAct라 부릅니다(Yao et al., 2022).

구체적으로 보겠습니다. 먼저 '생각' 단계에서 모델은 지금 상황과 목표를 놓고 다음에 무엇을 해야 할지 언어로 궁리합니다. '이 정보를 찾으려면 검색을 해야겠다' 같은 판단이 여기서 나옵니다. 이어 '행동' 단계에서 모델은 실제 도구를 호출합니다. 검색어를 만들어 검색 도구에 넘기는 식입니다. 그러면 '관찰' 단계에서 도구가 돌려준 결과가 모델 앞에 놓입니다. 모델은 그 결과를 읽고 다시 '생각'으로 돌아가, 목표에 닿았는지 아니면 한 바퀴 더 돌아야 하는지 판단합니다.

비서에게 출장 준비를 맡기면

이 루프를 일상 장면으로 한 번 끝까지 따라가 보겠습니다. 비서에게 "다음 주 목요일 부산 거래처 미팅이 있으니 출장 준비해 줘"라고 맡겼다고 해 봅시다.

  • 생각 1: 미팅 시각부터 알아야 기차 시간을 정할 수 있습니다. 일정표를 먼저 봅니다.
  • 행동 1: 일정표를 엽니다. 관찰 1: 목요일 오후 2시, 거래처 사무실은 부산역에서 택시로 20분.
  • 생각 2: 1시 30분 전에는 부산역에 닿아야 합니다. 오전 기차를 찾습니다.
  • 행동 2: 기차 예매 사이트를 조회합니다. 관찰 2: 9시 30분 열차는 매진, 10시 열차에 자리가 있고 12시 40분 도착.
  • 생각 3: 10시 열차면 시간이 맞습니다. 다만 표를 사면 돈이 나가니, 결제 전에 상사에게 확인을 받습니다.
  • 행동 3: "10시 열차로 예매할까요?"라고 묻습니다. 관찰 3: "좋아요."
  • 생각 4: 예매를 마치고, 일정표에 기차 시간과 거래처 주소를 적은 뒤 끝났다고 보고합니다.

좋은 비서는 이렇게 한 번 시키면 알아서 여러 번 확인하고 움직입니다. 매진이라는 관찰을 보고 계획을 바꾼 점, 돈이 나가는 일 앞에서 멈춰 물어본 점이 핵심입니다. 에이전트도 똑같은 모양으로 움직입니다. 다만 일정표와 예매 사이트 자리에 컴퓨터 프로그램으로 된 도구가 들어가 있을 뿐입니다.

챗봇과 갈리는 지점이 바로 여기입니다. 챗봇에게도 한 번씩 물으면 비슷한 판단을 들을 수 있지만, 에이전트는 이 사이클을 사람이 매번 시키지 않아도 스스로 여러 번 돌립니다. 목표를 잘게 쪼개고, 언제 어떤 도구를 쓸지 스스로 정하고, 몇 바퀴를 돌지도 스스로 판단합니다. 자율성은 새 원리가 아니라 익숙한 루프에 '반복'과 '스스로'를 얹은 것입니다.

여기서 흔한 오해 하나를 짚어 두겠습니다. 모델이 '생각한다'는 말은 인간처럼 의식적으로 사고한다는 뜻이 아닙니다. '생각' 단계 역시 확률로 그럴듯한 문장을 이어 붙이는 예측일 뿐입니다. 다만 그 예측을 절차 형태로 강제하니, 결과적으로 계획을 세우고 실행하는 것처럼 보이는 행동이 나옵니다. 이 차이를 분명히 해야 뒤에 나오는 한계를 제대로 이해할 수 있습니다.

사용자 질문이 들어오면 생각(Thought), 행동(Action), 관찰(Observation)을 일이 끝날 때까지 되풀이한 뒤 최종 답을 내는 ReAct 루프 그림

계획·도구·메모리: 에이전트를 이루는 세 기둥

루프가 돌아가려면 이를 떠받치는 부품이 필요합니다. 에이전트의 구조를 뜯어보면 대개 계획, 도구, 메모리라는 세 기둥이 보입니다. 언어 모델은 이 세 기둥을 지휘하는 두뇌 역할을 합니다.

첫째, 계획(planning)입니다. 큰 목표를 실행 가능한 작은 단위로 쪼개는 능력입니다. '보고서를 써 줘'라는 목표는 그대로는 실행할 수 없습니다. 자료 조사 → 개요 작성 → 초안 → 검토처럼 순서 있는 작은 일로 나눠야 도구를 붙일 수 있습니다. 앞서 본 사고 사슬처럼 풀이 과정을 차례로 적게 하는 기법이 이 계획 단계를 돕습니다.

둘째, 도구(tools)입니다. 모델이 자기 힘으로 못 하는 일을 맡기는 창구입니다. 웹 검색, 계산기, 코드 실행, 파일 읽기·쓰기, 외부 API(프로그램끼리 정해진 방식으로 요청과 답을 주고받는 창구) 호출 등이 도구가 됩니다.

셋째, 메모리(memory)입니다. 여러 단계를 이어 가려면 지금까지 한 일과 관찰한 결과를 기억해야 합니다. 짧게는 한 작업 안에서 대화 맥락을 유지하는 단기 기억이 있고, 길게는 과거 경험을 벡터 임베딩(글의 뜻을 숫자 목록으로 적은 좌표)으로 저장해 두었다가 필요할 때 뜻이 가까운 것을 찾아오는 장기 기억이 있습니다. 출장 예에서 비서가 "이 상사는 창가 자리를 좋아한다"를 기억해 두는 것이 장기 기억에 해당합니다. 검색 증강 생성(RAG, 답하기 전에 관련 문서를 찾아 붙여 주는 방식)에서 쓰는 임베딩·벡터 검색 기술이 여기서 그대로 쓰입니다.

언어 모델을 가운데 두고 웹 검색, 계산기, 문서 검색 도구를 부르며 대화 기록 메모리를 함께 써서 최종 답을 만드는 에이전트 구조 그림

도구를 언제 어떤 것으로 부를까: 의사결정의 실제

에이전트의 실력은 '무슨 도구를 쓸 수 있느냐'보다 '언제 어떤 도구를 골라 쓰느냐'에서 갈립니다. 도구를 여럿 붙여 놓아도 판단이 서툴면 엉뚱한 도구를 부르거나, 검색으로 해결될 일을 혼자 지어내며 환각을 냅니다.

실무에서 도구 선택은 대체로 이렇게 굴러갑니다. 프롬프트에 각 도구의 이름, 용도, 입력 형식을 설명으로 넣어 둡니다. 모델은 현재 상황을 보고 '지금은 검색이 필요하다'고 판단한 뒤, 미리 약속된 형식으로 도구 이름과 넣을 값을 적어 냅니다. 바깥의 실행 프로그램이 그 글을 읽어 실제 도구를 부르고, 돌아온 결과를 다시 모델에게 관찰로 건넵니다. 모델은 도구를 직접 만지지 않습니다. "이 도구를 이 값으로 불러 달라"는 주문서를 쓸 뿐이고, 실제 실행은 바깥 프로그램이 맡습니다. 요즘 AI 서비스들이 제공하는 함수 호출(function calling) 기능이 바로 이 주문서 형식을 표준으로 정해 둔 것입니다(자세한 방식은 글 끝 심화 절에서 다룹니다).

간단한 예를 들어 보겠습니다. 사용자가 '지금 서울 날씨와, 서울과 뉴욕의 시차를 알려 줘'라고 물으면, 잘 만든 에이전트는 두 번의 도구 호출을 계획합니다. 먼저 날씨 도구에 '서울'을 넣어 부르고, 이어 시차 계산을 위해 시간대 도구나 계산기를 부른 뒤, 두 관찰 결과를 합쳐 최종 답을 만듭니다. 반대로 '3,847 곱하기 29'처럼 정확한 계산이 필요한 질문에는 머릿속으로 어림하지 않고 코드 실행 도구에 맡기는 편이 정확합니다.

도구 이름과 넣을 값을 정확한 형식으로 적어야 하는 순간에는 모델의 답이 들쭉날쭉하지 않도록 무작위성을 낮게 설정하는 것이 보통입니다. 이런 설정값이 무엇이고 어떻게 조절하는지는 프롬프트 엔지니어링 글에서 다룹니다.

질문을 받은 에이전트가 도구가 필요한지, 필요하면 최신 정보, 계산, 문서 검색 가운데 어느 도구를 쓸지 고르고, 결과를 본 뒤 도구가 더 필요한지 다시 묻는 판단 흐름도

혼자보다 팀: 멀티 에이전트와 감독자 구조

에이전트 하나가 모든 일을 도맡기보다, 역할을 나눈 여러 에이전트가 협업하도록 설계하기도 합니다. 이를 멀티 에이전트(multi-agent) 구조라 부릅니다. 큰 문제를 여러 전문가에게 나눠 맡기는 조직도와 비슷합니다.

가장 흔한 형태가 감독자(supervisor) 구조입니다. 팀장처럼 전체 일을 나누고 조율하는 상위 에이전트가 목표를 잘게 나눠 하위 에이전트에게 배분하고, 각자의 결과를 모아 종합합니다. 예컨대 시장 조사 보고서를 만든다면, 조사 담당·초안 작성 담당·검증 담당을 따로 두고 감독자가 이들을 지휘하는 식입니다. 역할이 나뉘니 각 에이전트의 프롬프트와 도구를 더 좁고 정확하게 다듬을 수 있습니다.

다만 멀티 에이전트가 만능은 아닙니다. 에이전트를 늘릴수록 호출 비용과 지연이 커지고, 서로 주고받는 과정에서 오해와 오류가 번질 여지도 생깁니다. Anthropic이 2024년 12월에 낸 실무 지침(Building effective agents)도 비슷한 조언을 합니다. 화려한 구조를 먼저 세우기보다 가장 단순한 방법으로 문제가 풀리는지부터 확인하고, 정말 필요할 때만 복잡도를 올리라는 것입니다.

실제로 많은 문제는 완전 자율 에이전트가 아니라, 정해진 순서로 LLM 호출을 엮는 워크플로만으로도 충분히 풀립니다. 자율성이 높아질수록 성능의 상한도, 통제의 어려움도 같이 올라갑니다. 자율성과 예측 가능성은 맞바꾸는 관계라는 감각을 갖고 설계 수준을 고르는 편이 현명합니다.

감독자(Supervisor) 에이전트가 코드 작성, 코드 리뷰, 테스트를 맡은 하위 에이전트에게 일을 나눠 주고 결과를 모아 최종 결과로 내는 멀티 에이전트 구조 그림

에이전트 vs 워크플로 vs RAG: 헷갈리기 쉬운 경계

실무 논의에서 자주 뒤섞이는 세 개념이 있습니다. 정해진 순서로 LLM을 여러 번 호출하는 워크플로, 외부 지식을 검색해 답에 붙이는 RAG, 그리고 스스로 다음 행동을 정하는 에이전트입니다. 셋의 결정적 차이는 '경로를 누가 정하느냐'에 있습니다. 워크플로는 개발자가 흐름을 코드로 못 박아 둡니다. 에이전트는 모델이 매 단계 다음 행동을 스스로 판단합니다. RAG는 그 자체로는 검색 한 번을 답에 결합하는 패턴일 뿐, 자율 루프와는 별개의 축입니다.

이 차이를 표로 정리하면 선택 기준이 분명해집니다.

구분 경로 결정 주체 반복 여부 적합한 문제 예측 가능성
고정 워크플로 개발자(미리 짠 순서) 정해진 횟수 절차가 명확한 정형 작업 높음
RAG 개발자(검색→생성) 보통 1회 사내 문서 기반 질의응답 높음
에이전트 모델(일하는 도중에 판단) 조건 충족까지 절차가 미리 안 정해진 개방형 작업 낮음

여기서 얻을 실무 교훈은 '에이전트가 항상 정답은 아니다'라는 점입니다. 절차가 명확하고 예외가 적은 일을 굳이 자율 에이전트로 만들면, 통제하기 어렵고 비용만 더 듭니다. 고객 문의를 분류해 세 갈래로 보내는 일이라면 조건 분기 워크플로가 낫습니다. 반대로 '이 버그를 찾아 고쳐라'처럼 어떤 파일을 봐야 할지 미리 알 수 없는 작업은 에이전트에게 맡길 만합니다. 실전에서는 순수한 에이전트보다, 큰 틀은 워크플로로 잡고 특정 단계만 에이전트에게 맡기는 혼합 구조가 안정적인 경우가 많습니다. 앞의 여행사 예라면 "문의 분류"는 정해진 규칙으로, "일정이 꼬인 예약의 원인 찾기"만 에이전트에게 맡기는 식입니다.

RAG와 에이전트의 관계도 짚어 두겠습니다. 검색을 도구로 등록해 두면 에이전트는 필요할 때 스스로 검색을 되풀이합니다. 첫 검색 결과가 부실하면 질의를 바꿔 다시 검색하는 식입니다. 즉 RAG는 에이전트에 흡수될 수 있는 하위 요소이지, 대립하는 개념이 아닙니다. RAG 자체의 원리는 RAG(검색 증강 생성) 글에 정리해 두었습니다.

도구를 붙이는 공통 규약, MCP

에이전트가 쓸모 있으려면 파일, 데이터베이스, 사내 시스템 같은 바깥 세계와 연결되어야 합니다. 예전에는 도구마다 연결 코드를 따로 짰지만, 요즘은 모델 컨텍스트 프로토콜(MCP, Model Context Protocol)처럼 도구와 에이전트가 주고받는 방식을 하나로 정한 규약을 많이 씁니다. USB 규격이 여러 기기를 같은 포트로 연결하게 해 준 것과 비슷한 발상이며, 구조와 보안 문제는 MCP 글에서 자세히 다룹니다.

아직 넘지 못한 벽: 신뢰성·오류 누적·감독

할 수 있는 일이 늘어난 만큼 한계도 분명합니다. 그리고 그 한계는 별난 데서 오는 것이 아니라, 앞서 짚은 언어 모델의 본질에서 곧장 따라 나옵니다. 첫째는 신뢰성입니다. 에이전트의 각 단계는 결국 그럴듯한 다음을 고르는 예측이므로, 한 단계가 그럴듯하게 틀릴 수 있습니다. 검색어를 엉뚱하게 짜거나, 관찰 결과를 잘못 읽는 식입니다.

둘째는 오류 누적입니다. 에이전트에서 특히 조심할 지점입니다. 한 단계의 작은 오차가 다음 단계의 전제가 되고, 그 위에 또 오차가 쌓입니다. 각 단계의 정확도가 제법 높아도 단계가 길게 이어지면 전체가 목표에서 크게 벗어날 수 있습니다. 출장 예에서 비서가 미팅 날짜를 목요일이 아니라 수요일로 잘못 읽었다면, 그 뒤의 기차 조회와 예매는 아무리 꼼꼼해도 전부 헛일이 됩니다. 초반의 사소한 오독 하나가 열 단계 뒤에는 완전히 틀린 결론으로 불어나는 것입니다. 몇 바퀴 이상은 돌지 못하게 반복 상한을 두고, 중간중간 "지금까지 결과가 목표에 맞는가"를 스스로 되짚게 하는 자기 점검을 넣는 이유가 여기 있습니다.

셋째는 감독의 필요입니다. 파일 삭제, 결제, 메일 발송처럼 되돌릴 수 없는 행동은 에이전트에게 온전히 맡기기 위험합니다. 그래서 그런 행동 앞에는 사람이 확인하고 승인하는 관문을 둡니다. 이를 사람 개입(human-in-the-loop)이라 부릅니다. 출장 예에서 비서가 표를 사기 전에 물어본 것이 바로 이 관문입니다. 자동화의 효율을 조금 내주는 대신, 위험이 큰 지점에만 골라서 사람을 끼워 넣는 절충입니다.

결국 에이전트는 강력한 실행기이면서도 아직 감독이 필요한 실행기입니다. '초안은 기계, 판단은 사람'이라는 분업 원칙이 여기서도 그대로입니다. 오히려 여러 단계를 자동으로 처리하는 만큼, 사람의 감독은 덜 중요해지는 것이 아니라 더 중요해집니다. 자율성을 얻은 대가로 감독 설계라는 새로운 숙제가 생긴 셈입니다.

에이전트가 하려는 행동이 위험한지 먼저 가리고, 파일 삭제나 API 호출 같은 위험한 행동은 사람에게 승인을 받아 승인, 거부, 수정 가운데 하나로 처리하는 안전장치 흐름도

실무에서 에이전트를 다루는 법

현장에 적용할 때는 몇 가지 원칙이 되풀이해서 통합니다. 먼저 가장 단순한 것부터 시작합니다. 한 번 묻고 답하는 프롬프트로 되면 그걸로 끝내고, 안 되면 고정된 워크플로를 짜고, 그래도 부족할 때 비로소 자율 에이전트를 꺼냅니다. 자율성을 기본값으로 삼으면 어디서 잘못됐는지 찾기가 매우 어려워집니다.

다음으로 도구와 프롬프트를 분명하게 설계합니다. 각 도구가 무엇을 하고 언제 써야 하는지, 입력 형식은 무엇인지를 오해 없이 적어 줍니다. 모델이 도구를 잘못 고르는 문제의 상당수는 사실 설명이 모호했던 탓입니다. 새로 온 직원에게 업무 매뉴얼을 줄 때 "알아서 해"보다 "이럴 땐 이 서류를 쓴다"가 실수를 줄이는 것과 같습니다. 되돌릴 수 없는 행동에는 사람 승인 관문을 반드시 끼우고, 반복 상한과 예산 상한을 걸어 폭주를 막습니다.

기록도 실무의 핵심입니다. 에이전트가 어느 단계에서 무엇을 생각하고 어떤 도구를 어떤 값으로 불렀는지, 관찰 결과가 무엇이었는지를 모두 로그로 남깁니다. 여러 단계를 거치는 만큼 실패 지점을 추적하려면 이 기록이 있어야 합니다. 이렇게 속을 들여다볼 수 있게 해 두는 것을 관측 가능성(observability)이라 부릅니다. 각 단계에서 평가 지표를 정해 두고, 자주 실패하는 패턴을 찾아 프롬프트나 도구를 고쳐 가는 반복이 결국 품질을 만듭니다.

비용과 지연도 염두에 둬야 합니다. 한 목표를 처리하는 데 모델을 여러 번 부르므로, 단발 챗봇보다 비용과 응답 시간이 몇 배로 늘어날 수 있습니다. 형식이 흔들려 다시 부르는 일을 줄이고, 불필요한 단계를 쳐내고, 반복 상한을 현실적으로 잡는 것이 곧 비용 관리입니다.

더 깊이 파고들려면

에이전트를 제대로 공부하려면 인접 개념부터 단단히 다지는 편이 빠릅니다. 언어 모델이 다음 토큰(token, AI가 글을 읽고 쓰는 조각 단위로, 보통 단어 하나보다 조금 작은 단위)을 확률로 고르는 원리, 글을 숫자로 바꾸는 토큰화와 임베딩, 그리고 오늘날 언어 모델의 뼈대인 트랜스포머 구조를 알면 '왜 그럴듯하게 틀리는가'가 자연스럽게 설명됩니다. 각각 토큰과 임베딩, 트랜스포머 글에서 다룹니다. 프롬프트를 어떻게 쓰느냐가 에이전트의 판단을 좌우하므로 프롬프트 엔지니어링도 함께 읽어 두면 좋습니다.

실전에 적용하려면

에이전트를 실제 업무 자동화로 연결하려면 안정적인 도구 연동과, 여러 도구와 단계를 순서대로 지휘하는 흐름 관리(오케스트레이션)가 필요합니다. 젠아이랩스(GenAI Labs)의 MCP Agent 솔루션은 Model Context Protocol 기반으로 이 구조를 기업 환경에 맞춰 구축합니다.

맺으며

마지막으로 기억할 결론은 이 글 처음에 말한 그것입니다. 에이전트가 아무리 스스로 움직여도, 그 바닥에서 도는 것은 다음 말을 고르는 언어 모델입니다. 원리를 알아야 이 강력한 실행기를 언제 믿고 언제 감독해야 하는지 판단할 수 있습니다. 그것이 AI를 제대로 쓰는 힘입니다.

개발자를 위한 심화

이 부분은 직접 구현하는 개발자를 위한 내용입니다.

코드로 감 잡는 최소 루프

개념을 코드의 골격으로 옮겨 보면 감이 확실히 잡힙니다. 핵심은 '모델 호출 → 도구 실행 → 관찰을 다시 모델에 넣기'가 되풀이된다는 점입니다.

아래 코드는 앞에서 설명한 사고-행동-관찰 루프에서 실제 라이브러리를 걷어 내고 뼈대만 파이썬 모양으로 적은 의사코드입니다.

goal = "2024년 노벨 물리학상 수상자와 소속을 표로 정리"
history = [system_prompt(tools=[search, finish])]

for step in range(MAX_STEPS):          # 오류 누적을 막는 반복 상한
    thought, action = llm(history, temperature=0)   # 생각 + 행동 결정
    if action.name == "finish":
        answer = action.args["text"]
        break
    observation = run_tool(action)     # 실제 도구 실행(검색 등)
    history.append((thought, action, observation))   # 관찰을 기록해 다음 판단에 사용

눈여겨볼 대목이 몇 있습니다. 우선 for 문의 반복 상한(MAX_STEPS)입니다. 이것을 두지 않으면 에이전트가 답을 못 찾고 끝없이 루프를 돌거나 비용을 낭비할 수 있습니다. 다음으로 도구를 고를 때 temperature=0을 준 점입니다. 출력의 무작위성을 낮춰 형식을 흔들지 않으려는 선택입니다. 도구 이름과 인자를 정확히 적어야 하는 단계라서 그렇습니다. 여러 후보를 뽑아 봐야 하는 탐색 단계라면 온도를 조금 올리기도 합니다. 마지막으로 매 단계의 생각·행동·관찰을 history에 쌓습니다. 이 누적된 맥락이 곧 단기 메모리이고, 모델은 이를 보고 다음 수를 정합니다.

여기에 반성(reflection)을 더하면 결과가 더 나아집니다. Reflexion(2023)은 시도가 실패했을 때 그 원인을 언어로 스스로 되짚어 다음 시도에 반영하게 했습니다. 코드로 보면 루프 끝에 '방금 결과가 목표에 맞았는가, 아니면 무엇을 고쳐야 하는가'를 모델에게 한 번 더 묻고, 그 자기 평가를 메모리에 넣는 단계가 더해지는 셈입니다. 모델을 새로 학습시키는 값비싼 과정 없이 언어만으로 학습 효과를 흉내 내는 접근입니다.

에이전트의 눈과 손: 함수 호출과 구조화 출력

에이전트가 도구를 부르려면 언어 모델이 '자유로운 문장'이 아니라 '기계가 파싱할 수 있는 형식'으로 답해야 합니다. 파싱은 프로그램이 글을 읽어 필요한 칸을 뽑아내는 일입니다. 초기에는 프롬프트에 "도구를 쓸 때는 Action: search[검색어] 형식으로 쓰라"고 지시하고, 모델이 내놓은 문자열을 정규식(글자 패턴을 찾아내는 규칙 표기법)으로 잘라 썼습니다. 문제는 모델이 형식을 조금씩 어긴다는 데 있습니다. 대괄호를 빼먹거나, 설명을 덧붙이거나, 인자 순서를 바꿉니다. 파싱이 깨지면 루프 전체가 멈춥니다. 이 취약함을 없애려고 나온 것이 함수 호출(function calling), 요즘 표현으로는 도구 호출(tool calling)입니다.

함수 호출의 핵심은 도구의 명세를 JSON 스키마로 모델에 미리 넘겨 주는 데 있습니다. JSON은 "항목 이름: 값"을 짝지어 적는 데이터 표기법이고, JSON 스키마는 어떤 항목이 어떤 종류의 값을 가져야 하는지 적어 둔 양식 설명서입니다. 이름, 설명, 각 인자의 타입과 필수 여부를 스키마로 적으면, 모델은 그 형식에 맞춰 인자를 채운 JSON을 출력합니다. 예를 들어 get_weather 도구에 {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}} 같은 스키마를 주면, 모델은 "서울 날씨"라는 요청을 받아 {"city": "Seoul", "unit": "c"}를 만들어 냅니다. 이미 학습된 모델을 도구 호출용 예제로 파인튜닝(fine-tuning, 미세조정)해 스키마 형식에 맞춰 출력하도록 만들기 때문에, 문자열 파싱 시절보다 형식 오류가 크게 줄었습니다.

한 걸음 더 나가면 제약 디코딩(constrained decoding)이 있습니다. 모델이 다음 토큰을 고를 때 확률 분포 전체에서 뽑는 대신, 정해진 문법이 허용하는 토큰만 남기고 나머지 확률을 0으로 눌러 버리는 방식입니다. 이 문법은 JSON 스키마나 정규식을 "지금 상태에서 다음에 올 수 있는 글자"의 표로 바꾼 유한 상태 기계로 나타냅니다. 여는 중괄호 다음에는 키 문자열만, 콜론 다음에는 값만 나올 수 있게 강제하는 식입니다. 이렇게 하면 문법적으로 틀린 JSON은 아예 나올 수 없습니다. 오픈소스 라이브러리 Outlines, 그리고 내 컴퓨터에서 언어 모델을 돌리는 도구인 llama.cpp의 GBNF(문법 규칙을 적는 표기법) 지원이 이 방식을 씁니다. 형식은 보장되지만 내용의 정확성까지 보장하지는 않는다는 점은 기억해야 합니다. 스키마에 맞는 엉뚱한 도시 이름은 여전히 나올 수 있습니다.

실무에서 도구 스키마를 설계할 때 흔히 놓치는 부분이 인자 설명입니다. 모델은 함수 이름과 인자 설명을 거의 자연어 프롬프트처럼 읽습니다. query라고만 적은 인자와 "사용자가 찾으려는 핵심 키워드. 불용어를 뺀 명사 위주로"라고 적은 인자는 채워지는 값의 질이 다릅니다. 도구를 늘릴수록 이름이 헷갈리게 겹치지 않도록 하고, 비슷한 기능은 인자로 나눠 하나로 합치는 편이 잘못된 호출을 줄입니다. 도구가 많아지면 모델이 어떤 것을 골라야 할지 헷갈리기 시작하므로, 상황별로 보여 줄 도구 집합을 동적으로 줄이는 도구 라우팅도 함께 고려합니다.

컨텍스트 창이라는 예산: 토큰을 어디에 쓸 것인가

에이전트가 여러 단계를 돌면 대화 기록, 도구 호출 결과, 관찰 내용이 계속 쌓입니다. 이 모든 것이 컨텍스트 창(context window, 모델이 한 번에 읽을 수 있는 글의 최대 분량)에 들어가는데, 창의 크기는 유한합니다. 요즘은 100만 토큰을 받는 모델도 있지만, 무한은 아닙니다. 게다가 넣을 수 있다고 다 넣는 것이 좋은 것도 아닙니다. 컨텍스트를 예산으로 보고 관리해야 한다는 관점이 에이전트 설계의 핵심 감각입니다. 이 주제는 컨텍스트 엔지니어링 글에서 따로 깊게 다룹니다.

첫 번째 함정은 '중간이 사라지는 현상(lost in the middle)'입니다. 긴 컨텍스트를 주면 모델은 맨 앞과 맨 뒤에 있는 정보는 잘 활용하지만, 한가운데 놓인 정보는 놓치는 경향을 보입니다(Liu et al., 2023). 검색으로 스무 개 문서를 그러모아 순서 없이 밀어 넣으면, 정작 정답이 담긴 문서가 열 번째쯤에 묻혀 버릴 수 있습니다. 그래서 검색 결과를 관련도 순으로 다시 매기는 재순위(re-ranking)로 쓸 만한 문서를 추리고, 가장 관련 높은 문서를 앞뒤 끝에 놓는 재배치를 하거나, 애초에 넣는 문서 수를 줄이는 편이 정확도에 유리합니다. 무작정 많이 넣는 전략은 비용은 늘리고 성능은 떨어뜨립니다.

두 번째 함정은 컨텍스트 오염입니다. 앞 단계에서 도구가 엉뚱한 결과를 돌려줬는데 그것이 그대로 컨텍스트에 남으면, 뒤 단계의 추론이 그 오답을 사실로 믿고 진행합니다. 오류가 눈덩이처럼 커지는 배경에는 이런 오염이 있습니다. 이를 줄이려고 도구 결과를 요약해서 넣거나, 실패한 시도는 컨텍스트에서 잘라 내고 교훈만 한 줄로 남기는 압축 기법을 씁니다. 긴 작업에서는 주기적으로 대화 전체를 요약해 새 컨텍스트로 갈아 끼우는 방법도 흔합니다.

비용도 무시할 수 없습니다. 대부분의 API는 입력 토큰과 출력 토큰에 각각 요금을 매깁니다. 에이전트가 열 단계를 도는데 매 단계 컨텍스트에 전체 기록을 다시 넣으면, 토큰 사용량이 단계 수의 제곱에 가깝게 불어납니다. 이를 줄이는 데는 프롬프트 캐싱이 유용합니다. 매번 똑같이 보내는 앞부분을 서비스 쪽에 저장해 두고 다시 계산하지 않게 하는 기능입니다. 시스템 프롬프트와 도구 명세처럼 바뀌지 않는 앞부분을 캐시해 두면, 반복 호출에서 그 부분의 입력 비용과 지연이 크게 줄어듭니다. 자주 쓰는 앞부분을 컨텍스트 앞쪽에 고정해 두는 설계가 캐시 적중률을 높이는 요령입니다.

얼마나 잘하는지 어떻게 재나: 에이전트 평가의 난제

일반 LLM은 정답과 출력을 견주는 방식으로 평가하기 쉽습니다. 하지만 에이전트는 다릅니다. 최종 답만 봐서는 왜 맞았고 왜 틀렸는지 알 수 없습니다. 정답에 이르렀더라도 도구를 열 번 헛발질하며 돌아왔다면 좋은 에이전트가 아닙니다. 반대로 경로는 완벽했는데 마지막 도구에서 오류가 나서 실패했을 수도 있습니다. 그래서 에이전트 평가는 최종 결과와 과정을 함께 봐야 합니다. 에이전트가 거쳐 간 생각·행동·관찰의 기록 전체를 궤적(trajectory)이라 부릅니다.

평가 축을 나눠 보면 적어도 네 가지를 따로 재게 됩니다. 과제 성공률(정해진 목표를 실제로 이뤘는가), 궤적 품질(불필요한 단계 없이 효율적으로 갔는가), 도구 호출 정확도(맞는 도구에 맞는 인자를 넣었는가), 그리고 비용·지연(토큰과 시간을 얼마나 썼는가)입니다. 이 넷은 종종 서로 부딪힙니다. 성공률을 높이려고 단계를 늘리면 비용과 지연이 나빠집니다. 어느 지점에서 균형을 잡을지는 문제의 성격이 정합니다.

실무에서 궤적 평가는 크게 두 방식으로 합니다. 하나는 기대 궤적을 미리 정해 두고 실제 궤적과 도구 호출 순서·인자를 비교하는 규칙 기반 방식입니다. 결정적이고 재현 가능하지만, 정답 경로가 여러 개일 수 있는 개방형 문제에는 잘 맞지 않습니다. 다른 하나는 강한 모델을 채점자로 세워 궤적을 평가하게 하는 LLM-as-a-judge(LLM 심판) 방식입니다. 유연하지만 심판 모델 자체의 편향과 비용이 문제로 남습니다. 두 방식을 섞어 정형 지표는 규칙으로, 주관적 품질은 모델 심판으로 재는 절충이 흔합니다.

공개 벤치마크(여러 모델을 같은 문제로 견주는 공용 시험지)로는 코딩 에이전트를 실제 깃허브 이슈로 시험하는 SWE-bench, 웹 브라우징 능력을 보는 WebArena 계열, 복잡한 도구 사용을 평가하는 여러 데이터셋이 쓰입니다. 하지만 벤치마크 점수를 실제 성능으로 곧이 믿으면 곤란합니다. 시험 문제에만 지나치게 맞춰진(과적합된) 에이전트가 실무의 지저분한 입력 앞에서 무너지는 일이 흔하기 때문입니다. 결국 자기 업무의 대표 시나리오로 자체 평가셋을 만들어 배포할 때마다 돌리는 편이 가장 믿을 만합니다. 무언가를 고친 뒤에도 전에 되던 것이 여전히 되는지 확인하는 회귀 검사(regression test)로 쓰는 것입니다. 프롬프트 한 줄, 모델 버전 하나만 바뀌어도 궤적이 통째로 달라질 수 있으므로, 평가 자동화 없이는 에이전트를 안정적으로 운영하기 어렵습니다.

프롬프트 기법 비교와 원전

프롬프트 기법은 에이전트의 언어 그 자체입니다. 예시를 주지 않는 제로샷(zero-shot), 몇 개를 주는 퓨샷(few-shot), 생각을 풀어내는 사고 사슬(CoT), 추론과 행동을 엮는 ReAct의 차이를 아래 표로 비교해 두면 설계 감각이 잡힙니다. 모델 내부 구조가 궁금하다면 트랜스포머의 핵심인 자기어텐션(self-attention, 문장 안의 단어들이 서로 얼마나 관련 있는지 계산하는 장치)부터 보면 됩니다.

기법 핵심 방식 도구 사용 대표 쓰임새
제로샷 예시 없이 지시만 없음 단순 질의응답
퓨샷 예시 몇 개 제시 없음 형식·스타일 고정
CoT 추론 과정을 단계로 서술 없음 복잡한 추론 문제
ReAct 추론과 도구 실행을 번갈아 있음 에이전트의 기본 루프

원전을 직접 읽어 보는 것도 권합니다. 추론과 행동을 결합한 ReAct(arXiv 2210.03629), 모델이 언제 어떤 도구를 호출하면 예측이 좋아지는지를 스스로 학습하게 한 Toolformer(2302.04761), 실패를 언어로 되짚는 Reflexion(2303.11366), 여러 풀이 갈래를 동시에 펼쳐 놓고 나은 쪽을 골라 가는 Tree of Thoughts(2305.10601), 사람 행동을 흉내 내는 에이전트 사회를 다룬 Generative Agents(2304.03442)를 읽으면 흐름이 잡힙니다. 설계 실무는 Anthropic의 'Building effective agents'가 균형 잡힌 지침을 줍니다.

보완 · 한눈에 보기와 여행사·출장 준비 예시를 더하고, 전문 용어에 풀이를 달았으며, 함수 호출·컨텍스트·평가·코드 절을 개발자를 위한 심화로 옮겼다.

작성: AI (Claude Opus 4.8)

출처

  1. ReAct: Synergizing Reasoning and Acting
  2. Toolformer: LMs Can Teach Themselves to Use Tools
  3. Reflexion: Language Agents with Verbal Reinforcement Learning
  4. Generative Agents: Interactive Simulacra of Human Behavior
  5. Tree of Thoughts
  6. Building effective agents
  7. Building Effective AI Agents · 2024-12-19
  8. Lost in the Middle: How Language Models Use Long Contexts · 2023-07-06
뉴스레터로 매주 받아보기 기술 블로그 목록