이 글에는 제휴 링크가 없고 글에 나오는 AI 서비스들(OpenAI·앤트로픽·구글·NVIDIA·LM Studio)과 아무 관계가 없습니다. 제가 직접 만든 중계기의 개발 기록을 바탕으로 썼습니다. 삽화는 GPT 이미지 생성, 도식은 직접 제작했습니다.
‘다 했어요’라더니 잘린 답 — 영수증엔 완납, 물건은 반만 (LLM 중계기 개발기)
장을 보고 계산대에서 영수증을 받았다고 해 볼게요. 영수증 맨 아래에는 ‘결제 완료’ 도장이 또렷하게 찍혀 있습니다. 그런데 집에 와서 장바구니를 풀어 보니 물건이 절반뿐이에요. 직원이 봉투에 다 담기도 전에 도장부터 찍어 준 거죠.
영수증만 보고 가계부를 쓰는 사람이라면 이걸 알아챌 방법이 없습니다. 가계부에는 “장보기 끝”이라고 적히고, 빠진 물건은 처음부터 없던 일이 돼요.
제가 만든 LLM 중계기도 처음에는 이런 계산대였습니다. AI의 답이 중간에 잘려도, 답장 끝에는 늘 “다 했어요”라는 도장을 찍어 보냈거든요.
이 글은 LLM 중계기 개발기의 16편입니다. 지난 15편 ‘생각만 하다 답을 못 한 AI’에서는 생각하느라 답 분량을 다 써 버린 AI 이야기를 했어요. 이번에는 그보다 조용한 사고, 답이 잘렸는데 ‘다 했다’고 적혀 온 일을 깊게 들여다봅니다.

