Skip to main content

짧은 답변

콘솔 로그의 지속 시간과 클라이언트의 타임아웃은 같은 구간을 측정하지 않습니다.
  • 로그의 지속 시간은 게이트웨이가 처리를 완료하는 시점까지 계산됩니다.
  • 클라이언트는 응답 본문의 마지막 바이트가 도착하고 연결이 완료되었음을 알릴 때까지 끝난 것이 아닙니다.
따라서 “로그에는 280초에 완료되었다고 나오는데, 600초 타임아웃이 지나도 데이터가 오지 않았다”는 상황은 충분히 가능합니다 — 그리고 그 요청은 실제로 성공했고 실제로 과과금되었습니다. 그 차이는 로그가 전혀 포함하지 않은 구간에 있습니다.이 페이지에서는 그 차이를 측정하고, 특정 구간으로 정확히 짚어내며, 올바른 원인으로 처리하는 방법을 보여드립니다.
이 페이지는 대용량 응답을 반환하는 비스트리밍 호출에 대한 내용입니다. base64를 반환하는 이미지 엔드포인트가 대표적인 경우이며(응답 본문은 수 MB에서 수십 MB까지 커질 수 있음), 비스트리밍 장문 텍스트 출력도 동일하게 동작합니다. 스트리밍 호출과 작은 응답은 일반적으로 영향을 받지 않습니다.

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

한 호출의 전체 지연 시간은 다섯 구간으로 나뉩니다:
이 차이는 어떤 로그 필드에도 나타나지 않습니다.당사는 내부에서 제어된 raw-socket 비교를 수행했습니다. 같은 요청 배치에 대해 백엔드는 성공 상태와 함께 5초의 지속 시간을 기록했지만, 클라이언트는 완전한 응답을 받기까지 실제로 3740초를 기다렸습니다. 그 3135초는 게이트웨이가 처리를 마친 뒤에 발생했으며, 어떤 지속 시간 필드에도 기록되지 않았습니다.즉, “내 쪽에서는 엄청 오래 걸렸다”는 주장을 반박하려고 로그 지속 시간을 인용해도 아무 의미가 없습니다 — 두 숫자는 애초에 충돌한 적이 없습니다. 문제를 찾으려면 클라이언트에서 구간별 시간을 측정해야 합니다.
콘솔과 Log Query API에서 확인할 수 있는 필드: duration_for_view(호출 지속 시간, 초 단위), is_stream, 그리고 request_id(문제를 보고할 때는 이 값을 인용하십시오).

1단계: curl 한 번으로 간격을 세그먼트에 고정합니다

이것이 아래 모든 내용의 진입점입니다. 먼저 실행한 다음, 어떤 섹션이 적용되는지 판단하십시오.
세 가지 파생 지표는 그 원시 수치를 의미 있는 세그먼트로 변환합니다:

결과 읽기

아래 표와 여러분의 수치를 대조하십시오. 다음에 무엇을 해야 할지 이 표가 결정합니다:
한 번의 실행만으로는 충분하지 않습니다. 이 종류의 문제는 시간 창 단위로 나타납니다 — 어떤 창 안에서는 연속 호출이 모두 영향을 받지만, 그 밖에서는 수십 번의 연속 호출도 완전히 정상입니다. 10번 실행하고 분포를 확인한 뒤, 시간대와 함께 시각을 기록하십시오.

2단계: “데이터는 도착했지만 연결은 끝나지 않았다” 측정하기

표가 세 번째 행을 가리킨다면 더 세밀하게 관찰해야 합니다: 응답을 청크 단위로 읽으면서 각 청크의 도착 시각과 그 사이의 간격을 기록하십시오. 답해야 할 질문은 — 마지막 byte가 도착한 뒤 연결은 얼마나 더 유지되었습니까?
검출 임계값: 30초를 초과한 tail_99 또는 30초를 초과한 max_gap는 한 번의 “tail stall”로 간주합니다. 특징은 byte 수가 이미 100%에 도달한 시점에서 발생하는 max_gap입니다 — 모든 byte가 도착한 뒤에야 기다림이 시작됩니다.
세 단계를 하나의 timeout 값으로 묶지 마십시오.이것이 가장 쉬운 함정입니다: “첫 byte를 기다리는 중”과 “전송을 기다리는 중”에 하나의 timeout을 사용하면, 근본 원인이 완전히 다른 두 문제를 구분할 수 없는 하나의 실패로 합쳐 버립니다.이들을 분리하면 로그만 봐도 그것이 “느린 생성”인지, 아니면 “전달되었지만 끝나지 않음”인지 바로 알 수 있습니다 — 추측할 필요가 없습니다.

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

직접 소유한 두 머신 간

실제 처리량을 측정하려면 iperf3를 사용하십시오 — 가장 정확한 옵션입니다:

서버에서 저희 API로

iperf3는 이 구간에서는 사용할 수 없습니다 — 저희는 iperf 서버를 운영하지 않습니다. 대신 실제 호출을 통해 실효 속도를 측정하십시오:
링크 품질 확인과 함께 사용하십시오:
측정 표가 “끝 신호가 오지 않았습니다”를 가리킨다면, mtrping는 여기서는 쓸모가 없습니다. 그 경우 바이트 하나도 손실되지 않았고 링크 품질도 양호하므로, 이러한 도구들은 아무 문제도 보여주지 않을 것입니다 — 즉, 엉뚱한 원인을 추적하게 됩니다. 네트워크를 조사하기 전에 위 스크립트로 자신이 어느 범주에 속하는지 확인하십시오.

