메인 콘텐츠로 건너뛰기

짧은 답변

콘솔 로그의 소요 시간과 클라이언트의 timeout은 동일한 구간을 측정하지 않습니다.
  • 로그의 소요 시간은 게이트웨이가 처리를 완료하는 시점까지 측정됩니다.
  • 클라이언트는 응답 본문의 마지막 바이트가 도착하고 연결이 완료되었음을 알릴 때까지 완료되지 않습니다.
따라서 “로그에는 280초 만에 완료되었다고 나오는데, 600초 timeout을 설정했는데도 데이터를 받지 못했습니다”라는 상황은 충분히 발생할 수 있습니다. 해당 요청은 실제로 성공했고 실제로 과금되었습니다. 이 차이는 로그가 다루지 않은 구간에서 발생합니다.이 페이지에서는 이러한 차이를 측정하고, 특정 구간으로 범위를 좁히며, 올바른 원인에 대응하는 방법을 설명합니다.
이 페이지에서는 대규모 응답을 사용하는 비스트리밍 호출을 다룹니다. base64를 반환하는 이미지 엔드포인트가 대표적인 사례이며, 응답 본문 크기는 수 MB에서 수십 MB에 이릅니다. 비스트리밍 장문 출력도 동일하게 동작합니다. 스트리밍 호출과 소규모 응답에는 일반적으로 영향을 주지 않습니다.

로그의 지속 시간이 실제로 포함하는 범위

호출의 전체 지연 시간은 다섯 개 구간으로 나뉩니다.
이 간격은 어떤 로그 필드에도 표시되지 않습니다.내부적으로 제어된 원시 소켓 비교를 실행했습니다. 동일한 요청 묶음에 대해 당사 백엔드는 성공 상태와 함께 5초의 지속 시간을 기록했지만, 클라이언트는 완전한 응답을 받기까지 실제로 3740초를 기다렸습니다. 이 중 3135초는 게이트웨이가 처리를 완료한 후에 발생했으며, 어떤 지속 시간 필드에도 기록되지 않습니다.즉, “내 쪽에서는 너무 오래 걸렸다”는 주장을 반박하기 위해 로그의 지속 시간을 인용하는 것은 아무 의미가 없습니다 — 두 숫자는 애초에 서로 충돌하지 않았습니다. 문제의 위치를 파악하려면 클라이언트에서 구간별 시간을 측정해야 합니다.
콘솔 및 로그 쿼리 API에서 사용할 수 있는 필드는 duration_for_view(호출 지속 시간(초)), is_stream, request_id입니다(문제를 신고할 때는 이 필드를 인용하십시오).

지속 시간에는 최종 성공 시도만 포함됩니다

업스트림 경로에서 대기열에 들어가 있거나 오류를 반환하면 게이트웨이는 백그라운드에서 다른 경로로 자동 재시도합니다. 로그의 지속 시간에는 최종 성공 시도만 포함됩니다. 이전의 실패한 시도는 포함되지 않으며 과금되지도 않습니다. 따라서 다음과 같은 상황을 볼 수 있습니다. request_id의 처음 14자리는 게이트웨이가 요청을 받은 시점입니다(UTC, YYYYMMDDhhmmss; UTC+8의 경우 8시간을 더하십시오). 반면 로그의 완료 시간은 몇 분 후이고 지속 시간에는 수십 초만 표시됩니다. 추가로 소요된 시간은 이전의 실패한 시도에 해당하며, 클라이언트는 두 시도의 시간을 합한 만큼 기다립니다.

비스트리밍 요청은 결과가 준비될 때까지 응답 헤더를 전송하지 않습니다