결론 요약
- 문제 — AI 답장 끝의 끝난 이유 칸이 ‘다 했음’이면 프로그램은 답을 완성본으로 저장합니다. 잘린 답에도 이 도장이 찍히면 빠진 뒷부분은 아무 오류 없이 사라져요
- 원인 — 처음에는 중계기가 이 칸을 늘 ‘다 했음’으로 채웠고, 고친 뒤에도 이유를 말하지 않는 AI에게는 기본값 ‘다 했음’이 남아 일주일 동안 잘림을 가렸습니다
- 해법 — 실제 값은 그대로 전하고, AI마다 다른 말은 번역하고, 직접 잰 값에는 ‘추정’ 꼬리표를, 확인하지 못한 AI에는 스펙 카드에 모름 표시를 하고, 잘리면 기록에 경고를 남깁니다. 쓰는 쪽은 ‘잘렸음’이면 완성본으로 저장하지 않아요
🧾 1. ‘다 했음’ 도장 하나가 왜 위험한가
3편에서 짧게 다룬 내용을 두 줄로 정리할게요. AI의 답장에는 왜 멈췄는지를 적는 끝난 이유 칸이 있고, 보통 ‘다 했음’(stop) 아니면 ‘분량에 걸려 잘렸음’(length)이 적힙니다. 처음 중계기는 이 칸을 늘 ‘다 했음’으로 채웠다가 개발 둘째 날 고쳤고, 다른 낱말을 쓰는 Claude는 번역하게 했어요.
이번 편은 그 뒤 이야기입니다. 이 한 칸이 왜 그렇게 중요한지, 고친 줄 알았는데 왜 몇 번 더 손봐야 했는지, 그리고 지금 중계기와 쓰는 쪽 프로그램이 각각 무엇을 하는지예요.
사람은 잘린 답을 보면 대개 알아챕니다. 문장이 “그래서 결론은”에서 뚝 끊기니까요. 하지만 프로그램은 글을 읽고 판단하지 않아요. 답장 끝의 끝난 이유 칸을 보고, ‘다 했음’이면 다음 단계로 넘어갑니다. 그러면 이런 일이 생길 수 있어요.
- 회의록 요약 — 안건 다섯 개 가운데 세 개까지만 정리된 요약이 ‘완성본’으로 저장됩니다. 나중에 요약만 보는 사람에게 뒤의 두 안건은 회의에 없던 일이 돼요
- 코드 검토 — 바뀐 파일 열 개 가운데 앞의 여섯 개에만 의견이 달립니다. 나머지 네 개는 의견이 없으니 “문제없음”처럼 보이죠
- 자료 정리 — 표로 뽑아 달라고 한 자료의 마지막 몇 줄이 빠집니다. 표 모양은 멀쩡해서, 줄 수를 세어 보기 전에는 모릅니다
더 곤란한 점은 잘림이 오류가 아니라는 것이에요. AI는 허락된 분량만큼 정상적으로 쓰고 멈췄고, 요청도 ‘성공’으로 끝납니다. 빨간 오류 표시도, 다시 해 보라는 신호도 없어요. 끝난 이유 칸이 유일한 단서인데, 거기에 ‘다 했음’이 찍혀 있으면 그 단서마저 사라집니다.
✂️ 2. 고친 줄 알았는데 — 도장을 바로잡기까지
사고 경위를 시간 순서로 따라가 볼게요.
① 7월 14일 저녁 — 한꺼번에 받는 답장부터
중계기를 처음 만든 다음 날이었습니다. 한 AI 서버는 답이 분량에 걸리면 끝난 이유에 ‘잘렸음’을 분명히 적어 보냈어요. 그런데 중계기가 답장을 OpenAI 모양으로 다시 포장하면서 이 칸을 ‘다 했음’으로 덮어썼습니다. 코드에 ‘다 했음’이 글자 그대로 박혀 있었거든요. 계산대에 ‘완납’ 도장 하나만 있었던 셈입니다.
고친 방법은 단순했어요. AI가 적어 보낸 값을 그대로 옮겨 적고, AI가 아무것도 적지 않았을 때만 ‘다 했음’을 쓰게 했습니다. 중계기를 쓰던 다른 도구는 이 값으로 잘림을 알아채고, 잘린 데까지를 ‘부분 결과’로 살려 쓰게 됐어요.
② 34분 뒤 — 조금씩 받는 답장도, 그리고 기록에 경고
첫 수정은 답을 한꺼번에 받는 경우만 고친 것이었어요. 답을 만들어지는 대로 조금씩 흘려 받는 방식(스트리밍)에서는 끝난 이유가 맨 마지막 조각에 실려 오는데, 여기엔 여전히 ‘다 했음’이 박혀 있었습니다. 34분 뒤에 나온 다음 판에서 이쪽도 실제 값을 싣게 고쳤어요.
같은 판에서 중계기의 기록(로그)도 달라졌습니다. 응답 한 건마다 질문과 답에 쓴 분량, 요청한 분량 한도, 끝난 이유를 한 줄로 남기고, 끝난 이유가 ‘잘렸음’이면 그 줄을 경고로 올려 ‘출력 잘림’이라고 덧붙여요. 이 경고가 빠지면 실패하는 자동 검사도 함께 만들었습니다. 흉내만 내는 가짜 AI로 일부러 잘린 답을 만들고, 기록에 경고가 찍히는지 확인하는 검사예요.
다음 날 아침에는 중계기에 프로그램을 붙이는 사람을 위한 연결 안내서에 규칙 한 줄을 적었어요. 끝난 이유가 ‘잘렸음’이면 정상 완료로 저장하지 말라는 내용입니다.
③ 7월 21일 — 아무 말도 하지 않는 AI들
여기서 끝난 줄 알았는데, 일주일 뒤의 기록에는 잘림이 여전히 ‘다 했음’으로 위장되고 있었다는 진단이 남아 있습니다.
원인은 ①에서 남겨 둔 한 줄이었어요. “AI가 아무것도 적지 않았을 때만 ‘다 했음’을 쓴다.” 그런데 Claude, Codex, 그리고 끝난 이유 칸 자체가 없는 한 AI 서비스, 이 셋은 중계기 쪽 연결 부품(어댑터)이 끝난 이유를 아예 챙겨 오지 않고 있었습니다. 넘어오는 값이 없으니 매번 기본값 ‘다 했음’이 찍혔죠. 봉투를 확인하지도 않고 ‘완납’ 도장을 찍어 준 겁니다.
그날 세 연결 부품이 각자 끝난 이유를 챙겨 오도록 고치고, 그 동작을 확인하는 자동 시험 7개를 함께 넣었어요. 중계기의 위험 점검 문서에는 이 문제가 지금도 ‘끝난 이유 위장’이라는 이름으로 남아 있고, 옆에 ‘해소’라고 적혀 있습니다. AI마다 ‘끝’을 말하는 방식이 달라서 고치는 방법도 저마다 달랐는데, 그건 3절에서 볼게요.
④ 8월 12일 — 중계기 자신의 화면에서도
중계기에는 여러 AI에 같은 질문을 던져 답을 나란히 보는 화면이 있어요. 이 화면은 답 분량을 4,096토큰으로 고정해 보내고 있었습니다. 토큰은 AI가 글을 세는 단위예요. 그런데 생각을 길게 하는 AI가 생각에 분량을 쓰고 나면 정작 답이 잘렸고, 화면에는 그냥 ‘완료’라고 떴어요. 바깥 프로그램에는 하지 말라고 적어 둔 일을 중계기 자기 화면이 하고 있었던 거죠.
분량을 16,384토큰으로 늘리고, 끝난 이유가 ‘잘렸음’이면 상태를 ‘완료 · 출력 잘림’으로 바꾸고 답 아래에 “출력 예산(max_tokens)에서 잘렸습니다 — 이후 내용은 생성되지 않았습니다”라는 안내를 붙였습니다. 생각이 답 분량을 먹는 이야기는 15편에서 자세히 했어요.

