happy_various AI 실전 기록

LLM 중계기 개발기 6부 · 26편 / 전체 33편

2026년 10월 1일 기준

이 글에는 제휴 링크가 없고 OpenAI·앤트로픽·구글과 아무 관계가 없습니다. 제가 직접 만든 중계기의 개발 기록을 바탕으로 썼습니다. 삽화는 GPT 이미지 생성, 도식은 직접 제작했습니다.

한 질문, 여러 AI의 답 — 같은 문제를 여러 과외 선생님에게 (LLM 중계기 개발기)

수학 숙제에 도저히 안 풀리는 문제가 하나 있다고 해 볼게요. 마침 과외 선생님이 네 분 계셔서, 같은 문제를 네 분께 똑같이 보여 드렸어요. 세 분은 같은 답을 내셨는데, 한 분은 다른 답을 내셨어요.

이때 학생은 적어도 “여기 어딘가에 함정이 있구나”를 알게 됩니다. 풀이 네 장을 나란히 놓으면 어느 단계에서 갈렸는지도 보이고요. 설명이 가장 귀에 쏙 들어오는 선생님이 누구인지는 덤으로 알게 되죠.

제가 만든 LLM 중계기의 관리 화면에도 이런 기능이 있어요. 질문 하나를 여러 AI에게 동시에 보내고, 답을 카드로 나란히 받아 보는 병렬 채팅이에요.

이 글은 LLM 중계기 개발기의 26편이자, 6부 ‘중계기 위에서, 그리고 회고’의 첫 편입니다. 지난 25편 「무거운 껍데기를 걷어내다」에서는 중계기 앱을 감싸던 무거운 껍데기를 걷어내 가볍게 만든 이야기로 5부를 마무리했어요. 6부에서는 중계기 위에 올린 기능들과, 만들어 온 11주를 돌아보는 이야기를 합니다. 첫 이야기는 여러 AI에게 한꺼번에 묻는 병렬 채팅, 그리고 그 기능이 Codex 모델 네 개 앞에서 매번 거절당하던 사고예요.

숙제 한 장을 든 작은 학생 로봇 둘레에서, 서로 다른 색의 선생님 로봇 넷이 저마다 답 카드를 들어 보이는 공부방 (GPT 이미지 생성)

결론 요약

🃏 1. 병렬 채팅 — 질문 하나, 답 카드 여러 장

관리 화면의 채팅 칸에는 단일 채팅과 병렬 채팅 두 가지 모드가 있어요. 단일 채팅은 AI 하나와 주고받는 보통의 대화예요. 병렬 채팅은 이렇게 써요.

① [모델 선택]에서 연결된 AI 모델을 두 개 이상 고릅니다. 최대 10개까지예요 ② 질문을 한 번 입력하고 보냅니다 ③ 고른 모델마다 카드가 하나씩 생기고, 각 카드에 답이 동시에 흘러 들어옵니다

카드 한 장에는 이런 것이 담겨요.

처음부터 이런 모양은 아니었어요. 8월 7일(v0.1.54)에 처음 들어왔을 때 이름은 병렬 리뷰였어요. 코드 변경분을 Codex·Claude·Gemini에게 함께 보여 주고 검토 결과를 카드로 비교해 보는 시연용 화면이었죠. 닷새 뒤인 8월 12일(v0.1.65)에 코드 리뷰라는 틀을 걷어 내고 병렬 채팅으로 바꿨어요. 개발 기록의 표현을 빌리면 “같은 메시지를 여러 모델에 동시 전송, 응답 나란히 표시”예요. [예시 질문 입력] 버튼을 누르면 들어가는 질문도 코드 대신 “한 문장으로 자기소개 해줘.”로 바뀌었어요.

나란히 놓으면 보이는 것

개발자가 아니어도 병렬 채팅이 쓸모 있는 이유는 서론의 과외 선생님과 같아요.

🎟️ 2. 원래는 ‘단체 표’ 한 장으로 보냈다