비스트리밍 호출(이미지 생성에서 일반적인 방식)은 결과가 완전히 준비된 후 모든 내용을 한 번에 반환합니다. 기본 Gemini 엔드포인트는 제공업체가 이미지를 완성할 때까지 기다립니다. /v1/images/edits와 같은 호환 엔드포인트도 형식을 변환하고 이미지를 URL로 저장합니다. 그때까지는 응답 헤더조차 포함하여 연결을 통해 어떠한 데이터도 흐르지 않습니다. 이는 정상적인 동작이지만, 연결이 수십 초에서 몇 분 동안 완전히 무응답 상태가 될 수 있음을 의미합니다. 트래픽이 프록시, VPN 또는 자체 호스팅 릴레이를 통과하는 경우 이 무응답 상태를 유휴 연결로 간주하여 연결을 끊을 수 있습니다. 당사는 이미 결과를 반환하고 과금했지만, 결과가 사용자의 프로그램에 도달하지 않는 것입니다. 확인 방법은 약 90초 후 프록시가 이미지 요청을 끊는 경우를 참조하십시오.

1단계: curl 한 번으로 차이를 구간에 고정하기

이 내용은 아래의 모든 단계로 들어가는 시작점입니다. 먼저 실행한 다음, 어느 섹션이 해당하는지 판단합니다.
원시 수치를 의미 있는 구간으로 변환하는 파생 지표는 다음 세 가지입니다.

결과 읽기

수치를 아래 표와 비교하십시오. 다음에 수행할 작업이 결정됩니다.
한 번 실행하는 것만으로는 충분하지 않습니다. 이 유형의 문제는 특정 시간대에 발생합니다. 해당 시간대에는 모든 호출이 연속해서 영향을 받지만, 그 시간대가 아니면 수십 번의 호출이 연속해서 완벽하게 정상일 수 있습니다. 10번 실행하여 분포를 확인하고, 시간대와 시간대를 나타내는 시간대를 기록하십시오.

2단계: “데이터는 도착했지만 연결이 끝나지 않은” 상황 측정

표가 세 번째 행을 가리킨다면 더 세밀하게 관찰해야 합니다. 응답을 청크 단위로 읽고 각 청크의 도착 시간과 청크 사이의 간격을 기록합니다. 답해야 할 질문은 다음과 같습니다. — 마지막 바이트가 도착한 후 연결이 얼마나 오래 계속 처리 중 상태였습니까?
감지 기준: tail_99가 30초를 초과하거나 max_gap가 30초를 초과하면 “꼬리 지연” 한 건으로 간주합니다. 이 현상의 특징은 바이트 수가 이미 100%에 도달한 시점에 max_gap가 발생하는 것입니다. 모든 바이트가 도착했지만, 기다림은 그 이후에야 시작됩니다.
세 단계를 하나의 타임아웃 값으로 처리하지 마십시오.이는 가장 쉽게 빠지는 함정입니다. “첫 번째 바이트를 기다리는 시간”과 “전송을 기다리는 시간”에 단일 타임아웃을 사용하면 근본 원인이 완전히 다른 두 문제가 구분할 수 없는 하나의 장애로 합쳐집니다.단계를 분리하면 로그를 통해 “생성이 느린 것인지”, 아니면 “전달은 되었지만 끝나지 않은 것인지”를 추측 없이 바로 확인할 수 있습니다.

3단계: 두 서버 간 처리량 벤치마킹

소유한 두 시스템 간

iperf3을 사용하여 실제 처리량을 측정합니다. 이것이 가장 정확한 방법입니다.

사용자의 서버에서 당사 API로

이 구간에서는 iperf3을 사용할 수 없습니다 — 당사는 iperf 서버를 실행하지 않습니다. 대신 실제 호출을 통해 유효 속도를 측정합니다.
링크 품질 점검도 함께 수행합니다.
측정 결과 표에서 “종료 신호가 도착하지 않았다”고 나타난다면 mtr 및 ping은 여기서는 아무런 소용이 없습니다. 이 경우 단 한 바이트도 손실되지 않았고 링크 품질에도 문제가 없으므로, 이러한 도구로는 이상이 표시되지 않습니다. 잘못된 원인을 추적하게 되는 것입니다. 네트워크를 조사하기 전에 위 스크립트로 자신이 어느 유형에 해당하는지 확인하십시오.

대역폭이 충분한지 확인