🗣️ 3. AI마다 ‘끝’을 말하는 방식이 다르다
중계기 뒤에 선 AI들은 끝난 이유를 저마다 다른 방식으로 알려 줍니다. 크게 네 갈래였어요.
① 웹 주소로 부르는 AI — 직접 적어 보낸다
NVIDIA의 AI 창구, 구글 Gemini API, LM Studio처럼 ‘OpenAI 호환’ 모양으로 말하는 AI는 답장에 끝난 이유를 직접 적어 보냅니다. 중계기는 그 값을 손대지 않고 넘기기만 해요. 2절 ①의 첫 사고가 난 AI 서버도 이 갈래입니다.
② Claude — 자기 낱말로 말한다
Claude는 답이 끝날 때 마지막 알림에 멈춘 이유를 자기 낱말로 적어 보냅니다. 중계기는 이걸 OpenAI 형식의 낱말로 옮겨 적어요.
- ‘end_turn’(할 말을 마침), ‘stop_sequence’(미리 정해 둔 멈춤 표시를 만남) → 다 했음(stop)
- ‘max_tokens’(분량 한도에 닿음) → 잘렸음(length)
- ‘refusal’(답하기를 거절함) → 걸러짐(content_filter)
세 번째는 3편에서 다루지 않은 경우예요. 거절로 멈춘 답도 ‘다 했음’과는 다른 끝이라, 따로 구분해 적습니다.
③ Codex와 Gemini 명령어 도구 — 말이 없으면 ‘다 했음’
Codex는 일을 마치면 ‘끝났음’ 알림과 함께 쓴 분량을 알려 줍니다. 여기에 끝난 이유가 들어 있고 그게 분량 초과라면 중계기는 ‘잘렸음’으로 옮겨요. 이유가 따로 없으면 ‘다 했음’을 적습니다. 중계기가 Codex에는 답 분량 한도를 걸지 않기 때문이에요. 걸어 둔 한도가 없으니 한도에 걸려 잘릴 일도 없다는 판단입니다.
Gemini 명령어 도구는 끝 상태를 알리는 낱말을 읽어요. 그 낱말에 ‘길이’나 ‘한도’ 같은 말이 들어 있으면 ‘잘렸음’, 아니면 ‘다 했음’으로 적습니다.
④ 끝난 이유 칸이 아예 없는 AI 서비스 — 중계기가 재서 추정한다
한 AI 서비스는 답을 조각조각 보내 주기만 하고, 왜 멈췄는지는 어디에도 적지 않았어요. 그래서 중계기가 직접 재기로 했습니다.
- 답의 길이를 토큰으로 어림합니다. 이때 한국어는 글자 하나를 토큰 하나로 넉넉하게 셉니다. 적게 세면 잘린 답을 멀쩡한 답으로 놓치기 때문이에요
- 어림한 길이가 요청한 분량 한도의 98%에 닿았으면 잘렸음으로 판정합니다
- 그 밖에는 다 했음으로 둡니다
- 나중에 이 서비스가 끝난 이유를 보내기 시작하면, 그 값을 먼저 씁니다
그리고 판정이 어디서 왔는지 꼬리표를 붙여 기록에 남겨요. AI가 직접 알려 준 값이면 ‘받음’(upstream), 길이를 재서 ‘잘렸음’으로 본 것이면 ‘추정’(estimated), 별다른 근거 없이 ‘다 했음’으로 둔 것이면 ‘가정’(assumed)입니다. 같은 ‘다 했음’이라도 AI가 말해 준 것과 중계기가 짐작한 것은 무게가 다르니까요.
리본으로 치면 이런 차이예요. 재단사가 “여기서 잘랐어요”라고 말해 주는 리본이 있고, 아무 말 없이 건네받아 자로 재 보고 “주문한 길이에 거의 닿았으니 잘린 것 같다”고 짐작해야 하는 리본이 있습니다.
🏷️ 4. 그래서 ‘믿어도 되는지’를 따로 적는다
3절을 다시 보면, 쓰는 쪽 프로그램이 받는 ‘다 했음’에는 세 종류가 섞여 있어요. AI가 직접 한 말, 중계기가 번역한 말, 그리고 AI가 말이 없어서 중계기가 채운 말입니다. 답장의 칸만 봐서는 이 셋을 구별할 수 없어요. 지금도 칸이 비어 있으면 중계기는 ‘다 했음’을 적어 보내거든요.
그래서 9편의 스펙 카드에는 끝난 이유를 믿어도 되는지를 적는 줄이 있습니다. 7월 20일, 카드가 지금의 양식을 갖춘 날 함께 생긴 줄이에요. 값은 둘 중 하나입니다.
- 믿어도 됨(reliable) — 이 AI가 보낸 끝난 이유를 중계기가 그대로 전달한다고 연결 부품이 밝힌 경우예요. NVIDIA, 구글 Gemini API, 그리고 첫 사고의 그 AI 서버가 지금 여기에 있습니다
- 모름(unknown) — 연결 부품이 따로 밝히지 않으면 전부 이쪽이에요. 명령어 도구로 부르는 Claude·Codex·Gemini와, 3절 ④의 추정하는 AI 서비스가 여기에 있습니다
카드에는 확인을 마친 곳만 ‘믿어도 됨’으로 적어요. 코드에 남긴 메모 그대로 “과장 금지”입니다. 그래서 LM Studio처럼 끝난 이유를 그대로 넘기는 AI도 아직 카드에는 ‘모름’으로 적혀 있어요.
‘모름’은 틀렸다는 뜻이 아닙니다. ‘다 했음’이라고 적혀 있어도 AI가 직접 한 말이 아니라 중계기가 채운 값일 수 있으니, 그 점을 염두에 두고 보수적으로 다루라는 뜻이에요. 정리하면 이렇게 나뉩니다.
- 한 건 한 건의 판정 근거 — 기록에 남은 ‘받음·추정·가정’ 꼬리표에서
- 그 AI를 얼마나 믿을지 — 스펙 카드의 ‘믿어도 됨·모름’ 줄에서

