내 컴퓨터에서 잘 돌던 서비스를 동료에게 넘기면 첫날 어디선가 막힙니다. 내 컴퓨터에만 있던 설치 버전, 켜는 명령을 아는 사람은 나뿐이라는 점, 고쳤을 때 나아졌는지 확인할 방법이 없다는 점, 왜 이렇게 만들었는지 아무도 모른다는 점입니다.
그래서 코드 말고 네 가지를 더 넘깁니다. 실행 환경, 사용 설명서(README), 평가 결과, 설계 결정 기록(ADR)입니다. 아래에서 하나씩 갖춰 가며 받는 사람이 어디까지 가는지 보세요.
막히는 이유는 이 글의 서비스에서 실제로 겪었거나 확인한 것입니다. 받는 사람의 첫날을 단순하게 그린 그림입니다.
이 서비스에는 의존성이 서로 부딪치는 곳이 있었습니다. MCP 서버를 만든 파이썬 SDK는 2점대이고 MCP 서버에 연결하는 langchain-mcp-adapters 0.3.2는 설치할 때 SDK 1점대를 끌고 옵니다. 한 환경에 둘을 설치하면 서버 코드의 MCPServer를 불러올 수 없었습니다.
컨테이너(container)는 프로그램과 필요한 라이브러리를 한 상자에 담아 어디서나 같게 실행하는 기술입니다. 티켓 서버와 API를 상자 둘로 나누고 주소(TICKETS_URL)로 이으면 각자 필요한 버전을 씁니다. 두 구성을 눌러 보세요.
services:
tickets: # 1 MCP 2점대 SDK로 도는 티켓 서버
build: { context: ., dockerfile: Dockerfile.tickets }
api:
build: { context: ., dockerfile: Dockerfile.api }
environment:
TICKETS_URL: http://tickets:8000/mcp # 2 컨테이너 이름이 주소가 된다
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} # 3 키는 이미지에 굽지 않는다
ports: ["8010:8010"]
depends_on: [tickets]출력은 예시입니다. 이 환경은 Docker 데몬이 꺼져 있어 이미지 빌드는 해 보지 못했습니다. 컨테이너 대신 두 프로세스를 따로 띄워 같은 구성(서버 하나, API 하나, 주소로 연결)이 동작하는 것을 확인했습니다. 모델은 모의 서버입니다.
--http 옵션으로 켭니다. 다른 서비스도 같은 서버를 주소로 쓸 수 있어 재사용에 좋습니다.tickets)으로 서로를 찾습니다. 다른 컴퓨터에서 접속하는 주소 이름(Host)이 바뀌어도 서버가 거절하지 않는 것을 확인했습니다.앞에서 Agent 하나를 평가했다면 이번에는 만든 서비스를 바깥에서 평가합니다. 서비스 주소로 질문을 보내 스트림 이벤트를 모아 기대한 도구 경로와 답이 나왔는지 봅니다. 사례는 지식 질문, 조회, 승인을 받는 생성, 거절하는 생성, 지식 질문 하나 더, 다섯 가지입니다.
처음 돌린 결과는 5건 중 2건 통과였습니다. 승인 사례 둘의 도구 경로가 어긋나 있었습니다. 원인은 평가가 아닌 서비스에 있었습니다. 승인 뒤 이어 가는 스트림이 이미 보낸 tool_call 이벤트를 한 번 더 내보냈습니다. 고치기 전과 고친 뒤를 눌러 보세요.
CASES = [{"id": "faq-vpn", "msg": "VPN이 안 돼요", "path": ["search_kb"], "answer": "kb-vpn-01"}, ...]
async def stream(client, url, body): # 1 SSE를 이벤트 목록으로 모은다
...
for cs in CASES:
ev = await stream(c, "/chat", {"thread_id": tid, "message": cs["msg"]})
if any(n == "approval_required" for n, _ in ev): # 2 승인 요청이 오면 답을 보낸다
ev += await stream(c, "/approve", {"thread_id": tid, "approve": cs["approve"]})
path = [d["name"] for n, d in ev if n == "tool_call"] # 3 부른 도구 순서
answer = next((d["text"] for n, d in ev if n == "answer"), "")
ok = path == cs["path"] and cs["answer"] in answer # 4 경로와 답출력은 예시입니다. 모의 모델 서버로 실제 서비스를 평가한 결과를 줄였고 마지막 사례의 실패는 모의 서버가 문서 질문에 티켓 도구를 고르게 만든 것입니다. 실제 모델의 점수가 아닙니다.
README는 처음 온 사람이 십 분 안에 서비스를 켜 보게 하는 문서입니다. 무엇을 하는 서비스인지, 준비물, 켜는 명령, 시험해 보는 방법, 알려진 한계를 적습니다. 알려진 한계는 꼭 적습니다. 메모리 저장소라 서버를 다시 켜면 대화가 사라진다는 사실이 대표적입니다.
ADR(Architecture Decision Record, 설계 의사결정 기록)은 왜 그렇게 만들었는지를 한 장씩 남기는 문서입니다. 코드를 읽어서는 알 수 없는 이유를 남겨 나중에 같은 논쟁을 되풀이하지 않게 합니다. 세 문서를 눌러 보세요.
이 시리즈는 Agent가 무엇인지에서 시작해 직접 만든 루프, LangChain과 LangGraph, 여러 Agent, MCP, 평가와 보안을 거쳐 서비스까지 왔습니다. 마지막에는 코드보다 이 네 가지를 갖춰 남에게 넘길 수 있는 상태가 남습니다. 만든 Agent가 믿을 만한지는 점수, 기록, 이유로 설명할 수 있어야 합니다.