이미지 응답 본문은 base64로 이루어진 하나의 연속된 블록입니다. 측정된 크기는 다음과 같습니다. base64 인코딩 자체로 페이로드가 약 33% 증가합니다. 링크가 사용자에게 온전히 할당된 경우의 다운로드 시간은 다음과 같습니다. 주의할 점은 이 표가 링크를 사용자 혼자 사용한다고 가정한다는 것입니다. 실제로는 다음과 같습니다.
예를 들어 송신 대역폭이 10 Mbps이고 동시 이미지 요청이 30개이며 응답당 2.6 MB라면, 각 요청에는 대략 0.04 MB/s가 할당됩니다. 따라서 다운로드에만 62초가 걸리며, 그 62초 중 단 1초도 콘솔 로그에는 나타나지 않습니다. 동시 실행 수를 두 배로 늘리면 이 시간도 두 배가 됩니다.
이것이 바로 “바쁜 낮 시간에는 시간 초과가 발생하지만 같은 코드는 밤에는 정상적으로 작동한다”는 현상이 나타나는 이유입니다. 모델이 느려진 것이 아니라, 더 많은 요청 사이에서 대역폭이 나뉘는 것입니다.

4단계: 계측에서 기록해야 하는 필드

증상을 정확하게 설명하려면 — 직접 분석할 때든 저희에게 전달할 때든 — 호출마다 최소한 다음 항목을 기록해야 합니다. 마지막 열은 사람들이 건너뛰는 항목이지만, 실제로는 결론 그 자체인 경우가 많습니다. 동시 실행 수에 따른 속도를 그래프로 표시했을 때 동시 실행 수가 증가함에 따라 속도가 비례하여 떨어진다면, 병목은 대역폭이며 더 이상 다른 원인을 찾을 필요가 없습니다. 표 사용 방법: 콘솔 로그의 duration_for_view와 나란히 놓고 비교합니다 —
  • 서로 가까움 → 문제는 다운스트림 전송에 있습니다. 대역폭과 동시 실행 수를 확인합니다.
  • 서로 멂 → 문제는 완료 신호 또는 클라이언트 측에 있습니다.

즉시 위험을 줄이는 네 가지 방법

1

URL 출력으로 전환 — 효과가 가장 큰 변경

gpt-image-2-vip 및 gpt-image-2-all은 response_format: "url"을 허용하며, base64 대신 이미지 링크를 반환합니다. 응답 본문이 약 2.6MB에서 약 0.3KB로 줄어듭니다 — 작은 응답에는 Content-Length이 포함되므로 클라이언트가 자체적으로 완료 시점을 알 수 있어 다운로드 및 완료 신호 문제를 동시에 제거할 수 있습니다.비즈니스가 URL 출력에 의존하는 경우 토큰의 그룹을 image2_OSS으로 변경하십시오. 리소스 압박 상황에서도 base64로 저하되지 않는 결정적 URL 출력이 제공되며, 마크업 없이 1배 요율 배수가 적용됩니다.
공식 릴레이 gpt-image-2은 이 매개변수를 지원하지 않으며, 전송하면 400 unknown_parameter을 반환합니다. 현재 공식 릴레이에서 사용할 수 있는 유일한 출력 경로는 base64입니다.
2

응답 본문 크기 줄이기

base64를 사용해야 하는 경우: output_compression과 함께 output_format=jpeg을 사용하면 PNG보다 크기를 절반 이상 줄일 수 있습니다. size 및 quality은 기본값인 4K 대신 실제로 필요한 수준으로 낮추십시오. 입력 참조 이미지를 1.5MB 미만으로 압축하면 업로드 단계에도 도움이 됩니다.
3

대역폭이 지원하는 수준으로 동시 실행 수 제한

위의 공식을 뒤집어 계산하십시오. 허용 가능한 다운로드 시간 × 송신 대역폭 ÷ 이미지당 크기가 동시 실행 수의 상한입니다. 이 상한을 넘으면 동시 실행 수를 늘려도 전체 처리량은 증가하지 않고 모든 요청만 느려집니다. 모델별 제한은 사용할 수 있는 동시 실행 수는 얼마입니까?에서 확인할 수 있습니다.
4