대역폭이 충분한지 확인하십시오

이미지 응답 본문은 base64가 하나로 뭉친 덩어리입니다. 측정된 크기는 다음과 같습니다: Base64 인코딩 자체가 페이로드를 대략 33% 팽창시킵니다. 자기 자신과의 링크를 기준으로 한 다운로드 시간은 다음과 같습니다: 문제는 이 표가 자기 자신과의 링크가 있다고 가정한다는 점입니다. 실제로는:
예를 들어 10 Mbps 아웃바운드, 이미지 요청 30개 동시 실행, 응답당 2.6 MB라면 — 각 요청은 대략 0.04 MB/s를 받게 되므로 다운로드만 62초가 걸립니다, 그리고 그 62초 중 어느 1초도 콘솔 로그에 나타나지 않습니다. 동시 실행 수를 두 배로 늘리면 그 수치도 두 배가 됩니다.
이것이 바로 “혼잡한 낮에는 시간이 초과되지만 밤에는 같은 코드가 잘 동작합니다”라는 현상의 이유입니다. 모델이 느려진 것이 아니라, 대역폭이 더 많은 요청에 나뉘어 사용되고 있는 것입니다.

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

증상을 정확히 설명하려면 — 자체 분석을 위해서든 저희에게 보내기 위해서든 — 호출마다 최소한 다음 항목을 기록하십시오. 마지막 열은 사람들이 자주 건너뛰지만, 사실 결론 그 자체인 경우가 많습니다. 속도와 동시 실행 수를 그래프로 그려서 동시 실행 수가 늘어날수록 속도가 비례해서 떨어진다면, 병목은 대역폭이며 더 찾을 것은 없습니다. 표를 사용하는 방법: 콘솔 로그의 duration_for_view와 나란히 놓고 보십시오 —
  • 서로 가깝다면 → 문제는 다운스트림 전송입니다. 대역폭과 동시 실행 수를 살펴보십시오;
  • 서로 멀다면 → 문제는 완료 신호 또는 클라이언트 측입니다.

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

1

URL 출력으로 전환하십시오 — 가장 효과가 큰 변경입니다

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

응답 본문을 줄이십시오

base64를 계속 사용해야 한다면: output_format=jpegoutput_compression를 사용하면 PNG보다 크기가 절반 이상 줄어듭니다. 4K를 기본값으로 두지 말고, sizequality를 실제로 필요한 수준으로 낮추십시오. 입력 참고 이미지를 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를 반환하므로, 긴 이미지 요청에는 적합하지 않습니다.

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

curl 측정이 정상이고 애플리케이션 코드에서만 타임아웃이 발생한다면, 여기에서 확인하십시오:
  1. 타임아웃이 여러분이 생각하는 의미가 아닐 수 있습니다. 600초가 전체 타임아웃입니까, 아니면 읽기 타임아웃만입니까? Node의 undici에는 서로 독립적인 타임아웃 세 가지 — headersTimeout, bodyTimeout, connect.timeout — 가 있으며, 기본값은 바깥 레이어에서 설정한 값보다 훨씬 낮고, 바깥쪽 값만 바꿔서는 아무 효과가 없습니다.
  2. 커넥션 풀 대기열입니다. 풀이 포화되면 시계는 요청이 실제로 전송되기 전에 시작됩니다. 그 대기 시간은 저희에게 완전히 보이지 않습니다 — 요청이 실제로 나갈 때까지 백엔드 로그에는 해당 요청의 기록이 없습니다. 진단: 일치하는 로그 기록이 없으면 일반적으로 이 경우입니다.
  3. 그 사이에 또 다른 레이어가 있습니다. 자체 호스팅 nginx는 기본적으로 proxy_read_timeout를 60초로 설정하며, 로드 밸런서, API 게이트웨이, 서버리스 플랫폼은 각각 자체 상한을 적용합니다. 각 홉의 타임아웃을 모두 확인하십시오. 가장 작은 값이 실제 타임아웃입니다.

보고할 때 포함할 내용

자체 점검 후에도 도움이 더 필요하면, 여러 번 주고받는 일을 줄이기 위해 아래 내용을 함께 보내 주십시오.
  • 요청 ID 몇 개면 충분하며, 전체를 모두 보낼 필요는 없습니다
  • 세그먼트별 시간: 첫 바이트까지의 시간 / 마지막 바이트까지의 시간 / 총 시간 / 응답 본문 bytes
  • 발생 시각, 시간대를 포함하여(예: 2026-08-13 15:57 (UTC+8))
  • 당시의 동시 실행 수와 출력 대역폭
  • 사용 중이던 모델token 그룹

관련 문서

API 타임아웃을 피하려면 어떻게 해야 합니까?

시나리오별 권장 타임아웃과 엔드포인트 선택

이미지 요청 종료 지연

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

이미지 API 연결 끊김

ECONNRESET 및 SSL EOF 유형의 다운스트림 연결 종료 문제 진단

얼마나 많은 동시 실행 수를 사용할 수 있습니까?

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

이미지 API 모범 사례

모델별 타임아웃 치트시트 및 출력 형식 비교

로그에서 과금 금액 읽기

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

문의하기

WeCom 지원

WeCom 지원 QR 코드QR 코드를 스캔하거나 지원팀에 문의이미지 타임아웃 및 느린 다운로드 진단

이메일