
AI 에이전트 뒤에 숨겨진 추악한 비밀 (데모 🚀)
요약
AI 에이전트 구축에 복잡한 프레임워크가 반드시 필요한 것은 아니며, 핵심 루프는 약 80줄의 코드로도 구현 가능하다는 점을 보여줍니다. LangChain이나 CrewAI 같은 도구의 역할을 설명하고, Node.js로 구현된 실제 코드 리뷰 에이전트 데모를 소개합니다.
핵심 포인트
- AI 에이전트 프레임워크는 메모리, 도구 실행 등을 단순화할 뿐 마법이 아님
- 핵심 메커니즘을 이해하면 프레임워크 사용 여부를 결정하기 쉬워짐
- Node.js를 사용하여 약 80줄의 코드로 에이전트 핵심 루프 구현 가능
- 실제 작동하는 코드 리뷰 에이전트 'Steve'의 오픈소스 데모 제공
꽤 오랫동안 저는 AI 에이전트가 신비로운 아우라에 둘러싸여 있다는 느낌을 받아왔습니다. 아무도 그들이 실제로 무엇을 하는지 모르고, 아마 곧 세상을 지배할 것이며, 만약 당신이 직접 하나를 만들고 싶다면... 글쎄요, 당연히 프레임워크 (Framework)가 필요할 것입니다.
만약 그것이 사실이 아니라고 말한다면 어떨까요? 당신은 약 80줄의 코드만으로 자신만의 AI 에이전트를 구축할 수 있습니다.
솔직히 고백하자면, 이번 주는 쉽지 않았습니다. 직장에서 많은 일이 있었습니다. 설상가상으로, 제가 제출한 CFP(Call for Papers) 중 하나에 대해 자동 거절 이메일을 받았습니다. 보통이라면 컨퍼런스 거절은 게임의 일부일 뿐이기에 아마 5분 정도만 신경 썼을 것입니다.
하지만... 저는 실제로 그 컨퍼런스에 초대받은 상태였습니다. "이미 승인되었으니, CFP에서 발표 상세 내용을 수집하기만 하면 됩니다."라는 내용이었죠. 그 초대 때문에 저는 다른 두 곳의 컨퍼런스 기회를 거절했습니다. 뭐, 어쩔 수 없죠. 적어도 이제 9월은 자유롭네요.😉
어쨌든, 삶은 계속됩니다. 오늘은 제 생일이라서, 저 자신에게(그리고 여러분 모두에게!) 주는 작은 선물로 이 글을 썼습니다. 😄 즐겁게 읽어주시길 바랍니다!
정말로 프레임워크가 필요할까요?
본론으로 들어가 봅시다.
LangChain, CrewAI, 또는 Mastra와 같은 프레임워크들은 마법을 부리는 것이 아닙니다. 이들은 대화 메모리 (Conversation memory), 도구 실행 (Tool execution), 재시도 (Retries), 폴백 (Fallbacks) 등의 작업을 단순화해 줄 뿐입니다.
기저에 깔린 메커니즘 (Underlying mechanism)을 이해하고 나면, 프레임워크를 실제로 사용할 가치가 있는 시점이 언제인지 결정하기가 훨씬 쉬워집니다. 그리고 결국 프레임워크를 사용하게 되더라도, 내부에서 어떤 일이 일어나고 있는지 이해하게 될 것입니다.
그래서 저는 작은 데모를 만들어 AI 에이전트가 실제로 얼마나 적은 코드를 필요로 하는지 확인해 보기로 했습니다.
저는 Node.js를 사용하여 약 80줄의 코드로 AI 에이전트를 작성했습니다... 알겠습니다, 알겠어요, **핵심 루프 (Core loop)**가 약 80줄입니다. 도구 (Tools), 프로바이더 추상화 (Provider abstraction), 그리고 약간의 주변 로직은 여전히 존재합니다. 하지만 에이전트라면, _"80줄로 만든 AI 에이전트"_라는 말이 훨씬 듣기 좋잖아요. 😄
저장소는 여기 있습니다:
https://github.com/sylwia-lask/code-review-agent
그리고 제 생일이기도 하니... 만약 이 프로젝트가 마음에 드신다면, 편하게 ⭐를 눌러주세요. 물론 정말로 마음에 드실 때만요. 😄
Steve를 소개합니다
이 애플리케이션은 단순한 코드 리뷰 에이전트 (code review agent)입니다. 음... 꼭 그렇지만은 않습니다.
Steve를 소개합니다. 그는 다른 사람의 코드를 리뷰한 경력이 15년에 달하는 소프트웨어 엔지니어입니다. Steve는 어떤 것도 액면 그대로 받아들이지 않습니다. 물론, 가끔 약간 냉소적일 때도 있지만... 그의 결론에 반박하기는 어렵습니다.
그의 코드 리뷰 중 하나는 다음과 같습니다:

또는 빈 디프 (empty diff)가 있을 때:
현재 Steve는 로컬 Git 디프 (Git diff)를 리뷰합니다. 이는 기본적으로... 자기 자신을 리뷰하고 있다는 뜻입니다. 따라서 저는 @nitsancohen770에 따르면 언젠가 제 일자리를 뺏어갈 것이라는 그 유명한 셀프 힐링 에이전트 (self-healing agent)의 프로토타입을 만든 것 같습니다.
보시다시피, 저는 기본적으로 저 스스로를 실직하도록 자동화하는 것을 돕고 있습니다. 어쩌면 이제 드디어 은퇴를 생각해야 할 때인지도 모르겠네요. 😄
"에이전트는 그저 while 루프일 뿐이다"
이전 글에서 저는 AI 에이전트가 while 루프에 불과하다고 주장하는 사람들에 대해 농담을 했습니다. 음... 제 것은 while 루프조차 아닙니다. for 루프입니다. 실수로 무한 루프 (infinite loop)를 만들어 토큰 (tokens) 비용으로 너무 많은 돈을 잃는 것을 방지하고 싶었거든요. 😄
공정하게 말하자면, 루프(loop) 자체가 실제로 무언가를 _수행_하는 것은 아닙니다. 루프는 단순히 프로세스를 오케스트레이션 (orchestrating)하는 역할을 할 뿐입니다. 하지만 재미있는 점은 대부분의 에이전트 프레임워크 (agent frameworks)들도 내부적으로는 놀라울 정도로 유사한 작업을 수행하고 있다는 것입니다.
루프 자체를 작성하는 것은 매우 간단했습니다. 진짜 도전 과제는 정확히 예상했던 곳에 있었습니다.
AI 에이전트를 구축하는 것은... LLM (Large Language Model)을 선택하는 것부터 시작됩니다. 😄 이번에는 Gemini API를 선택했는데, 이런 프로젝트를 위한 토큰 (tokens) 비용이 터무니없이 저렴하기 때문입니다. 다음 버전을 로컬 모델 (local model)을 사용하여 구축하고 싶은 유혹이 강하게 들지만... 잠시만요. 😄
저는 즉시 한 가지 문제에 부딪혔습니다. 일부 Gemini 모델에 과부하가 걸려 계속해서 503 응답을 받았기 때문입니다. 이는 프레임워크들이 보통 기본적으로 제공하는 기능인 간단한 재시도 메커니즘 (retry mechanism)을 직접 구현해야 함을 의미했습니다.
제가 만든 것은 의도적으로 매우 기본적인 수준입니다. 프로덕션용 프레임워크들은 보통 지수 백오프 (exponential backoff), 지터 (jitter), 또는 다른 모델로의 자동 폴백 (automatic fallback)과 같이 훨씬 더 많은 기능을 제공합니다.
다음 과제는 당연히 적절한 프롬프트 (prompt)를 작성하는 것이었습니다. 그 이후로는 모든 것이 놀라울 정도로 명확해졌습니다.
에이전트는 실제로 어떻게 작동하나요?
여러분이 생각하는 것보다 훨씬 더 간단합니다.
1단계: 프롬프트와 사용 가능한 도구 전송
우리는 모델에 두 가지를 보냅니다:
- 사용자의 메시지,
- 모델이 사용하도록 허용된 도구 (tools) 목록.
요청은 다음과 같은 형태를 띱니다:
{
"model": "gemini-2.5-flash",
"contents": [
...
2단계: 모델의 응답 대기
모델은 다음 세 가지 방식 중 하나로 응답할 수 있습니다:
- 일반 텍스트 (plain text),
- 도구 호출 (tool call) 요청,
- 또는 두 가지 모두.
만약 일반 텍스트를 반환한다면 작업이 완료된 것입니다. 그것이 우리의 최종 코드 리뷰입니다. 만약 도구를 호출해 달라고 요청한다면, 3단계로 넘어갑니다.
예를 들어, 다음과 같은 응답을 받을 수 있습니다:
{
"candidates": [
{
...
3단계: 로컬에서 도구 실행
이제 우리 애플리케이션의 차례입니다.
우리는 요청된 도구(tool)를 로컬에서 실행합니다. 예를 들어, git diff를 실행하거나 저장소에서 파일을 읽은 다음, 그 결과를 대화의 또 다른 메시지로서 모델에게 다시 보냅니다.
이 데모에서 사용할 수 있는 도구는 다음과 같습니다:
getDiffgetFilelistFiles
다시 말해, 훌륭한 코드 리뷰어에게 필요한 모든 것입니다. 😄
4단계: 모델이 완료될 때까지 반복
그런 다음 단순히 2단계로 돌아갑니다. 무한 루프에 빠지는 것을 방지하기 위해, 최대 반복 횟수를 10회로 제한합니다.
하지만 한 가지 더 중요한 세부 사항이 있습니다.
다음 요청을 살펴보세요. 우리가 **전체 대화 기록 (entire conversation history)**을 모델에게 다시 보내고 있다는 점에 주목하세요:
{
"contents": [
{
...
그리고... 이게 전부입니다. LLM은 어떤 도구를 사용할지와 언제 완료할지를 결정합니다. 그 외의 모든 것 — 도구 실행, 재시도 처리, 반복 제한 적용, 루프 오케스트레이션(orchestrating) — 은 우리 애플리케이션의 책임입니다.
단순하죠, 그렇지 않나요? 시각화 자료를 좋아하신다면, ChatGPT가 우리를 위해 하나를 준비했습니다 😉

다음은 무엇인가요?
앞으로 최소 두 개의 후속 기사를 쓰고 싶습니다. 하나는 Steve를 MCP에 연결하는 것에 관한 것이고, 다른 하나는 호스팅된 모델을 **로컬 LLM (local LLM)**으로 교체하는 것에 관한 것입니다.
하지만... 잠시만요. 한 번에 한 단계씩 가야죠. 😄
보너스: 모델은 함수를 호출해야 한다는 것을 어떻게 알까요?
만약 여러분이 오직 AI 에이전트를 구축하는 방법만을 배우기 위해 이곳에 오셨다면, 아마 지금 읽기를 멈추셔도 좋습니다. 😄
이 섹션은 호기심 많은 분들을 위한 것입니다. 왜냐하면 조만간 누군가는 이렇게 물을 것이기 때문입니다: "Sylwia, 무슨 말을 하는 건가요? 본인만의 AI 에이전트를 만들고 있다고 말하지만, 그냥 Gemini SDK를 사용하고 있잖아요. JSON을 보내고, JSON을 돌려받을 뿐이잖아요."
그리고 @darkwiiplayer가 자주 지적하듯, LLM (Large Language Model)은 기본적으로 매우 정교한 다음 토큰 예측기 (next-token predictor)일 뿐이지, 어떤 마법 같은 JSON 생성기가 아닙니다.
그렇다면... 우리가 JSON을 보낼 때 모델은 무엇을 해야 할지 어떻게 알까요? 만약 Gemini 대신 오래된 로컬 Llama 모델을 사용한다면 어떤 일이 벌어질까요?
Gemini SDK가 비밀리에 어떤 특별한 프롬프트 (prompt)를 앞에 붙이는 걸까요? 아니면 모델 자체가 이를 위해 학습된 것일까요?
솔직한 답변은 우리가 모든 세부 사항을 알지는 못한다는 것입니다. 우리가 확실히 아는 것은 Gemini나 GPT 같은 모델들이 도구 호출 (tool calling)을 네이티브로 지원한다는 점입니다. SDK는 요청을 올바르게 형식화하고 API와 통신하는 역할을 담당하며, 모델 자체는 도구 선언 (tool declarations)을 이해하고 필요하다고 판단될 때 함수 호출 (function calls)을 생성할 수 있습니다.
다시 말해, 만약 우리가 더 오래된 Llama 모델을 사용하더라도, JSON을 어떻게 해석해야 하는지 설명하고 특정 JSON 형식으로 응답하도록 요청하는 프롬프트를 작성할 수 있습니다.
그러면 우리는 단순히 JSON.parse()를 호출하면 됩니다...
...모델이 마크다운 (Markdown), 설명, 또는 모델이 스스로 추가하기로 결정한 몇 가지 "도움이 될 만한" 주석 대신, 실제로 유효한 JSON을 반환한다는 가정하에 말이죠. 😄
그렇긴 하지만, 최신 오픈 소스 (open-source) 모델들도 점점 더 네이티브로 도구 호출을 지원하고 있다는 점을 언급할 가치가 있습니다.
에필로그: 다른 에이전트가 작성한 에이전트
솔직해집시다. 지금은 2026년입니다. 이 에이전트는 상당 부분... 또 다른 AI 에이전트에 의해 작성되었습니다. 😄
제가 AWS 커뮤니티 빌더 (AWS Community Builder)로 활동한 지 꽤 되었기 때문에, Claude Code 구독을 취소하고 Kiro로 전환했습니다. Kiro는 Claude, GPT, Gemini를 포함한 여러 LLM을 내장 지원하는 AI IDE입니다. 비용은 거의 비슷하지만, 프로그램 덕분에 무료로 사용할 수 있습니다.
지금까지 저는 정말 즐겁게 사용하고 있습니다. VS Code 위에 에이전트 기반의 레이어가 얹혀진 느낌이라 금방 익숙해졌습니다. 또한 현재 제가 이 도구가 실제로 할 수 있는 기능의 약 10% 정도만 사용하고 있다는 느낌이 들어서, 앞으로 이에 대해 더 많은 글을 쓰게 될 것 같습니다.
이제 AWS가 드디어 저에게 굿즈 (swag)를 보내주기만을 바라고 있습니다. 😄 특히 그들의 티셔츠 중 하나를 꿈꾸고 있어요. 몇 년 전, 폴란드에는 실제로 AWS라는 이름의 정당이 있었기 때문에, 나이 지긋한 분들의 표정이 어떨지 정말 보고 싶네요. 😄
AWS... 만약 이 글을 읽고 있다면... 기다리고 있을게요!! 😄
마치며
보시다시피, AI 에이전트가 반드시 프레임워크 (framework)로 시작할 필요는 없습니다. 때로는 LLM (Large Language Model), 도구 (tools), 대화 기록 (conversation history), 그리고 단순한 루프 (loop)만 있으면 충분합니다. 그 외의 모든 것들은 편의성, 프로덕션 강화 (production hardening), 그리고 삶의 질을 높여주는 개선 사항들일 뿐입니다.
그러니...
Steve에 대해 어떻게 생각하시나요? 그리고 AI 에이전트를 구축하는 이 방식은 어떠신가요? 😄
이 포스트가 마음에 드셨다면 LinkedIn에서 저를 팔로우하실 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기