레퍼런스 전멸, 믿을 건 내 기억뿐
MCP를 하려고 구글을 뒤졌지만 나오는 건 피그마(Figma)나 지라(Jira) 연결법뿐이었습니다. 마치 교수님이 툭 던져준 고서 한 권으로 유튜브를 구현해야 했던 대학 시절의 막막함이 재림했죠.

영어 블로그 사이에서 파이썬과 노드 사이를 방황하다가, 문득 Spring AI 밋업에서 본 장면이 스쳤습니다.
"그래, 익숙한 Spring으로 가자!"

쇼츠는 안 돼도 택배는 된다
PlayMCP 환경을 뜯어보니 모델이 요청을 보내면 MCP가 연동된 정보를 물어다 주는 체계였습니다. 여기서 고민이 깊어졌죠. 웹툰이나 쇼츠 제작처럼 타임아웃이 긴 작업은 MCP와 어울리지 않았습니다.
"하지만 내 택배 서비스라면? 연동만 잘 되면 사용자가 늘어날수록 배송 예측 데이터도 정교해질 거야!"

어노테이션이냐 DSL이냐, 그것이 문제로다
먼저 Swagger처럼 어노테이션으로 기능과 파라미터를 정의했습니다. /mcp 엔드포인트로 초기 리스트를 조회하는 구조를 짰죠. 여기서 개발자의 고집이 발동했습니다

AI의 헛소리(Hallucination)를 잡는 Self-Correction
테스트 중 문제가 터졌습니다. AI가 편의점 택배 유무를 자꾸 틀리게 답하는 겁니다. 저는 MCP 서버 측에 전체적인 오류 메시지를 던져 자기 교정(Self-correction)을 유도하도록 짰습니다. try-catch 로직 하나로 AI가 "아, 이게 아니구나!" 하고 다시 생각하게 만든 거죠.

에러처리을 하는걸 개발자 사용성을 위해 어노테이션과 Kotlin DSL 중 고민하다가, 런타임 오버헤드를 줄이고 더 유연한 구조를 위해 DSL 형식을 선택했습니다.

특히 GS 편의점 조회가 실패할 땐 RAG(검색 증강 생성)를 줄 수 없는 환경이라, 토큰을 더 써서라도 GPT가 리스트를 강제 조회하게 밀어붙였습니다. 어차피 카카오 '카나나'를 통하면 토큰 문제는 희석될 것이고, 컨텍스트에 한 번 올라가면 description을 보고 똑똑하게 판단할 거라 믿었으니까요.

로컬에선 신(God), 서버에선 반려?
npx @modelcontextprotocol/inspector로 로컬 테스트는 완벽했습니다.

기세를 몰아 Terraform으로 VPC, Route 53, EKS(Pod 2개), ALB(로드밸런서)까지 세팅하며 AWS에 화려하게 입성했습니다.

하지만 돌아온 건 카카오의 '연동 반려'.
"클로드(Claude)에선 잘 되는데 왜요?!" 억울함에 반론을 던졌지만, 담당자님의 답변은 싸늘했습니다. "저희 쪽 에이전트는 연결이 안 됩니다."


범인은 로드밸런싱과 세션 키
옆에 있던 초코바를 먹고 spring 문서를 기웃 거리다가 원인을 알게 되었다.

원인은 Spring MCP의 Streamable-HTTP 방식 때문이었습니다.
로컬에선 서버가 하나라 문제없었지만, EKS에 Pod를 2개 띄운 게 화근이었습니다. 첫 요청은 A 서버로 가서 세션을 맺었는데, 다음 요청이 ALB를 타고 B 서버로 가버리니 "너 누구야?" 하며 세션 키가 안 맞았던 거죠.
퇴근 후 담당자님의 조언을 곱씹으며 설정을 수정했습니다. '나만 되는 마법'의 정체는 결국 분산 환경의 세션 불일치였던 겁니다. 이 고비를 넘기자 드디어 카카오 에이전트에서도 제 서비스가 숨을 쉬기 시작했습니다.

다음화에 계속!
'프로그래밍 > 사이드프로젝트' 카테고리의 다른 글
| 사이드 프로젝트 #1 - 주제 정하기 (0) | 2026.03.02 |
|---|