🚨 5. 지금 중계기가 하는 일, 쓰는 쪽이 할 일
지금 중계기는 끝난 이유를 이렇게 다룹니다.
- 그대로 전한다 — AI가 적어 보낸 끝난 이유는 손대지 않고, 한꺼번에 받는 답장과 조금씩 받는 답장 모두에 싣습니다
- 번역한다 — Claude·Codex·Gemini 명령어 도구의 낱말을 OpenAI 형식의 낱말로 옮깁니다
- 모르면 표시한다 — 직접 잰 값에는 기록에 ‘추정’ 꼬리표를, 확인하지 못한 AI에는 카드에 ‘모름’을 적습니다
- 잘리면 경고한다 — 기록에 쓴 분량·한도와 함께 ‘출력 잘림’ 경고 줄을 남기고, 이 경고가 사라지면 자동 검사가 실패합니다. 중계기 자기 화면에도 ‘완료 · 출력 잘림’이 뜹니다
이 표시는 중계기 안에서도 쓰여요. 15편의 자동 재시도는 끝난 이유가 ‘잘렸음’인데 답 본문이 0자일 때 “생각하다 분량을 다 썼다”고 보고 분량을 키워 다시 보냅니다. ‘잘렸음’이 정확히 적혀야 이 장치도 제때 움직일 수 있어요.
중계기가 할 수 있는 건 여기까지예요. 잘린 답을 어떻게 다룰지는 결국 쓰는 쪽 프로그램이 정해야 합니다. 그래서 연결 안내서와 설명서에 이렇게 적어 두었어요.
① ‘잘렸음’이면 완성본으로 저장하지 않는다 — 요약이든 검토든 ‘끝난 일’로 기록하지 않습니다
② 부분 결과라고 알린다 — 잘린 데까지의 내용은 ‘부분 결과’라는 표시를 달아 보여 줄 수 있어요
③ 분량을 조정해 다시 요청한다 — 입력을 줄이거나 답 분량 한도를 늘려서 다시 보냅니다
④ 조금씩 받을 때는 마지막 조각을 챙긴다 — 끝난 이유는 맨 마지막 조각에만 실려 오고, 그 앞의 조각에는 ‘아직 없음’(null)이 적혀 있어요. 마지막 값을 버리지 말고 보관합니다
⑤ 카드가 ‘모름’이면 보수적으로 — ‘다 했음’이어도 잘렸을 가능성을 남겨 둡니다
중계기 화면에서 받아 갈 수 있는 연동 지침, 그러니까 프로그램을 붙일 때 AI 코딩 도구에 그대로 건네는 지침에도 이 규칙이 들어 있어요. “실제 사고에서 나온 규칙”이라는 제목 아래 첫 줄입니다.

