MCP 도구가 토큰을 잡아먹는다 — 응답 하나가 대화 전체를 무겁게 만든 이야기

2026년 08월 28일 · AI 자동화, 개발 일지

같은 작업의 토큰 소모가 고치기 전 120k에서 응답을 깎은 뒤 15k로 줄어든 비교

앞 글에서 발행 도구를 MCP 서버로 만든 이야기를 했다. 만들고 나서 한동안은 잘 썼다. 그러다 문제가 터졌다.

어느 날 글 다섯 편을 올리고 사후에 태그와 본문을 고치는 작업을 한 세션에서 처리했는데, 토큰이 예상보다 훨씬 많이 나갔다. 글을 쓴 것도 아니고 이미 있는 글을 손본 것뿐인데 그랬다.

뭐가 먹었는지 세어봤다

감으로 짐작하지 않고 그 세션의 도구 호출을 전부 세어봤다. 어떤 호출이 몇 번 있었고, 응답이 얼마나 컸는지 표로 정리했다.

결과가 명확했다. 전체 소모의 70~80퍼센트가 딱 두 종류에서 나왔다. 글의 태그를 바꾸는 호출과 본문을 교체하는 호출이었다. 이 둘만 합쳐서 90k 토큰쯤 됐다.

이상했다. 태그를 바꾸는 요청은 크지 않다. 글 번호와 태그 목록만 보내면 된다. 본문 교체도 본문 자체는 2~3천자다. 그런데 왜 이렇게 큰가.

응답을 열어보고 알았다.

범인은 응답이었다

워드프레스 REST에 글 수정을 요청하면 수정된 글 객체를 통째로 돌려준다. 확인해보라는 뜻인데, 그 안에 든 게 문제였다.

본문이 두 번 들어 있었다. 원본 형태로 한 번, HTML로 변환된 형태로 또 한 번. 같은 내용을 엔티티만 바꿔서 중복으로 담고 있었다. 거기에 각종 링크가 스무 개 넘게, 그리고 CSS 클래스 목록, 고유 식별자, 퍼머링크 템플릿, 자동 생성된 슬러그, 개정 이력까지 붙어 왔다.

내가 필요한 건 “성공했나”와 “글 주소가 뭔가” 둘뿐이었다. 그런데 글 하나 고칠 때마다 10k 토큰짜리 확인 메시지가 돌아왔다.

진짜 문제는 그게 남는다는 것

한 번에 10k면 크긴 해도 감당 못 할 정도는 아니다. 문제는 다른 데 있었다.

도구 응답은 대화에 남는다. 그리고 대화는 매 턴마다 통째로 다시 전달된다. 즉 한 번 받은 10k짜리 응답이 그 세션이 끝날 때까지 계속 따라다닌다. 열 번 호출하면 100k가 대화에 얹히고, 그 뒤로 무슨 말을 하든 그 100k가 매번 같이 실린다.

이게 복리로 불어나는 구조다. 나는 글을 고치고 있다고 생각했는데, 실제로는 고칠 때마다 이후 모든 대화를 조금씩 더 무겁게 만들고 있었다.

일반 API를 쓸 때는 응답이 커도 처리하고 버리면 그만이다. 그런데 AI가 쓰는 도구는 다르다. 응답이 문맥에 쌓인다. 그래서 도구를 만들 때 “동작하는가”만 볼 게 아니라 “얼마나 말이 많은가”를 같이 봐야 했는데, 그걸 몰랐다.

원인은 세 겹이었다

파고들어 보니 문제가 하나가 아니었다.

첫째는 방금 말한 응답 비대다. 비상구로 만들어둔 패스스루 도구가 원본 응답을 그대로 넘기고 있었다.

