Measure request timing

요청의 각 단계(DNS·연결·TLS·첫 바이트·전체) 소요 시간을 측정해 지연의 원인을 구간별로 파악하는 레시피입니다.

개요

요청의 각 단계(DNS·연결·TLS·첫 바이트·전체) 소요 시간을 측정해 지연의 원인을 구간별로 파악하는 레시피입니다.

코드로 보기

curl -o /dev/null -s -w \
'dns:      %{time_namelookup}s\nconnect:  %{time_connect}s\ntls:      %{time_appconnect}s\nttfb:     %{time_starttransfer}s\ntotal:    %{time_total}s\n' \
  https://api.example.com/data
const t0 = performance.now();
const res = await fetch('https://api.example.com/data');
const ttfb = performance.now();
await res.arrayBuffer();
const done = performance.now();
console.log(`ttfb ${(ttfb - t0).toFixed(1)}ms, total ${(done - t0).toFixed(1)}ms`);
import requests

res = requests.get('https://api.example.com/data')
# elapsed = send -> last byte of headers received
print('elapsed:', res.elapsed.total_seconds(), 's')

설명

curl의 `-w`(write-out)는 전송이 끝난 뒤 타이밍 변수를 출력합니다. 핵심 변수는 `time_namelookup`(DNS), `time_connect`(TCP 연결), `time_appconnect`(TLS 핸드셰이크 완료), `time_starttransfer`(TTFB=첫 바이트까지), `time_total`(전체)입니다. `-o /dev/null -s`로 본문과 진행률을 버려 숫자만 깔끔히 봅니다.

이 변수들은 누적값이라 각 구간의 순수 소요 시간은 뺄셈으로 구합니다. 예: TLS 순수 시간 = `time_appconnect - time_connect`. TTFB가 크면 서버 처리 지연, `namelookup`이 크면 DNS 문제, `connect`가 크면 네트워크 왕복(RTT) 지연을 의심합니다.

브라우저에서는 `performance.now()`나 Resource Timing API로, `requests`에서는 `res.elapsed`로 대략을 잽니다. 다만 `res.elapsed`는 본문 다운로드 시간을 포함하지 않는 점에 유의하세요. 서버가 `Server-Timing` 헤더를 주면 서버 내부 처리 시간을 세부적으로 받을 수 있습니다. 정확한 벤치마크는 캐시·keep-alive 영향을 줄이도록 여러 번 반복 측정하세요.

관련 헤더

관련 상태코드