타임아웃을 세 가지로 나누고, 데이터가 완료되면 선제적으로 종료

위에서 설명한 대로 첫 바이트, 청크 간격, 완료 유예 타임아웃을 각각 설정하십시오. 데이터가 완료되었지만 완료 신호가 도착하지 않는 경우, 이미 보유한 응답을 애플리케이션에 전달하십시오 — 전체 호환성 코드는 이미지 요청 완료 지연에 있습니다.

일반적인 질문

과금은 게이트웨이가 처리를 완료할 때 발생하며, 그 시점까지 업스트림은 실제로 결과를 생성하고 반환했기 때문입니다. 이후 클라이언트가 결과를 수신하게 되는지는 이미 발생한 비용을 변경하지 않습니다. 측정 비교 결과, 5초 후 연결을 끊은 클라이언트도 완료될 때까지 실행한 클라이언트와 정확히 동일하게 과금됩니다.이를 반대로 생각하면 가장 강력한 진단 기준이 됩니다. 과금 기록이 있다는 것은 요청이 실제로 업스트림에 도달하여 성공했다는 의미이므로, 문제는 게이트웨이가 처리를 완료한 이후 또는 요청이 실제로 전송되기 이전에 있을 수 있습니다. 업스트림을 의심할 필요는 없습니다.이미지 엔드포인트에는 비동기 작업 ID가 없으므로 연결이 끊기면 결과를 잃게 됩니다. 비동기 이미지 API가 있습니까?를 참조하십시오.
경우에 따라 다릅니다. 바로 그렇기 때문에 변경하기 전에 먼저 측정해야 합니다.
  • 다운로드가 느린 경우(속도는 낮지만 바이트 수가 계속 증가함): 예. 늘리면 결과를 받을 수 있습니다.
  • 완료 신호가 전혀 오지 않은 경우(바이트 수는 오래전에 완료되었고 마지막에 새로운 데이터가 없음): 아닙니다. 이 상태에서 새로운 바이트가 단 하나도 추가되지 않은 채 330초 동안 계속 기다린 사례가 측정되었습니다. 타임아웃을 늘리면 알아차리는 시점만 늦어집니다. 이 경우에는 클라이언트에서 능동적으로 완료해야 합니다.
어느 쪽일 수도 있으므로 먼저 측정해야 합니다. 양쪽을 구분하는 기준은 다음과 같습니다.
  • 사용자 측을 가리키는 경우: 명확하게 낮은 speed_download, 동시 실행 수가 증가할수록 낮아지는 속도, mtr의 패킷 손실 또는 curl은 정상적으로 동작하지만 애플리케이션 코드만 타임아웃되는 경우입니다.
  • 저희 측을 가리키는 경우: 바이트 수는 오래전에 완료되었지만 마지막에 새로운 데이터가 전혀 없는 긴 구간이 있는 경우입니다. 게이트웨이에는 실제로 완료 신호가 지연되는 문제가 있었습니다. 원인은 이미지 경로의 과금 집계가 요청 처리를 차단한 것이었으며, 2026년 8월 13일 업스트림 릴리스로 수정 및 검증되었습니다. 완전히 정상적인 기간에도 요청의 약 4%는 데이터가 이미 모두 전달된 상태에서 완료 신호를 받기까지 추가로 10~79초를 기다립니다.