병렬 채팅 뒤에서 일하던 것은 중계기의 묶음 창구였어요. 병렬 리뷰 화면과 같은 날(8월 7일) 생긴 창구로, 정식 이름은 ‘병렬 리뷰 API’예요. 프로그램이 모델 여러 개와 질문 하나를 한 번에 보내면, 중계기가 그 모델들을 동시에 출발시켜 답을 모아 줘요.

이 창구에는 독특한 규칙이 하나 있어요. 다 같이 출발하지 못하면 아무도 출발하지 않는다는 거예요.

개발자들은 이런 성질을 원자적(atomic)이라고 불러요. 더 쪼갤 수 없는 알갱이라는 뜻의 ‘원자’처럼, 묶음을 반쯤만 실행하는 일은 없다는 뜻이에요. 놀이공원으로 치면 일행 전원이 한 칸에 같이 타는 단체 표예요.

왜 굳이 이렇게 만들었을까요? 이 창구의 원래 손님은 여러 AI의 답을 같은 조건에서 비교하려는 프로그램이에요. 다음 편에서 다룰 코드 리뷰 대결 도구가 그런 예예요. 중계기 안내서에는 “개별 모델만 즉시 다시 부르면 원래 요청의 동시 시작·비교 조건이 달라진다”고 적혀 있어요. 한 모델은 지금, 다른 모델은 1분 뒤에 출발하면 같은 조건의 비교라고 하기 어렵다는 거죠.

병렬 채팅도 처음에는 이 묶음 창구를 그대로 썼어요. 고른 모델이 몇 개든 묶음 요청 한 개로 보냈죠.

🎢 3. 사고 — 네 명이 3인승 칸에 같이 타려 할 때

놀이공원의 3인승 놀이기구를 떠올려 볼게요. 네 명 일행이 단체 표를 들고 와서 “우리는 꼭 한 칸에 같이 타야 해요”라고 해요. 직원은 이렇게 말해요. “지금은 자리가 없네요. 1초 뒤에 다시 와 주세요.”

1초 뒤에 빈 칸이 들어와요. 그래도 네 명은 3인승 칸에 탈 수 없어요. 직원은 또 “1초 뒤에 다시”라고 하고, 일행은 또 돌아와요. 놀이기구가 텅 비어 있어도 이 대화는 끝나지 않아요. 직원의 말이 틀렸기 때문이에요. “잠깐 기다리면 된다”가 아니라 “이 인원으로는 영원히 안 된다”가 맞는 말이었죠.

텅 빈 3인승 놀이기구 칸 앞에서 손을 맞잡은 로봇 넷이 함께 타려 하고, 모자를 쓴 안내원 로봇이 손바닥을 들어 멈춰 세운다 (GPT 이미지 생성)

병렬 채팅에서 바로 이 일이 일어났어요.

10편에서 본 것처럼 중계기의 교통정리 칸은 Codex에 차선 3개를 줘요. 서로 다른 Codex 모델 세 개까지는 동시에 달릴 수 있고, 같은 모델은 한 번에 하나씩이에요. 3인승 칸인 셈이죠.

그런데 병렬 채팅에서 Codex 모델을 네 개 고르면 이렇게 흘러갔어요.

① 병렬 채팅이 Codex 모델 네 개를 묶음 요청 하나로 보내요 ② 묶음 창구가 자리를 세어 봐요. Codex 자리는 3개라 넷째가 앉을 자리가 없어요 ③ 묶음 전체가 거절돼요. 거절 번호는 429, 이유 이름은 ‘묶음 전체를 지금 시작할 자리 부족’(batch_capacity_unavailable), 다시 올 시간은 1초예요 ④ 화면에는 “HTTP 429” 알림이 뜨고, 카드가 모두 ‘실행 안 됨’으로 끝나요. Codex가 아닌 AI를 함께 골랐다면 그 카드까지 함께요

개발 기록은 이 증상을 한 줄로 적었어요. “게이트웨이가 놀아도 항상 429.” 중계기가 아무 일도 하지 않고 있을 때도, Codex 모델을 넷 이상 고르면 결과는 늘 같았어요.

거절보다 나빴던 것 — 틀린 ‘다시 오세요’