정리
① AI 답장 끝의 끝난 이유가 ‘다 했음’이면 프로그램은 답을 완성본으로 저장해요. 잘림은 오류가 아니라서, 이 칸이 틀리면 빠진 뒷부분이 소리 없이 사라져요 ② 중계기는 7월 14일에 실제 값을 전하게 고쳤지만, 말이 없는 AI에게 찍히던 기본값 ‘다 했음’이 일주일 뒤까지 잘림을 가렸어요. 지금은 AI마다 다른 말을 번역하고, 직접 잰 값엔 ‘추정’ 꼬리표를, 확인하지 못한 AI엔 카드에 ‘모름’을 적고, 잘리면 기록에 경고를 남겨요 ③ 쓰는 쪽은 ‘잘렸음’이면 완성본으로 저장하지 않고, 부분 결과라고 알리거나 분량을 조정해 다시 요청해요
다음 17편은 “성공 응답 속에 숨은 실패”입니다. 이번 편이 ‘다 했다’는 도장 아래 숨은 잘림이었다면, 다음은 로그인이 만료됐다거나 한도를 다 썼다는 안내문이 아예 정상 답처럼 돌아온 날의 이야기예요.
2026년 10월 1일 기준입니다. 제가 만든 중계기의 개발 기록을 바탕으로 썼고, 특정 기업·서비스의 공식 입장이 아닙니다.