측정이 끝나면 구간별 측정값을 저희에게 보내 주십시오. 단순히 느리다고 말하는 것보다 훨씬 구체적으로 조치할 수 있습니다. 포함해야 할 필드는 다음 섹션에 나와 있습니다.
현재 이미지 생성은 전부 동기 방식이며, 작업 ID를 조회할 수 있는 엔드포인트는 없습니다. 비동기 옵션을 준비 중이며, 제공이 시작되면 별도로 안내할 예정입니다.그때까지는 자체적으로 비동기 래퍼를 구현하는 방법을 권장합니다. 제출 시 로컬 작업 ID를 반환하고 백그라운드 작업자가 동기 호출을 수행하도록 하십시오. 자체 비동기 큐 구축을 참조하십시오.
어느 유형에 해당하는지에 따라 다릅니다. 대역폭 부족은 이그레스의 특성이므로 저희의 진입 주소를 변경해도 아무런 효과가 없습니다. 더 많은 대역폭, 더 작은 페이로드 또는 더 낮은 동시 실행 수가 필요합니다. 완료 신호 유형의 문제는 특정 시간 구간에 여러 진입점에서 동시에 나타났다가 동시에 복구되었으므로 도메인을 변경해도 우회할 수 없습니다.피해야 할 주소는 CDN 노드 하나입니다. api-cf.apiyi.com는 Cloudflare를 거치며 약 100초 후 524을 반환하므로, 장시간 실행되는 이미지 요청에는 적합하지 않습니다.

쉽게 놓치는 클라이언트 측 원인 3가지

curl로 측정했을 때는 문제가 없고 애플리케이션 코드에서만 타임아웃이 발생한다면 다음을 확인해야 합니다.
  1. 타임아웃이 생각하는 의미와 다릅니다. 600초가 전체 타임아웃입니까, 아니면 읽기 타임아웃만 의미합니까? Node의 undici에는 서로 독립적인 세 가지 타임아웃인 headersTimeout, bodyTimeout, connect.timeout가 있으며, 기본값은 외부 계층에서 설정한 값보다 훨씬 짧습니다. 외부 계층의 타임아웃만 변경하면 아무런 효과가 없습니다.
  2. 연결 풀 대기열입니다. 풀이 포화되면 요청이 실제로 전송되기 전에 시간이 시작됩니다. 이 대기 시간은 완전히 보이지 않습니다. 요청이 실제로 전송될 때까지 백엔드 로그에 해당 요청 기록이 남지 않습니다. 진단 방법: 일치하는 로그 기록이 일반적으로 없다면 이 유형일 가능성이 높습니다.
  3. 중간에 다른 계층이 있습니다. 자체 호스팅 nginx는 기본적으로 proxy_read_timeout를 60초로 설정하며, 로드 밸런서, API 게이트웨이, 서버리스 플랫폼도 각각 자체적인 상한을 적용합니다. 모든 중간 구간의 타임아웃을 나열해야 합니다. 가장 작은 값이 실제 타임아웃입니다.

보고 시 포함할 내용

자가 점검 후에도 도움이 필요하다면, 여러 차례의 추가 확인을 줄일 수 있도록 다음 정보를 함께 보내주시기 바랍니다.
  • 요청 ID (전체가 아닌 몇 개면 충분합니다)
  • 세그먼트별 소요 시간: 첫 바이트까지의 시간 / 마지막 바이트 시간 / 총 소요 시간 / 응답 본문 바이트 수
  • 발생 시점, 시간대 포함 (예: 2026-08-13 15:57 (UTC+8))
  • 당시 동시 실행 수 및 이그레스 대역폭
  • 사용 중이던 모델 및 token 그룹

관련 문서

API 시간 초과를 방지하려면 어떻게 해야 합니까?

시나리오별 권장 시간 초과 및 엔드포인트 선택

이미지 요청 완료 시 멈춤

데이터가 완료되었지만 연결이 종료되지 않을 때의 클라이언트 측 처리

이미지 API 연결 끊김

ECONNRESET 및 SSL EOF 유형의 다운스트림 연결 끊김 진단

사용할 수 있는 동시 실행 수는 얼마입니까?

모델별 동시 실행 수 제한 및 쿼터 요청

이미지 API 모범 사례

모델별 시간 초과 요약표 및 출력 형식 비교

로그에서 과금 금액 확인하기

각 콘솔 로그 열의 의미와 과금 기록 방식

문의하기

WeCom 지원

WeCom 지원 QR 코드QR 코드를 스캔하거나 지원팀에 문의하십시오이미지 시간 초과 및 느린 다운로드 진단

이메일