팀에 합류하자마자 MCP 서버를 만든 이유: 제휴 비즈니스 19개 플로우를 AI로 디버깅하기까지
제휴마케팅 팀에 합류한 직후, 장애가 날 때마다 여러 DB 클라이언트를 수동으로 뒤지는 팀의 디버깅 과정을 목격했습니다. 유입부터 정산까지 이어지는 체인이 DB 4종에 흩어져 있었고, 사람의 힘으로 추적하는 데 한계가 있었습니다. 비즈니스 전체를 분석해 MCP 서버를 만들었습니다.
참고: 이 글은 실제 사내 프로젝트를 개념 수준에서 재구성했습니다. 내부 테이블명, 도메인 식별자, 사내 인프라 설정 등 구체적인 내부 정보는 포함하지 않습니다.
팀에 합류하자마자 본 것
제휴마케팅 팀으로 이동한 첫 주에 장애 대응을 옆에서 지켜봤습니다.
상황은 이랬습니다. 특정 파트너사의 클릭 유입이 주문으로 이어지지 않는다는 CS가 들어왔고, 담당자는 원인을 추적하기 위해 DB 클라이언트를 세 개 열었습니다. 유입 로그는 MongoDB에 있고, 주문 귀속 테이블은 Oracle에 있고, 정산 결과는 MSSQL에 있었으니까요. 탭을 넘나들며 유입 토큰을 손으로 복사하고, SQL을 직접 작성해 대조했습니다.
30분이 넘어서야 원인이 나왔습니다. 타임존 보정 오차로 유입과 주문의 시간 기준이 맞지 않아 귀속 실패로 처리된 케이스였습니다.
저는 옆에서 이 과정을 보면서 한 가지 생각이 들었습니다.
"이 흐름 전체를 AI 에이전트에게 시키면 어떨까?"
문제를 명확히 하기 위해 먼저 비즈니스부터 분석했습니다
MCP 서버를 만들기 전에, 먼저 팀의 비즈니스를 제대로 이해해야 했습니다. 어떤 이벤트가 어디에 기록되는지도 모른 채로 추적 도구를 만들 수는 없으니까요.
제휴마케팅 비즈니스의 핵심은 **귀속(Attribution)**입니다. 파트너사의 링크를 클릭한 사용자가 구매까지 이어졌을 때, 그 기여를 올바르게 파트너사에 귀속하고 정산하는 것. 이 체인이 깨지면 파트너사 CS, 정산 오류, 수동 재처리가 발생합니다.
플로우를 파악하기 위해 6개 Gradle 서브프로젝트의 엔트리포인트를 전수 스캔했습니다. codegraph CLI를 활용해 HTTP, Batch, Kafka, Scheduled 총 1,000개가 넘는 엔트리포인트의 콜체인과 닿는 테이블을 추출했습니다. 이 결과를 정리해 19개 핵심 비즈니스 플로우를 flows.yaml 카탈로그로 만들었습니다.
# flows.yaml (개념 예시)
flows:
- name: click-inflow
description: "파트너 링크 클릭 → 유입 로그 기록"
entrypoints: ["InflowController.handleClick", ...]
- name: order-attribution
description: "결제 완료 → 유입 토큰 대조 → 주문 귀속"
entrypoints: ["OrderEventConsumer.onOrderComplete", ...]
- name: settlement-aggregation
description: "일/월 정산 집계 배치"
entrypoints: ["SettlementBatchJob.run", ...]
이 카탈로그가 MCP 서버의 뼈대가 됩니다. "이 플로우에 어떤 엔트리포인트가 매핑되어 있고, 코드와 DB에 실제로 존재하는가"를 검증하는 verifyFlow Tool의 기준점이 되기 때문입니다.
왜 REST API나 어드민 화면이 아니라 MCP인가
처음에 "이걸 내부 어드민 화면으로 만들까" 생각했습니다. 버튼 하나로 유입~정산 체인을 조회하는 UI를요.
그런데 실제 디버깅 과정을 떠올려보면, 단순히 데이터를 조회하는 것이 전부가 아닙니다. 조회 결과를 보고 다음 단계를 결정하고, 그 다음 조회를 이어가는 맥락 유지 기반의 탐색이 핵심입니다.
예를 들어, 유입 추적을 하다가 타임존 보정 오차가 의심되면 verifyInflowDateOffset으로 표본 검증을 하고, 주문 귀속이 실패했다면 traceFullFlow로 어느 단계에서 체인이 끊겼는지 확인하고, PCS 유입이라면 verifyServiceSubPair로 소유 정합성을 추가로 검사합니다.
이 탐색 흐름은 사전에 정해진 게 아니라, 앞선 결과에 따라 동적으로 결정됩니다. REST API나 어드민 화면은 이 흐름을 담을 수 없습니다. MCP는 AI 에이전트가 맥락을 유지한 채 여러 Tool을 자율 조합하므로, 디버깅 대화 자체가 탐색 흐름이 됩니다.
# Claude Code에 등록
claude mcp add --transport http affiliate-mcp http://localhost:8099/mcp
# 이후 자연어로 디버깅
> "유입 토큰 abc123 추적해줘"
> "주문 귀속이 왜 실패했는지 분석해줘"
> "이 파트너사의 최근 정산 상태 확인해줘"
3계층 37개 Tool 설계
MCP 서버의 Tool은 용도에 따라 세 계층으로 나뉩니다.
계층 1. 코드 추출 (정적 분석, devbox 전용)
코드베이스에서 비즈니스 플로우의 골격을 뽑아냅니다. DB 없이도 동작하지만, codegraph 인덱스가 필요합니다.
| Tool | 역할 |
|---|---|
listEntryPoints |
전 프로젝트 엔트리포인트 열거 (HTTP/Kafka/Batch/Scheduled) |
traceEntryPoint |
특정 클래스의 콜체인 + 닿는 테이블 추출 |
verifyFlow |
카탈로그 vs 코드/DB 실존 검증 |
findUnassignedEntryPoints |
어떤 플로우에도 배정 안 된 엔트리포인트 발굴 |
계층 2. 런타임 추적 (실 DB 데이터, 컨테이너 배포 가능)
실제 dev 환경 데이터로 플로우를 단계별 추적합니다. 이 계층이 디버깅 대화의 핵심입니다.
traceInflow(token) → MongoDB 유입 로그 추적
traceOrder(orderToken) → Oracle 주문 귀속 추적
traceSettlement(...) → Oracle + MSSQL 정산 추적
traceFullFlow(token) → 유입 → 주문 전체 체인 리포트
tracePostback(...) → 포스트백 발송 이력 추적
traceMember(linkrewId) → 파트너 회원 전체 프로필
verifyInflowDateOffset() → 타임존 보정 정합성 표본 검사
이 계층은 하위 서비스들이 실제로 쓰는 것과 동일한 접속 설정으로 DB에 붙습니다. 별도 추상화 없이 실 운영 데이터와 완전히 동일한 맥락을 볼 수 있습니다.
계층 3. Databricks 교차검증 (silver 레이어)
Oracle/MongoDB/MSSQL을 미러링한 은(silver) 레이어를 동일 키로 대조합니다. dev 환경에서는 볼 수 없는 채널 유입, 옥션 주문, 정산 미러를 이 계층에서 채울 수 있습니다.
가장 까다로웠던 부분: PCS 비정상 유입 역추산
단순 추적보다 훨씬 복잡한 케이스가 있었습니다. PCS(Price Comparison Site) 유입에서 발생하는 비정상 패턴 감지입니다.
기존에는 담당자의 개인 지식에 의존했습니다. "이 조합이 이상하다"는 걸 경험으로 파악하고, SQL을 3~4개 직접 조합해서 검증했습니다. 재현이 안 되고, 인수인계도 어려웠습니다.
이걸 Tool로 구조화했습니다.
P1. 소유 정합성 판정
→ verifyServiceSubPair(serviceCode, subId)
→ (serviceCode, subId) 쌍이 실제 등록된 조합인지 확인
P2. 제휴사 혼종 판정
→ verifyServiceSubPair의 affiliateIdWhitelist 활용
→ 같은 파트너 소유지만 다른 매체를 혼용한 케이스 감지
P3. 위조 토큰 역산
→ traceOrder → 주문 토큰 디코드 → verifyServiceSubPair
→ 주문 토큰 내 serviceCode/subId가 실존하는지 검증
P4. 유입-주문 불일치 감지
→ tracePcsInflow + traceOrder 조합
→ 유입 로그만 있고 주문이 없는 위조 호출 패턴 탐지
P5. 봇/크롤링 판정
→ tracePcsInflow + 미등록 UA + 이미지 도메인 referer 3중 대조
이제 이 판정 과정은 AI 에이전트와의 대화 한 번으로 재현됩니다. 신규 팀원도 "이 유입이 정상인지 확인해줘"라고 물으면 에이전트가 플레이북 순서대로 Tool을 조합해 결과를 돌려줍니다.
코드와 런타임 계층을 분리한 이유
처음에는 모든 Tool을 하나의 컨테이너에 다 넣으려 했습니다. 그런데 정적 분석 Tool들은 전체 소스코드와 codegraph 인덱스가 필요했습니다. 수십만 줄짜리 모노레포를 컨테이너에 넣는 건 현실적이지 않았습니다.
그래서 의도적으로 분리했습니다.
- 정적 분석 계층(5개 Tool): devbox에서만 동작. 소스코드와 codegraph 인덱스 필요.
- 런타임 추적 계층(27개 Tool): Dockerfile 하나로 어디서든 배포 가능. DB 접속만 있으면 됨.
이 분리 덕분에 핵심 디버깅 기능(런타임 추적)은 배포 환경 제약과 무관하게 항상 동작합니다. 정적 분석이 필요할 때만 devbox에서 실행하면 됩니다.
결과
이 MCP 서버를 쓰기 시작한 이후 팀의 디버깅 방식이 달라졌습니다.
장애 대응 시 DB 클라이언트를 열고 탭을 넘나들던 과정이, AI 에이전트와의 대화로 바뀌었습니다. "유입 토큰 xxx 추적해줘" 한 마디에 에이전트가 Tool을 순서대로 조합해 유입~정산 전체 체인 리포트를 돌려줍니다.
신규 팀원 온보딩도 달라졌습니다. "제휴 주문 귀속이 어떻게 동작해?"라고 물으면 에이전트가 verifyFlow로 코드 골격을 보여주고, traceFullFlow로 실제 데이터 흐름을 같이 확인하는 형태로 도메인을 탐색할 수 있게 됐습니다.
배운 것: AI-native 엔지니어링이란
이 프로젝트를 통해 제가 정의하게 된 "AI-native 엔지니어링"은 단순히 LLM을 사용하는 게 아닙니다.
팀이 가진 도메인 지식과 반복 업무를 Tool로 구조화하는 것입니다.
verifyServiceSubPair는 담당자의 경험이 코드가 된 것이고, traceFullFlow는 30분짜리 수동 디버깅 절차가 Tool로 바뀐 것입니다. MCP는 그 Tool들을 AI 에이전트가 맥락에 맞게 조합할 수 있는 인터페이스를 제공합니다.
도메인을 분석하고, 반복을 발견하고, 그것을 Tool로 만드는 과정. 이게 AI-native 엔지니어링이라고 생각합니다.