12편에서 429는 “지금 너무 많다, 이만큼 뒤에 다시 와 보라”는 뜻이라고 했어요. 다시 올 시간까지 붙어 있으니, 잘 만든 프로그램일수록 그 시간만큼 기다렸다가 같은 요청을 다시 보내요. 중계기 안내서도 그렇게 하라고 권하고 있었어요. “429가 오면 다시 올 시간만큼 기다린 뒤 동일한 전체 묶음을 다시 보내라.”

문제는 이 묶음은 아무리 기다려도 들어갈 수 없었다는 거예요. 안내를 성실히 따르는 프로그램은 1초마다 같은 묶음을 보내고, 1초마다 같은 거절을 받으며 끝없이 돌 수 있었어요. 병렬 채팅은 사람이 보고 있으니 몇 번 해 보다 그만두면 되지만, 묶음 창구를 쓰는 다른 프로그램은 사정이 달라요. 고친 코드 옆의 메모에도 “일시적 혼잡처럼 보여 쓰는 쪽이 무한 재시도했다”고 적혀 있어요.

13편의 ‘따를수록 막히는 안내’와 닮은 모양이에요. 그때는 붐빔을 고장처럼 알렸고, 이번에는 불가능을 붐빔처럼 알렸어요.

🔀 4. 고친 것 ① — 채팅 화면은 ‘나눠 타기’

고친 버전은 8월 16일 v0.1.69로 나갔어요. 첫째 고침은 병렬 채팅 화면이에요.

생각해 보면 병렬 채팅에는 단체 표가 필요 없었어요. 사람이 답을 비교하는 화면이라, 네 AI가 같은 순간에 출발하지 않아도 괜찮아요. 넷째 답이 조금 늦게 시작해도 비교하는 데는 문제가 없죠. 놀이기구로 치면 나눠 타기예요. 세 명이 먼저 타고, 넷째는 다음 칸을 기다리면 돼요.

그래서 병렬 채팅은 묶음 창구를 쓰지 않고, 고른 모델마다 보통의 대화 요청을 하나씩 따로 보내게 바꿨어요. 3편에서 본 ‘OpenAI 호환’ 대화 창구, 다른 프로그램들이 늘 쓰는 바로 그 창구예요. 개발자들은 이렇게 하나를 여러 갈래로 펼쳐 보내는 것을 팬아웃(fan-out)이라고 불러요. 부채(fan)를 펴는 모양에서 온 말이에요.

따로 보낸 요청은 교통정리 칸에서 각자 차례를 기다려요. 그래서 Codex 모델 네 개를 고르면 이렇게 돼요.

Codex 모델 4개를 고를 때 — 고치기 전에는 묶음 하나가 3자리 창구에서 '1초 뒤 다시(429)'로 끝없이 거절되고, 고친 뒤에는 모델마다 따로 보내 셋은 바로 답하고 넷째는 줄을 섰다 출발한다. 아래는 429(잠깐 붐빔)와 400(이대로는 불가능)의 차이 (직접 제작)

나눠 보내면서 함께 바뀐 것들이 있어요.

실제 Codex를 붙여 확인한 기록에도, 넘친 모델이 줄을 섰다가 끝까지 답했고 정지 버튼 하나가 펼쳐 보낸 요청 전부를 멈췄다고 남아 있어요.

다만 줄에서 기다릴 수 있는 시간에도 10편에서 본 기본 한도(60초)가 있어요. 앞의 세 답이 아주 길어져 넷째가 그 안에 자리를 얻지 못하면, 넷째 카드는 ‘줄에서 기다리다 시간 초과’로 끝나고 자동으로 다시 보내지는 않아요.

로봇 셋이 3인승 놀이기구 칸을 타고 신나게 출발하고, 넷째 로봇은 줄 맨 앞에서 작은 초시계를 들고 느긋하게 다음 칸을 기다린다 (GPT 이미지 생성)

🚦 5. 고친 것 ② — ‘잠깐 붐빔’과 ‘이대로는 불가능’을 나눠 말하기

묶음 창구 자체는 그대로 남겼어요. 같은 순간에 출발해야 하는 프로그램에게는 여전히 단체 표가 필요하니까요. 대신 거절할 때 하는 말을 고쳤어요.

