AI 에이전트 개발 필수 용어 총정리 (5): 실행 환경과 샌드박싱
최규민
2026년 3월 30일8 분 소요
글 작성에 사용된 프롬프트 원문
Think harder. Think systematically.
[Context]
I am a new junior developer who has absolutely zero background in modern AI agent development and software infrastructure. I have recently joined a development team to build AI agents, but I find myself completely lost when my seniors use terms like 'Bun' or 'pi' as if they are common knowledge. I now need to master the essential vocabulary of AI agent development and its underlying infrastructure to build and manage agents effectively in a software development setting.
I have never studied, practiced, or even casually encountered modern runtimes, package managers, or agentic frameworks. My knowledge in this area is completely blank.
Therefore, do NOT skip over terms, actions, or concepts that a senior software engineer would consider so obvious they go without saying. The things that are "too basic to mention" are precisely what I need explained — the implicit, taken-for-granted knowledge that experts forget is not universal.
[Request]
Create an encyclopedia-level deep-dive terminology dictionary covering these sub-domains: JavaScript and TypeScript Runtimes, Package Managers and Dependency Management, Agentic Orchestration Frameworks, Vector Databases and Memory Management, Execution Environments and Sandboxing, API Integration and Tool Calling.
For each term, explain not just the definition but also: why the term exists (historical or practical origin), how it connects to neighboring concepts, common beginner mistakes or misconceptions, edge cases or exceptions that practitioners know from experience, and how the term is actually used in day-to-day work (not just textbook definitions).
[Output Constraints]
Output Language: ALL output MUST be written in Korean. English original terms should appear in parentheses where they aid understanding (e.g., 런타임(Runtime)).
Output Volume: Use your FULL output token capacity with ZERO abbreviation. Absolute maximum verbosity.
Output Format: Use long-form descriptive paragraphs, NOT short bullet points. No emojis.
Depth: Expand on every nuance, edge case, historical context, and common real-world mistake for each term.
If you reach the output limit, end with ">>> 여기서부터 이어서 작성 <<<" so the user can prompt you to continue.5부: 실행 환경과 샌드박싱 (Execution Environments & Sandboxing)
컨테이너(Container)와 Docker
컨테이너(Container)는 현대 소프트웨어 배포에서 가장 중요한 인프라 개념 중 하나다. AI 에이전트 개발에서 팀원들이 “도커로 띄워”라거나 “컨테이너 이미지 빌드해”라는 말을 당연하게 사용하는데, 이 개념을 모르면 배포 관련 작업에서 완전히 막혀버린다. 컨테이너는 애플리케이션과 그 실행에 필요한 모든 것(런타임, 라이브러리, 환경 변수, 설정 파일 등)을 하나의 독립적인 패키지로 묶은 것이다. 마치 애플리케이션이 작동하는 데 필요한 모든 환경을 이식 가능한 상자 안에 넣어두는 것과 같다.
컨테이너가 해결한 가장 유명한 문제는 “내 컴퓨터에서는 되는데(It works on my machine)” 문제다. 개발자 A의 컴퓨터에서는 Node.js 18 + 특정 라이브러리 버전으로 잘 동작하던 코드가, 운영 서버에서는 Node.js 16 + 다른 라이브러리 버전 환경 때문에 오류가 나는 상황이다. 컨테이너를 사용하면 개발, 테스트, 스테이징, 프로덕션 환경에서 완전히 동일한 실행 환경을 보장할 수 있다. Docker는 컨테이너를 만들고 실행하는 가장 대중적인 플랫폼이자 도구다.
Docker에서 알아야 할 핵심 개념들이 있다. 도커파일(Dockerfile)은 컨테이너 이미지를 만들기 위한 명세서(Recipe)다. FROM(베이스 이미지 지정), RUN(명령어 실행), COPY(파일 복사), ENV(환경 변수 설정), EXPOSE(포트 공개), CMD(컨테이너 시작 시 실행 명령) 등의 지시문으로 작성한다. 도커 이미지(Docker Image)는 Dockerfile을 빌드하여 만들어진 불변의(Immutable) 실행 패키지다. 도커 컨테이너(Docker Container)는 이미지를 실제로 실행한 인스턴스다. 도커 레지스트리(Docker Registry)는 이미지를 저장하고 공유하는 저장소로, Docker Hub가 대표적인 공개 레지스트리이며, AWS ECR(Elastic Container Registry)이나 GitHub Container Registry는 사설 레지스트리 서비스다.
AI 에이전트 프로젝트에서 Docker를 활용하는 전형적인 패턴을 예로 들면, 에이전트 서버, 벡터 데이터베이스(Chroma), PostgreSQL 데이터베이스를 각각 별도의 컨테이너로 정의하고, docker-compose.yml 파일을 통해 이것들을 하나의 명령(docker compose up)으로 동시에 시작하는 방식이다. 이렇게 하면 신규 팀원이 프로젝트에 합류했을 때 docker compose up 명령 하나로 전체 개발 환경을 즉시 실행할 수 있다.
샌드박싱(Sandboxing)
샌드박싱(Sandboxing)은 프로그램 또는 코드가 실행될 때 그 실행이 시스템의 나머지 부분에 영향을 미치지 못하도록 격리된 환경에서 실행하는 보안 기법이다. “모래 상자(Sandbox)”라는 이름처럼, 아이가 모래 상자 안에서 노는 것은 괜찮지만 모래가 상자 밖으로 나가지는 않는다는 비유에서 유래했다. AI 에이전트 개발에서 샌드박싱이 특히 중요한 이유는 에이전트가 코드를 실행하는 기능을 가질 때다.12
만약 LLM이 생성한 코드를 아무런 격리 없이 서버에서 직접 실행한다고 상상해보자. LLM이 의도적이든 실수든 rm -rf / 같은 명령(리눅스 시스템의 모든 파일 삭제 명령)을 생성한다면, 서버 전체가 파괴될 수 있다. 샌드박스는 이런 위험한 코드가 실행되더라도 격리된 공간 안에서만 피해를 입히고 실제 시스템에는 영향을 주지 않도록 보호한다. 에이전트가 실행 결과를 파일 시스템에 저장하거나 네트워크 요청을 하거나 외부 프로세스를 실행하는 모든 행위를 통제할 수 있다.13
E2B (Environment to Build)
E2B는 AI 에이전트를 위한 전용 클라우드 코드 실행 샌드박스 서비스로, 2023년에 등장하여 AI 에이전트 커뮤니티에서 빠르게 채택되었다. E2B의 핵심 가치 제안은 간단하다. “AI 에이전트가 생성한 코드를 안전하게, 빠르게, 확장 가능하게 실행할 수 있는 격리된 환경을 API 형태로 제공한다.” E2B에서 각 샌드박스(Sandbox)는 경량화된 VM(Virtual Machine) 또는 마이크로VM 위에서 실행되며, 샌드박스 시작에 걸리는 시간이 약 150밀리초(ms) 수준으로 매우 빠르다.1415
E2B를 사용하면 에이전트 코드에서 SDK를 통해 샌드박스를 생성하고, 그 안에서 파이썬이나 자바스크립트 코드를 실행하고, 파일을 읽고 쓰고, 표준 출력을 스트리밍으로 받아볼 수 있다. 예를 들어 데이터 분석 에이전트가 CSV 파일을 처리하고 차트를 생성하는 판다스(Pandas) 코드를 LLM이 작성하면, 그 코드를 E2B 샌드박스 안에서 실행하고 생성된 차트 이미지를 반환받는 방식이다. E2B는 각 샌드박스 세션에 타임아웃을 설정할 수 있고, 세션이 종료되면 그 안에서 일어난 모든 변경 사항은 사라진다. 이는 상태를 유지하지 않아도 되는 일시적 실행에 이상적이다.16
초보 개발자들이 E2B를 처음 접할 때 오해하는 것은 E2B가 일반 클라우드 서버(EC2, Cloud Run 등)와 동일하다고 생각하는 것이다. E2B는 장기 실행 서비스를 호스팅하는 곳이 아니라, 단발성의 동적 코드 실행을 위한 환경이다. 에이전트가 필요할 때 샌드박스를 생성하고, 코드를 실행하고, 결과를 가져온 다음, 샌드박스를 종료하는 일회용 컴퓨팅 자원이다. 지속적으로 실행되어야 하는 에이전트 서버 자체는 E2B가 아니라 일반 컨테이너나 서버리스 함수로 배포한다.
가상 머신(VM)과 컨테이너의 차이
AI 에이전트 배포 옵션을 논의할 때 가상 머신(Virtual Machine, VM)과 컨테이너(Container)라는 두 기술이 자주 비교된다. 가상 머신은 하이퍼바이저(Hypervisor)라는 소프트웨어가 물리적 서버 위에서 완전한 가상 컴퓨터를 에뮬레이션(Emulation)하는 방식이다. 각 VM은 독립된 운영 체제(OS) 전체를 포함하므로 격리 수준이 높고 보안성이 강하지만, 시작 시간이 분 단위이고 메모리 사용량이 크다.
컨테이너는 운영 체제 커널(OS Kernel)을 호스트 시스템과 공유하면서, 네임스페이스(Namespace)와 컨트롤 그룹(cgroup)이라는 리눅스 커널 기능을 사용하여 프로세스 수준의 격리를 제공한다. 운영 체제 전체를 포함하지 않으므로 크기가 작고(수 MB에서 수백 MB), 시작 시간이 초 단위 혹은 그 이하다. 단점은 VM보다 커널을 공유하기 때문에 이론적으로 격리 수준이 낮다는 것이다. AI 에이전트 실행 샌드박스에서는 이 두 가지의 장점을 결합한 마이크로VM(microVM) 기술, 예를 들어 AWS Firecracker, gVisor 같은 것들이 사용된다. E2B도 내부적으로 Firecracker 기반의 마이크로VM을 사용하여 컨테이너 수준의 빠른 시작 시간과 VM 수준의 강한 격리를 모두 달성한다.17
서버리스(Serverless)와 엣지 컴퓨팅(Edge Computing)
서버리스(Serverless)는 “서버가 없다”는 의미가 아니라, 개발자가 서버 관리를 직접 하지 않아도 되는 실행 모델을 의미한다. 코드를 함수(Function) 단위로 배포하면, 요청이 들어올 때만 실행되고 비용도 실행 시간만큼만 과금된다. AWS Lambda, Google Cloud Functions, Vercel Functions, Cloudflare Workers가 대표적인 서버리스 플랫폼이다. AI 에이전트 프로젝트에서 서버리스는 트래픽이 불규칙하거나 특정 이벤트에 반응하는 에이전트 트리거(Trigger)를 구현할 때 자주 활용된다.
서버리스 환경에서 AI 에이전트를 배포할 때 주의해야 할 핵심 제약은 콜드 스타트(Cold Start)와 타임아웃(Timeout)이다. 콜드 스타트는 서버리스 함수가 일정 시간 사용되지 않다가 다시 호출될 때, 새 실행 환경을 초기화하는 데 수백 밀리초에서 수 초가 걸리는 현상이다. LLM API 호출처럼 응답 시간이 긴 에이전트 작업에서는 콜드 스타트가 체감 성능에 영향을 준다. 타임아웃은 더 심각한 문제다. AWS Lambda의 최대 실행 시간은 15분인데, 복잡한 다단계 에이전트가 벡터 검색, 웹 검색, LLM 호출 등을 여러 번 반복하다 보면 이 한도를 초과할 수 있다. 따라서 장시간 실행이 예상되는 에이전트는 서버리스보다 상시 실행 서버나 컨테이너로 배포하는 것이 적합하다.
환경 변수(Environment Variables)와 .env 파일
환경 변수(Environment Variables)는 프로그램 코드 외부에서 설정값을 제공하는 운영 체제 수준의 메커니즘이다. AI 에이전트 개발에서 환경 변수는 특히 API 키(API Key) 관리에 필수적이다. OpenAI API 키, Pinecone API 키, 데이터베이스 비밀번호 같은 민감한 정보를 코드에 직접 하드코딩(Hardcoding)하는 것은 절대 해서는 안 된다. 코드를 GitHub 같은 공개 저장소에 올리면 전 세계에 노출되어 심각한 보안 사고로 이어진다. 실제로 GitHub에 API 키를 실수로 커밋했다가 수백만 원의 청구서를 받은 개발자들의 사례가 비일비재하다.
환경 변수를 관리하는 표준적인 방법은 .env 파일을 사용하는 것이다. 프로젝트 루트에 .env 파일을 생성하고 OPENAI_API_KEY=sk-xxx… 형식으로 값을 저장한다. 그런 다음 dotenv 패키지(Node.js)나 python-dotenv 패키지(파이썬)를 사용하여 코드 시작 시 이 파일의 값들을 환경 변수로 로드한다. Bun은 .env 파일을 기본으로 자동 로드하여 dotenv 패키지 설치가 불필요하다. 중요한 것은 .env 파일을 반드시 .gitignore에 추가해야 한다는 것이다. 대신 .env.example 파일을 저장소에 포함시켜, 어떤 환경 변수가 필요한지 보여주되 실제 값은 포함하지 않는 관행이 표준이다. .env.local, .env.development, .env.production처럼 환경별로 다른 파일을 사용하는 패턴도 흔히 사용된다.
6부: API 통합과 도구 호출 (API Integration & Tool Calling)
API (Application Programming Interface)
API(Application Programming Interface)는 소프트웨어 컴포넌트들이 서로 통신하기 위한 규약(Contract)이다. AI 에이전트 개발에서 API는 에이전트가 외부 세계와 상호작용하는 거의 유일한 통로다. LLM 서비스(OpenAI, Anthropic, Google), 벡터 데이터베이스(Pinecone, Weaviate), 외부 도구(날씨 API, 주식 API, 검색 API) 등 모든 것이 API를 통해 연결된다. REST API(Representational State Transfer API)가 가장 일반적인 형태로, HTTP 프로토콜을 사용하여 요청(Request)과 응답(Response)을 JSON 형식으로 주고받는다.
HTTP 메서드(HTTP Method)는 API 요청의 종류를 나타낸다. GET은 데이터를 조회할 때, POST는 새 데이터를 생성하거나 처리를 요청할 때, PUT/PATCH는 기존 데이터를 업데이트할 때, DELETE는 데이터를 삭제할 때 사용한다. OpenAI의 채팅 완성(Chat Completions) API는 POST 메서드를 사용하며, 메시지 배열과 모델 설정을 JSON으로 전송하면 모델의 응답을 JSON으로 돌려받는다. HTTP 상태 코드(Status Code)도 알아야 한다. 200은 성공, 400은 잘못된 요청(Bad Request, 입력값 오류), 401은 인증 실패(API 키 오류), 429는 속도 제한 초과(Rate Limit Exceeded), 500은 서버 내부 오류다. 에이전트를 디버깅할 때 어떤 상태 코드가 반환됐는지가 문제 원인을 찾는 첫 번째 단서가 된다.
함수 호출(Function Calling)과 도구 호출(Tool Calling)
함수 호출(Function Calling)은 2023년 OpenAI가 GPT 모델에 도입한 기능으로, LLM이 단순히 텍스트를 생성하는 것을 넘어서 사전에 정의된 함수를 호출하도록 구조화된 출력을 생성하는 능력이다. 현재는 OpenAI를 포함하여 Anthropic(Claude), Google(Gemini), Mistral 등 대부분의 LLM 제공업체가 이 기능을 지원하며, “도구 호출(Tool Calling)”이라는 더 일반적인 용어로 표준화되고 있다.
함수 호출이 왜 중요한지 이해하려면, 이것이 없을 때 어떤 문제가 있는지를 생각해야 한다. LLM은 텍스트를 출력하는데, 에이전트가 이 텍스트를 파싱(Parsing)하여 어떤 도구를 호출해야 하는지 판단하려면 복잡한 텍스트 처리 로직이 필요하다. 예를 들어 LLM이 “서울의 날씨를 알아봐야겠다. get_weather 함수를 location=’Seoul’로 호출하자”라고 자유 형식의 텍스트로 출력한다면, 코드에서 이것을 파싱하는 것은 오류가 발생하기 쉽다. 함수 호출 기능은 LLM이 JSON 형식으로 {“name”: “get_weather”, “arguments”: {“location”: “Seoul”}}을 출력하도록 강제하여, 코드에서 신뢰성 있게 파싱하고 실행할 수 있게 한다.
실무에서 도구 호출을 정의할 때는 함수의 이름, 설명(Description), 파라미터 스키마(Parameter Schema)를 JSON Schema 형식으로 정의한다. 이 설명은 LLM이 언제 이 도구를 사용해야 하는지 판단하는 근거가 되므로, 명확하고 구체적으로 작성하는 것이 매우 중요하다. 초보 개발자들이 자주 하는 실수는 도구 설명을 너무 짧거나 모호하게 작성하는 것이다. 예를 들어 “날씨를 가져온다”라는 설명보다 “주어진 도시 이름의 현재 기온(섭씨), 날씨 상태(맑음/흐림/비 등), 습도를 반환한다. 사용자가 특정 지역의 날씨를 물어볼 때 사용한다”처럼 상세하게 작성해야 LLM이 올바른 상황에서 도구를 선택한다.
병렬 도구 호출(Parallel Tool Calling)은 LLM이 여러 도구를 순차적으로 한 번씩 호출하는 대신, 한 번의 응답에서 여러 도구 호출을 동시에 요청하는 기능이다. 예를 들어 “서울, 부산, 제주도의 날씨를 모두 알려줘”라는 요청에 대해, 순차 호출이라면 서울 날씨 조회 → 결과 수신 → 부산 날씨 조회 → 결과 수신 → 제주 날씨 조회 순서로 세 번의 LLM 호출이 필요하지만, 병렬 도구 호출로 세 도시의 날씨 조회를 한 번에 요청하고 모두 완료된 다음 결과를 LLM에 한 번에 전달하면 비용과 시간을 크게 절약할 수 있다. LangGraph의 병렬 노드 실행 기능과 결합하면 에이전트 성능을 크게 향상시킬 수 있다.
MCP (Model Context Protocol)
MCP(Model Context Protocol)는 Anthropic이 2024년 말에 발표하고 2025년에 급속도로 채택된 개방형 표준 프로토콜로, AI 에이전트와 외부 데이터 소스 및 도구 사이의 통신 방식을 표준화한다. MCP가 등장하기 이전에는 각 에이전트 프레임워크마다 도구를 통합하는 방식이 달랐다. LangChain으로 만든 에이전트와 AutoGen으로 만든 에이전트가 동일한 데이터베이스 도구를 사용하려면, 각각의 프레임워크 방식에 맞게 별도로 구현해야 했다. MCP는 이 통합 방식을 단일 표준으로 통일하는 것을 목표로 한다.18
MCP의 구조는 세 요소로 나뉜다. MCP 호스트(Host)는 Claude Desktop이나 VS Code Copilot처럼 MCP를 지원하는 AI 클라이언트 애플리케이션이다. MCP 클라이언트(Client)는 호스트 내에서 MCP 서버와 통신하는 컴포넌트다. MCP 서버(Server)는 실제 데이터나 도구를 제공하는 경량 서비스다. 예를 들어 파일 시스템 MCP 서버는 파일 읽기/쓰기 도구를 제공하고, GitHub MCP 서버는 이슈 조회, PR 생성 등의 도구를 제공한다. 표준화된 MCP 프로토콜 덕분에 어떤 MCP 호스트든 어떤 MCP 서버와도 연결할 수 있다.19
MCP가 가져온 가장 큰 변화는 도구 생태계의 공유다. 한 개발자가 Slack MCP 서버를 만들면, MCP를 지원하는 모든 에이전트에서 그 서버를 재사용할 수 있다. 2025년 말 기준으로 수천 개의 MCP 서버가 커뮤니티에 의해 개발되었고, AWS, Cloudflare, GitHub 같은 대형 기업들도 공식 MCP 서버를 발표했다. 초보 개발자들이 MCP를 처음 접할 때 헷갈리는 것은 MCP 서버의 실행 방식이다. MCP 서버는 크게 두 가지 전송 방식을 지원한다. stdio(Standard Input/Output) 방식은 MCP 서버가 로컬 프로세스로 실행되며 표준 입출력을 통해 통신하는 방식으로, 로컬 도구에 적합하다. SSE(Server-Sent Events) 방식은 HTTP 기반으로 원격 서버와 통신하는 방식으로, 클라우드에 배포된 MCP 서버에 적합하다.
스트리밍(Streaming)과 SSE (Server-Sent Events)
스트리밍(Streaming)은 LLM의 응답이 생성되는 즉시 토큰 단위로 전달하는 방식이다. ChatGPT를 사용할 때 답변이 한 글자씩 타이핑되듯 나타나는 것이 바로 스트리밍의 시각적 결과다. 스트리밍이 없으면 LLM이 200 토큰 분량의 답변을 완성할 때까지 사용자는 아무 반응 없이 기다려야 하는데, 응답이 길수록 수 초에서 수십 초를 그냥 기다려야 한다. 이는 사용자 경험을 크게 해친다. 스트리밍을 사용하면 LLM이 첫 토큰을 생성하는 순간부터 사용자에게 전달되므로, 체감 응답 속도가 훨씬 빠르게 느껴진다.
기술적으로 스트리밍은 HTTP 연결을 닫지 않고 열어둔 채로 데이터를 조각조각 전송하는 방식을 사용한다. 서버가 클라이언트에게 단방향으로 이벤트를 지속적으로 전송하는 표준 방식이 SSE(Server-Sent Events)다. OpenAI API를 스트리밍 모드로 호출하면 응답이 data: {“choices”: [{“delta”: {“content”: “안”}}]} data: {“choices”: [{“delta”: {“content”: “녕”}}]} 처럼 토큰 하나씩 SSE 형식으로 전달된다. LangChain에서는 .stream() 메서드, OpenAI SDK에서는 stream: true 옵션으로 스트리밍을 활성화할 수 있다. 웹소켓(WebSocket)과 SSE의 차이도 실무에서 자주 등장하는 개념인데, SSE는 서버에서 클라이언트로 단방향 통신만 가능한 반면, 웹소켓은 양방향 실시간 통신이 가능하다. AI 에이전트 응답 스트리밍처럼 서버 → 클라이언트 방향의 단방향 전송이면 SSE가 더 가볍고 단순하다.
AI 에이전트 개발에서 스트리밍은 단순한 UX 향상을 넘어서 에이전트의 내부 추론 과정을 실시간으로 노출하는 데도 활용된다. LangGraph의 .stream() 메서드는 각 노드의 실행 상태, 도구 호출 이벤트, LLM 응답 토큰을 각각 다른 이벤트 타입으로 스트리밍하여, 사용자가 에이전트가 지금 무엇을 하고 있는지 실시간으로 볼 수 있게 한다. 초보 개발자들이 스트리밍을 구현할 때 흔히 저지르는 실수는 스트리밍 응답을 일반 응답처럼 await로 단순히 기다리는 것이다. 스트리밍 응답은 반드시 for await…of 루프(자바스크립트/타입스크립트)나 for 루프와 함께 async for(파이썬)를 사용하여 각 청크를 순차적으로 처리해야 한다.
레이트 리밋(Rate Limit)과 재시도 로직(Retry Logic)
레이트 리밋(Rate Limit)은 API 제공자가 특정 시간 내에 허용하는 최대 요청 횟수 또는 토큰 수를 제한하는 정책이다. AI 에이전트 개발에서 레이트 리밋은 현실적으로 매우 자주 부딪히는 문제다. OpenAI API의 경우 초당 요청 수(RPM, Requests Per Minute), 분당 토큰 수(TPM, Tokens Per Minute), 일일 요청 수(RPD, Requests Per Day) 등 여러 차원에서 제한이 적용된다. 에이전트가 루프 안에서 반복적으로 LLM을 호출하거나, 수천 개의 문서를 배치(Batch) 임베딩 처리할 때 레이트 리밋에 걸려 429 오류를 받는 일이 흔하다.
재시도 로직(Retry Logic)은 API 호출이 실패했을 때 자동으로 재시도하는 코드 패턴이다. 단순히 즉시 재시도하는 것은 좋지 않다. 레이트 리밋 상황에서 즉시 재시도하면 연속으로 같은 제한에 부딪히기만 한다. 올바른 재시도 패턴은 지수 백오프(Exponential Backoff)다. 첫 번째 실패 후 1초 기다렸다가 재시도, 두 번째 실패 후 2초, 세 번째 실패 후 4초, 네 번째는 8초처럼 대기 시간을 지수적으로 늘려가는 방식이다. OpenAI Python SDK와 TypeScript SDK는 자동으로 지수 백오프 재시도 로직을 내장하고 있으나, 최대 재시도 횟수(maxRetries)를 적절히 설정해야 한다. 또한 재시도 로직에는 지터(Jitter)라는 개념도 중요한데, 이는 대기 시간에 약간의 랜덤 값을 더하는 것이다. 만약 수백 개의 에이전트 인스턴스가 동시에 동일한 시간에 재시도를 하면 다시 집중적인 요청 폭발이 발생할 수 있는데, 지터를 통해 재시도 타이밍을 분산시켜 이를 방지한다.
웹훅(Webhook)
웹훅(Webhook)은 이벤트가 발생했을 때 미리 지정한 URL로 HTTP POST 요청을 보내는 방식이다. “역방향 API(Reverse API)”라고도 불린다. 일반적인 API 호출은 내 코드에서 외부 서비스로 요청을 보내는 폴링(Polling) 방식이지만, 웹훅은 반대로 외부 서비스에서 이벤트 발생 시 내 서버로 요청을 보내주는 방식이다. 예를 들어 Stripe 결제 완료, GitHub 코드 푸시, 슬랙(Slack) 메시지 수신 등의 이벤트가 발생했을 때 에이전트를 트리거(Trigger)하는 데 웹훅을 활용한다.
AI 에이전트 개발에서 웹훅은 에이전트를 이벤트 기반(Event-driven)으로 실행하는 핵심 메커니즘이다. 예를 들어 고객이 이메일을 보낼 때마다 이메일 처리 에이전트를 실행하거나, 새 파일이 스토리지에 업로드될 때마다 분석 에이전트를 실행하는 것이 웹훅으로 구현된다. 실무에서 웹훅을 구현할 때 초보 개발자들이 자주 빠뜨리는 것이 웹훅 서명 검증(Signature Verification)이다. 외부 서비스는 웹훅 페이로드(Payload)에 HMAC-SHA256 서명을 포함하는데, 이를 검증하지 않으면 악의적인 제3자가 위조된 웹훅 요청을 보내도 에이전트가 실행될 수 있는 보안 취약점이 생긴다. 또한 웹훅 엔드포인트는 빠르게 응답(200 OK)을 반환하고, 실제 에이전트 처리는 백그라운드 작업 큐(Queue)로 넘겨야 한다. 에이전트 처리가 수 초 이상 걸리면 외부 서비스에서 타임아웃으로 판단하고 재전송하여 중복 실행이 발생할 수 있기 때문이다.
프롬프트 엔지니어링(Prompt Engineering)
프롬프트 엔지니어링(Prompt Engineering)은 LLM이 원하는 출력을 생성하도록 입력 텍스트(프롬프트, Prompt)를 설계하고 최적화하는 기술이다. AI 에이전트 개발에서 프롬프트 엔지니어링은 에이전트의 핵심 행동 방식을 결정하는 소프트웨어 설계 작업이다. 잘 설계된 프롬프트는 에이전트를 안정적이고 예측 가능하게 만들지만, 잘못된 프롬프트는 에이전트가 엉뚱한 도구를 호출하거나 루프에 빠지거나 잘못된 형식으로 출력하는 원인이 된다.
시스템 프롬프트(System Prompt)는 LLM에게 역할, 행동 규칙, 출력 형식 등을 지정하는 초기 설정 메시지다. 사용자의 메시지가 들어오기 전에 LLM이 처음 읽는 지시문이며, 에이전트의 성격과 제약 조건을 정의한다. 퓨샷 프롬프팅(Few-shot Prompting)은 시스템 프롬프트나 사용자 메시지 안에 몇 가지 예시(Example)를 포함하여 LLM이 그 패턴을 학습하게 만드는 기법이다. 예를 들어 특정 형식의 JSON을 출력하게 만들 때, 그 형식의 예시를 두세 개 보여주면 LLM이 훨씬 안정적으로 동일한 형식을 따른다. 체인 오브 소트(Chain-of-Thought, CoT) 프롬프팅은 LLM이 최종 답변을 내기 전에 단계적으로 생각하는 과정을 명시하도록 유도하는 기법이다. “단계별로 생각하라(Let’s think step by step)”라는 지시를 추가하거나, 추론 과정을 먼저 작성한 뒤 답변하는 예시를 보여주면 특히 수학적 추론이나 복잡한 논리 문제에서 정확도가 크게 향상된다.
구조화된 출력(Structured Output)
구조화된 출력(Structured Output)은 LLM이 자유 텍스트가 아닌 특정 스키마를 따르는 JSON처럼 정형화된 형식으로 응답하도록 강제하는 기능이다. AI 에이전트 개발에서 에이전트의 출력을 코드에서 프로그래밍적으로 처리하려면, 그 형식이 예측 가능해야 한다. OpenAI API의 response_format: { type: “json_schema”, json_schema: {…} } 옵션, Anthropic의 도구 호출을 통한 구조화 출력, 그리고 LangChain의 .with_structured_output() 메서드가 이를 지원한다.
파이썬 에코시스템에서는 Pydantic 라이브러리가 구조화된 출력의 스키마를 정의하는 사실상 표준 도구다. TypeScript 에코시스템에서는 Zod 라이브러리가 동일한 역할을 한다. 예를 들어 에이전트가 웹 검색 결과에서 회사 정보를 추출할 때, CompanyInfo라는 Pydantic/Zod 모델을 정의하고 LLM에게 그 모델의 스키마에 맞는 JSON을 출력하도록 강제하면, 코드에서 안전하게 company.name, company.founded_year 같은 방식으로 접근할 수 있다. 초보 개발자들이 흔히 하는 실수는 LLM의 응답을 별도의 검증 없이 직접 JSON.parse()로 파싱하는 것이다. LLM은 완벽한 JSON 대신 마크다운 코드 블록(json ...) 안에 JSON을 넣거나, 앞뒤에 설명 문장을 추가하거나, 스키마에 없는 필드를 포함하는 경우가 있다. 구조화된 출력 기능을 사용하거나, Zod/Pydantic으로 검증하거나, 적어도 JSON 추출 유틸리티 함수를 사용하는 것이 견고한 에이전트 코드 작성의 기본이다.
오케스트레이터-워커 패턴 (Orchestrator-Worker Pattern)
오케스트레이터-워커(Orchestrator-Worker) 패턴은 AI 에이전트 시스템 아키텍처에서 가장 널리 사용되는 설계 패턴 중 하나다. 오케스트레이터(Orchestrator)는 전체 작업을 이해하고 계획을 세워 하위 태스크(Subtask)를 여러 워커 에이전트(Worker Agent)에게 위임하는 역할을 한다. 워커 에이전트들은 각자 특정 도메인의 전문적 역할, 예를 들어 웹 검색 전문 에이전트, 코드 실행 전문 에이전트, 데이터 분석 전문 에이전트 등을 수행하고 결과를 오케스트레이터에게 반환한다. 오케스트레이터는 워커들의 결과를 통합하여 최종 출력을 생성한다.
이 패턴의 핵심 이점은 관심사의 분리(Separation of Concerns)와 전문화(Specialization)다. 오케스트레이터는 “무엇을 해야 하는가”의 고수준 계획을 담당하고, 워커는 “어떻게 해야 하는가”의 세부 실행을 담당한다. 각 워커에게 다른 LLM 모델을 사용할 수도 있다. 예를 들어 오케스트레이터는 복잡한 추론이 필요하므로 Claude 3.7 Sonnet이나 GPT-4o 같은 강력한 모델을 사용하고, 단순한 작업을 수행하는 워커는 비용 효율적인 Claude Haiku나 GPT-4o-mini를 사용하는 방식으로 비용 최적화가 가능하다. 실무에서 이 패턴을 구현할 때 주의할 점은 오케스트레이터와 워커 사이의 컨텍스트 전달이다. 워커에게 충분한 컨텍스트를 제공하지 않으면 오케스트레이터의 의도를 이해하지 못하고 잘못된 결과를 반환하며, 반대로 너무 많은 컨텍스트를 전달하면 토큰 비용이 급증한다.
LLM 게이트웨이(LLM Gateway)와 LiteLLM
LLM 게이트웨이(LLM Gateway)는 여러 LLM 제공업체(OpenAI, Anthropic, Google, Mistral 등)에 대한 API 호출을 단일 통합 인터페이스로 추상화하는 미들웨어(Middleware) 레이어다. 에이전트 개발팀이 처음에는 OpenAI GPT-4o를 사용하다가 비용 이유로 Anthropic Claude로 전환하거나, 특정 작업에 따라 다른 모델을 선택하고 싶을 때, 각 제공업체마다 API 형식이 다르면 코드를 전부 수정해야 하는 문제가 생긴다. LLM 게이트웨이는 이 추상화를 통해 모델 전환을 설정 변경만으로 가능하게 한다.
LiteLLM은 이 분야에서 가장 인기 있는 오픈소스 파이썬 라이브러리로, 100개 이상의 LLM 제공업체를 OpenAI와 동일한 인터페이스로 통합한다. 즉, OpenAI SDK를 사용하는 방식 그대로 코드를 작성하면서 model 파라미터만 “claude-3-7-sonnet-20250219” 혹은 “gemini/gemini-2.0-flash”로 바꾸는 것만으로 다른 모델을 호출할 수 있다. 또한 LiteLLM은 비용 추적(Cost Tracking), 캐싱(Caching), 로드 밸런싱(Load Balancing), 폴백(Fallback, 기본 모델 실패 시 대안 모델로 자동 전환) 같은 프로덕션 기능도 내장하고 있어 기업 AI 에이전트 시스템에서 필수 구성 요소로 자리잡고 있다.
옵저버빌리티(Observability)와 트레이싱(Tracing)
옵저버빌리티(Observability)는 “시스템의 내부 상태를 외부 출력만으로 얼마나 잘 이해할 수 있는가”를 나타내는 개념이다. AI 에이전트 시스템은 LLM 호출, 도구 실행, 벡터 검색 등 복잡한 과정이 체인처럼 연결되어 있어, 어떤 단계에서 무엇이 잘못됐는지 파악하기 어렵다. 에이전트가 예상과 다른 답변을 생성했을 때 “LLM이 잘못된 프롬프트를 받은 것인가?”, “벡터 검색이 엉뚱한 문서를 반환한 것인가?”, “도구가 잘못된 파라미터로 호출된 것인가?”를 파악하기 위해 옵저버빌리티 도구가 필요하다.
트레이싱(Tracing)은 에이전트의 각 실행 단계를 스팬(Span)이라는 단위로 기록하고, 이 스팬들의 트리 구조를 통해 전체 실행 흐름을 시각화하는 방식이다. LangSmith(LangChain의 공식 옵저버빌리티 플랫폼), Langfuse(오픈소스 LLM 옵저버빌리티 플랫폼), Helicone, Arize AI 등이 AI 에이전트 전용 트레이싱 도구들이다. 이 도구들을 사용하면 각 LLM 호출의 입력 프롬프트와 출력, 소요 시간, 비용(토큰 수)을 대시보드에서 확인하고, 실패한 실행의 원인을 추적하고, 프롬프트 변경 전후 성능을 비교(A/B 테스트)할 수 있다. 실무에서 LangSmith를 LangGraph 프로젝트에 연결하는 것은 환경 변수 두세 줄 설정으로 가능하며, 처음 에이전트를 개발할 때부터 트레이싱을 연결해두는 것이 디버깅 시간을 크게 줄여주는 실용적인 습관이다.
pi (π) — 인퍼런스 파라미터로서의 “파이”
팀 시니어들이 “파이(pi)”를 언급할 때 맥락에 따라 두 가지 중 하나를 의미할 수 있다. 첫 번째는 Raspberry Pi(라즈베리 파이)다. 이것은 영국의 라즈베리 파이 재단에서 만든 신용카드 크기의 초소형 컴퓨터로, 로컬 AI 에이전트를 저전력 엣지 장치에 배포하거나 홈 서버로 활용할 때 자주 언급된다. 두 번째는 파이썬 패키지 인덱스(PyPI, Python Package Index)다. PyPI는 npm의 파이썬 버전으로, 파이썬 패키지들을 배포하고 설치하는 공식 저장소다. pip install langchain 명령어를 실행하면 PyPI에서 langchain 패키지를 다운로드한다. “파이파이(PyPI, 발음: 파이-피-아이)”를 줄여서 “파이”라고 부르는 경우가 있다.
세 번째 맥락은 AI 에이전트 분야에서 더욱 구체적인데, inflection.ai가 개발한 Personal Intelligence(PI) AI 어시스턴트를 지칭하거나, 혹은 수학 상수 파이(π = 3.14159…)에서 이름을 딴 특정 도구나 라이브러리를 의미하는 경우다. 실무에서 이 단어가 등장하면 당황하지 말고 “어떤 파이를 말씀하시는 건가요?”라고 맥락을 확인하는 것이 현명하다. 시니어 개발자들도 이런 암묵적 약어가 혼선을 줄 수 있다는 것을 알고 있으며, 질문을 두려워하지 않는 태도가 올바른 학습 자세다.
에이전트 평가(Agent Evaluation)와 벤치마크(Benchmark)
AI 에이전트를 개발했다면 그것이 얼마나 잘 작동하는지 측정해야 한다. 에이전트 평가(Agent Evaluation)는 일반 소프트웨어 테스트와 다른 고유한 어려움을 가진다. 일반 소프트웨어는 입력에 대한 출력이 결정론적(Deterministic)이지만, LLM 기반 에이전트는 동일한 입력에도 매번 조금씩 다른 출력을 생성하는 확률론적(Probabilistic) 특성을 가진다. 따라서 에이전트의 정답은 하나의 정확한 값이 아니라 “충분히 좋은 답변”의 범위로 정의되며, 그 평가도 자동화하기 어렵다.
에이전트 평가에서 현재 많이 사용되는 접근법은 LLM-as-a-Judge(LLM을 평가자로 사용)다. 에이전트의 출력이 정확한지, 완전한지, 관련성이 있는지, 사실에 부합하는지를 또 다른 강력한 LLM(예: GPT-4o, Claude 3.7 Sonnet)이 평가하게 하는 방식이다. 이는 인간 평가자의 노동력을 줄이고 자동화가 가능하지만, 평가 LLM 자체도 편향(Bias)을 가질 수 있다는 한계가 있다. 벤치마크(Benchmark)는 에이전트의 성능을 객관적으로 비교하기 위한 표준화된 테스트 세트다. GAIA(General AI Assistants), SWE-bench(소프트웨어 엔지니어링 에이전트 평가), HumanEval(코딩 능력 평가) 등이 AI 에이전트 분야의 대표적인 벤치마크다. 실무에서는 이런 공개 벤치마크 점수를 참고하여 에이전트 프레임워크나 모델을 선택하지만, 자신의 특정 비즈니스 유스케이스에 맞는 커스텀 평가 세트를 구축하는 것이 장기적으로 더 중요하다.
마무리: 개념들의 연결
지금까지 여섯 개의 핵심 도메인에 걸쳐 AI 에이전트 개발의 필수 용어들을 살펴보았다. 이 개념들이 실제 프로젝트에서 어떻게 하나의 흐름으로 연결되는지 정리하면 다음과 같다.
개발팀은 Bun 런타임 위에서 TypeScript로 에이전트 코드를 작성하고, pnpm으로 LangChain, LangGraph, @langchain/openai 같은 패키지들을 관리한다. 에이전트의 메모리 시스템은 Chroma(개발 환경) 혹은 Pinecone(프로덕션 환경)이라는 벡터 데이터베이스에 임베딩된 지식을 RAG 패턴으로 검색하여 컨텍스트 윈도우에 주입한다. 에이전트의 실행 흐름은 LangGraph의 그래프 구조로 정의되며, 외부 세계와의 상호작용은 OpenAI의 도구 호출(Tool Calling) 기능과 MCP 서버를 통해 이루어진다. 에이전트가 코드를 생성하고 실행해야 할 때는 E2B 샌드박스를 통해 안전하게 격리된 환경에서 실행된다. 전체 시스템은 Docker 컨테이너로 패키징되어 배포되고, .env 파일로 관리되는 API 키들이 환경 변수로 주입된다. 에이전트의 모든 실행은 LangSmith나 Langfuse로 트레이싱되어 디버깅과 최적화에 활용된다.
이 연결 고리를 이해했다면, 시니어들의 대화에서 등장하는 용어들이 더 이상 낯설지 않을 것이다. 각 용어는 독립된 지식이 아니라 전체 에이전트 시스템이라는 큰 그림의 퍼즐 조각이며, 이 관계를 파악하는 것이 진정한 AI 에이전트 개발 역량의 출발점이다.