둘째는 전용 도구가 없어서 그 비상구를 쓸 수밖에 없었다는 점이다. 발행 도구는 새 글을 만드는 것만 할 줄 알았다. 이미 올린 글을 고치는 도구가 없으니 본문이든 태그든 손대려면 패스스루로 갈 수밖에 없었고, 그게 첫 번째 문제를 직격했다.

태그 하나 바꾸는 데 네 단계를 밟아야 했다. 글에 붙은 태그를 조회하고, 새 태그를 만들고, 글에 연결하고, 안 쓰는 태그를 지운다. 이 과정에서 태그 이름을 손으로 이스케이프해 넣다가 한글이 깨지는 오타까지 냈다. 절차가 번거로우면 실수도 따라온다.

셋째가 좀 뜻밖이었다. 본문의 목록이 제대로 렌더링되지 않는 버그가 있었다. 굵은 줄 바로 밑에 빈 줄 없이 목록을 쓰면 목록으로 변환되지 않고 그냥 문장으로 나오는 문제였다. 그래서 다섯 편 전부 사후에 다시 고쳐야 했고, 그 재작업이 첫 번째와 두 번째 문제를 대량으로 호출했다.

렌더링 버그 하나가 토큰 폭발의 방아쇠였던 셈이다. 원인을 하나씩 따라가다 보니 서로 물려 있었다.

고친 것

우선순위를 매겨서 손봤다.

응답을 깎는 게 첫 번째였다. 패스스루 도구의 기본 동작을 핵심 필드만 돌려주는 쪽으로 바꿨다. 상태, 글 번호, 주소, 수정 시각 정도만 남기고 링크 목록이나 중복된 본문은 잘라냈다. 전체가 필요한 드문 경우에만 따로 요청하게 했다. 이것 하나로 그 세션 기준 90k가 5k 수준이 됐다.

두 번째는 글 수정 전용 도구를 만드는 것이었다. 넘긴 필드만 바뀌고 안 넘긴 건 그대로 두는 방식이다. 본문만 주면 본문만, 태그만 주면 태그만 바뀐다. 반환은 처음부터 짧게 설계했다. 이걸 만드니 패스스루로 왕복할 일 자체가 사라졌다.

태그는 이름 목록만 주면 알아서 처리하게 흡수했다. 네 단계가 한 번으로 줄었고, 손으로 이스케이프할 일이 없어지니 인코딩 오타도 구조적으로 못 나게 됐다.

목록 렌더링 버그도 고쳤다. 원래 한쪽 경로에만 있던 전처리를 공용 모듈로 빼서 양쪽에 적용했다. 애초에 제대로 렌더링되면 사후 재작업이 없고, 재작업이 없으면 앞의 문제들이 호출될 일도 없다.

결과적으로 같은 작업을 다시 한다면 120k 쓰던 게 15k 수준으로 내려간다.

배운 것

MCP 도구를 만드는 튜토리얼은 많은데 이 얘기를 다루는 글은 거의 못 봤다. 겪고 나니 설계에서 제일 중요한 축이었다.

도구의 응답 크기는 그 도구를 쓰는 비용이다. 한 번의 크기가 아니라 남아서 반복되는 크기다. 그래서 기본값은 짧게 두고, 전체가 필요하면 따로 요청하게 만드는 쪽이 맞다.

그리고 전용 도구가 없으면 사람은 비상구를 쓴다. 비상구는 유연한 대신 무겁다. 자주 하는 일에 전용 도구가 없다는 건 그 일을 할 때마다 가장 비싼 경로로 간다는 뜻이다.

마지막으로, 토큰 문제는 토큰이 아닌 데서 시작될 수 있다. 이번엔 렌더링 버그가 출발점이었다. 숫자만 보고 응답 크기만 줄였다면 재작업 자체는 계속 발생했을 것이다.

다음 글에서는 조금 다른 층위의 낭비를 다루려 한다. 도구가 뱉는 게 아니라, 정해진 순서로 도는 파이프라인이 구조적으로 매번 먹는 비용에 대한 이야기다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다