묶음 창구는 이제 빈자리를 세기 전에 먼저 묶음의 모양을 봐요. 한 AI의 모델 수가 그 AI의 차선 수보다 많으면, 중계기가 텅 비어 있어도 이 묶음은 영원히 출발할 수 없어요. 이런 묶음은 기다리게 하지 않고 바로 400으로 돌려보내요.

400은 ‘요청 자체를 고쳐야 한다’는 뜻의 번호예요. 429와 나란히 놓으면 이래요.

429 — 잠깐 붐빔400 — 이대로는 불가능
뜻지금 자리가 없을 뿐, 기다리면 들어갈 수 있다요청의 모양이 한도와 안 맞는다. 기다려도 안 된다
다시 올 시간함께 온다오지 않는다
쓰는 쪽이 할 일그만큼 기다렸다 같은 묶음을 다시 보낸다요청을 바꾼다. 예: Codex 모델을 3개 이하로
놀이기구로 치면“다음 칸이 오면 타세요”“이 칸은 3인승이에요. 나눠 타세요”

429가 사라진 건 아니에요. 다른 프로그램이 Codex 차선 셋 중 둘을 쓰고 있을 때 Codex 모델 두 개짜리 묶음이 오면, 그건 정말 ‘잠깐 붐빔’이라 예전처럼 429와 다시 올 시간을 돌려줘요. 바뀐 건 영원히 안 되는 경우만 400으로 떼어 낸 거예요.

이 변경은 묶음 창구를 쓰는 프로그램에게는 약속이 바뀌는 일이라, 그 버전의 안내문에 따로 적어 뒀어요. 실패 응답이면 무엇이든 다시 보내는 프로그램은 이 400을 ‘끝’으로 받아들이고, 표를 보고 모델 수를 줄여야 한다고요.

검사도 두 가지 더했어요.

남긴 교훈 — 거절은 ‘기다리면 되는지’까지 말해야 한다

오류 번호는 쓰는 쪽 프로그램에게 보내는 다음 행동 안내예요. 429는 “기다렸다 다시”, 400은 “요청을 고쳐서 다시”라는 안내죠. 안내가 틀리면 프로그램은 성실할수록 더 크게 틀려요.

이 사고가 남긴 교훈은 하나예요. 거절할 때는 이유뿐 아니라 기다리면 언젠가 되는지까지 정확히 말해야 해요.

🗂️ 6. 카드 한 장 한 장도 다듬었다

병렬 채팅의 카드도 몇 번 손봤어요. 두 가지만 짧게 적어 둘게요.

정리

① 병렬 채팅은 질문 하나를 여러 AI에 동시에 보내고 답을 카드로 나란히 보여 줘요. 비교가 쉽고, 엇갈리는 답이 다시 확인할 곳을 알려 줘요 ② ‘다 같이 아니면 아무도’인 묶음 요청을 쓰던 탓에, Codex 모델을 넷 고르면 차선 3개짜리 Codex 앞에서 늘 ‘1초 뒤 다시(429)‘로 거절됐어요. 모델마다 따로 보내 넷째는 줄을 서게 했고, 기다린 시간을 카드에 보여 줘요 ③ 기다려도 영원히 안 되는 묶음에는 이제 ‘요청을 바꾸라(400)‘와 넘친 정도를 바로 알려요. 거절은 기다리면 되는지까지 정확히 말해야 끝없는 재시도를 막아요

다음 27편은 「AI끼리 코드리뷰 대결」이에요. 오늘 나온 묶음 창구의 원래 손님, 코드 리뷰 대결 도구 이야기를 해요. 코드를 관점과 조각으로 나눠 여러 AI에게 맡기고, 서로의 지적을 교차로 검증하는 방법이에요. 차선과 줄 이야기는 10편에, 429와 다시 올 시간은 12편에 있어요.


2026년 10월 1일 기준입니다. 제가 만든 중계기의 개발 기록을 바탕으로 썼고, 특정 기업·서비스의 공식 입장이 아닙니다. 차선 수(Codex 3개), 줄에서 기다리는 시간(60초), 다시 시도 횟수와 간격, 답 예산 같은 숫자는 기본 설정값이라 이후 버전에서 바뀔 수 있어요.