TTFB(Time to First Byte): 정의, 측정 방법, 최적화 가이드
TTFB는 HTTP 요청과 브라우저가 첫 번째 응답 바이트를 수신하는 시점 사이의 지연을 측정합니다. Google의 기준은 field data(P75) 기준 800ms 미만입니다. 가장 흔한 원인은 페이지 cache 부재, query parameter로 인한 cache 희석, 최적화되지 않은 DB 쿼리, CDN 부재입니다. 서버 측에서는 full-page cache를 통해 20-50ms로 단축할 수 있으며, 올바르게 설정된 CDN은 모든 지역으로 이 성능 향상을 확장합니다.
TTFB(Time to First Byte)는 HTTP 요청과 브라우저가 첫 번째 응답 바이트를 수신하는 시점 사이의 지연을 측정합니다. Google의 기준은 field data(P75) 기준 800ms 미만입니다. 가장 흔한 원인은 페이지 cache 부재, query parameters로 인한 cache 희석, 최적화되지 않은 DB 쿼리, CDN 부재입니다. 서버 측에서는 full-page cache를 통해 20-50ms로 단축할 수 있으며, 올바르게 설정된 CDN은 이 성능 향상을 모든 지역으로 확장합니다. SFCC 기반 e-commerce 사이트에서 cache key 정규화를 통해 cache 희석률을 80% 줄이고, field data 기준 Server Response가 0.74s에서 0.63s로 15% 개선되었습니다.
TTFB: 정의 및 Google 기준
TTFB는 브라우저가 HTTP 요청을 전송한 시점부터 서버 응답의 첫 번째 바이트를 수신하는 시점까지의 시간을 측정합니다. 이 지연은 세 가지 요소로 구성됩니다. 네트워크 지연(DNS + TCP + TLS 왕복), 서버 처리 시간(애플리케이션 실행, DB 쿼리, 응답 렌더링), 그리고 서버 측의 잠재적 대기 시간입니다.
Google은 TTFB에 대해 세 가지 성능 수준을 정의합니다.
| 수준 | 기준 | 상태 |
|---|---|---|
| 양호 | < 800ms | 초록 |
| 개선 필요 | 800ms ~ 1,800ms | 주황 |
| 불량 | > 1,800ms | 빨강 |
이 기준은 75번째 백분위수(P75) field data에 적용됩니다. 실제 방문의 75%가 양호 판정을 받으려면 800ms 미만이어야 합니다.
네트워크 waterfall에서 TTFB의 위치
TTFB는 페이지 로딩의 첫 번째 단계입니다. 내비게이션 waterfall에서 TTFB는 모든 것보다 앞서 있습니다. 첫 번째 바이트가 도착하기 전에는 HTML parser가 시작될 수 없고, 파싱 전에는 중요 리소스(CSS, 폰트, LCP 이미지)가 발견될 수 없으며, 시각적 요소가 렌더링되기 전에는 LCP가 트리거될 수 없습니다. TTFB가 800ms라면 브라우저가 작업을 시작하기 전에 이미 LCP 예산의 800ms를 소비한 것입니다. LCP 목표가 2.5s라면 TTFB가 1.2s일 경우 나머지 모든 작업에 1.3s밖에 남지 않습니다.
TTFB 측정 방법
Chrome DevTools (일회성 진단)
DevTools(F12)를 열고 Network 탭에서 첫 번째 HTML 요청을 클릭한 후 Timing 패널을 확인합니다. "Waiting for server response" 항목이 순수 서버 처리 시간입니다. 활용 사례: 문제가 네트워크(DNS/TCP/TLS 높음)에서 비롯된 것인지, 서버(Waiting 높음)에서 비롯된 것인지 빠르게 파악할 수 있습니다. DNS/TCP/TLS가 정상인데 Waiting이 900ms라면 애플리케이션 문제를 의미합니다.
WebPageTest (제어된 벤치마크)
WebPageTest는 특정 도시에 위치한 에이전트에서 시뮬레이션된 네트워크 환경(Moto G4, 4G)으로 TTFB를 측정합니다. 활용 사례: 프랑스 e-commerce 사이트를 모바일 프로파일로 "Paris, France"에서 벤치마크하거나, CDN이 없거나 잘못 설정되어 있음을 나타내는 지역적 차이(파리에서 1.2s, 싱가포르에서 3.8s)를 식별할 수 있습니다.
Google Search Console (P75 field data)
Search Console은 CrUX 데이터를 통해 28일 이동 평균 P75로 집계된 TTFB를 보고합니다. 활용 사례: 모든 네트워크와 위치를 아우르는 실제 사용자의 TTFB를 파악할 수 있습니다. WebPageTest(양호)와 GSC(불량) 사이의 차이는 흔히 CDN의 지역 커버리지 부족이나 실제 트래픽 부하 하에서 성능이 저하되는 서버를 나타냅니다.
TTFB가 높은 5가지 주요 원인
1. 페이지 cache 부재
가장 흔하고 영향력이 큰 원인입니다. Cache가 없으면 모든 요청이 전체 애플리케이션 체인을 트리거합니다. 라우팅, 인증, DB 쿼리, 템플릿 렌더링, 응답 직렬화가 모두 실행됩니다. 표준 CMS나 e-commerce에서는 복잡도에 따라 300ms에서 2s까지 소요됩니다. full-page cache를 사용하면 동일한 응답이 5-50ms 내에 메모리에서 제공됩니다.
2. Query parameters로 인한 cache 희석
Cache는 있지만 cache hit rate가 매우 낮습니다. 원인: 각 URL 파라미터 조합(?color=red&size=L&sort=price_asc)이 별도의 cache key를 생성합니다. 각각 5개의 값을 가진 필터가 20개 있는 e-commerce 카탈로그에서는 수천 개의 조합이 발생하며, 대부분은 캐시가 워밍업되지 않습니다. 결과적으로 대부분의 요청이 cache miss가 되어 cache가 존재함에도 TTFB가 높게 유지됩니다.
3. 느리거나 인덱스가 없는 DB 쿼리
5개의 동적 콘텐츠 블록(추천 상품, 재고, 리뷰, 개인화 가격, 패싯 내비게이션)을 로드하는 상품 페이지는 20~50개의 SQL 쿼리를 트리거할 수 있습니다. 필터링되는 컬럼에 적절한 인덱스가 없으면 각 쿼리가 full table scan을 수행합니다. 50만 개 상품 카탈로그에서 product_category_id에 인덱스가 없는 쿼리는 단독으로 800ms가 걸릴 수 있습니다.
4. CDN 부재 또는 caching이 설정되지 않은 CDN
완벽한 서버 cache가 있더라도 네트워크 지연은 피할 수 없습니다. 프랑스의 서버와 싱가포르의 사용자 사이에서 네트워크 왕복만으로 150-200ms가 추가됩니다. DNS + TCP + TLS + 요청에 3-4번의 왕복이 발생하면 서버가 아무것도 처리하기 전에 기계적인 TTFB가 600-800ms에 달합니다. edge caching이 있는 CDN은 로컬 노드에서 응답을 제공함으로써 이 문제를 해결합니다.
5. 동기적으로 실행되는 무거운 연산
일부 처리는 중요 경로에서 동기적으로 실행됩니다. 개인화 가격 계산, 서드파티 API 블로킹 호출(번역, 개인화, 실시간 추천) 등이 해당됩니다. 동기적 경로에서 타임아웃이 2s인 서드파티 API 호출은 장애 발생 시 TTFB 최솟값을 2s로 고정시킵니다. 해결책은 이러한 결과를 cache하거나 비동기로 이동시키는 것입니다.
서버 측 TTFB 최적화
Full-page cache
Full-page cache는 최종 HTML 응답을 직렬화하여 메모리(Redis, Memcached)나 디스크에 저장합니다. 동일한 URL에 대한 이후 요청은 DB나 애플리케이션을 거치지 않고 cache에서 제공됩니다. 일반적인 성능 향상: cache 없이 800ms-2s에서 Redis cache 사용 시 20-80ms로 단축됩니다. Laravel, Nginx FastCGI Cache, Varnish에서는 개인화 없는 공개 페이지에 즉시 적용할 수 있습니다.
// Laravel: Redis를 사용한 간단한 페이지 cache
Route::get('/produit/{slug}', function ($slug) {
return Cache::remember("page:produit:{$slug}", 3600, function () use ($slug) {
$produit = Product::with(['images', 'variants', 'category'])
->where('slug', $slug)->firstOrFail();
return view('produit', compact('produit'))->render();
});
});
Cache key 정규화 (희석 방지)
목표는 제공되는 콘텐츠를 변경하지 않는 파라미터를 제외하여 별개의 cache key 수를 줄이는 것입니다. JavaScript로 선택된 색상 필터는 페이지의 원시 HTML을 변경하지 않으며 클라이언트 측 UI 선택만 변경됩니다.
// 정규화된 cache key 생성: 구조적이지 않은 파라미터 제외
function buildCacheKey(Request $request): string {
$structuralParams = ['page', 'category', 'brand']; // 콘텐츠에 영향을 미치는 파라미터
// 제외되는 파라미터: color, size, sort, utm_source, ref...
$params = $request->only($structuralParams);
ksort($params); // 중복 방지를 위한 알파벳 순 정렬
return 'page:' . $request->path() . ':' . md5(serialize($params));
}
DB 최적화
두 가지 고영향 조치: 필터링 컬럼 인덱싱과 페이지당 쿼리 수 감소입니다.
-- 카테고리와 가격으로 필터링된 상품 목록을 위한 복합 인덱스
CREATE INDEX idx_products_category_price
ON products (category_id, price, status)
WHERE status = 'active'; -- 부분 인덱스: 비활성 상품 제외
인덱스 추가 전에 EXPLAIN ANALYZE(PostgreSQL) 또는 EXPLAIN(MySQL/MariaDB)을 사용하여 full table scan을 식별합니다. 50만 행 테이블에서의 full scan은 항상 200ms 이상 소요됩니다.
PHP 및 SFCC: 애플리케이션 처리 시간 단축
네이티브 PHP에서 OPcache를 활성화하면 요청마다 스크립트를 재컴파일하는 과정이 제거됩니다(PHP 실행 시간에서 60-80% 성능 향상). SFCC에서는 Business Manager를 통한 파이프라인 caching으로 어떤 라우트가 애플리케이션 cache를 사용하는지와 TTL을 제어할 수 있습니다. 렌더링 파이프라인에서 동기 API 호출을 수행하는 커스텀 cartridge는 SFCC 측 높은 TTFB의 주요 원인입니다.

현장 경험 — Query parameters로 인한 SFCC cache 희석.
한 럭셔리 브랜드 SFCC 사이트(수천 개 SKU 카탈로그)에서 애플리케이션 cache가 설정되어 있었음에도 TTFB가 높게 유지되었습니다. 분석 결과, color, size, sort 파라미터가 한 번도 방문되지 않은 조합을 포함하여 모든 URL 조합에 대해 별도의 cache key를 생성하고 있었습니다. 겉보기에는 cache가 설정된 것처럼 보였지만 cache hit rate는 거의 0에 가까웠습니다. 조치 사항: SFCC cache key 정규화(key 계산에서 구조적이지 않은 파라미터 제외) 및 페이지 유형별 맞춤 TTL을 적용한 고급 애플리케이션 cache 구현. field data RUM 결과: cache 희석률 80% 감소, Server Response 0.74s에서 0.63s로 개선(-15%). 교훈: 잘못 설정된 cache는 cache가 없는 것만큼 비용이 많이 들 수 있으며, 인프라 관련 결정을 내리기 전에 반드시 희석 감사를 먼저 수행해야 합니다.
CDN으로 TTFB 줄이기
Edge caching
edge caching이 있는 CDN은 사용자와 가장 가까운 곳에 HTML 응답을 저장합니다. 도쿄의 사용자가 페이지를 로드하면 파리의 서버가 아닌 도쿄 노드에서 응답이 제공됩니다. 네트워크 지연이 150-200ms에서 5-20ms로 줄어듭니다. 작동 조건: 응답이 cache 가능해야 합니다(Cache-Control: public, max-age=3600). Set-Cookie 또는 Cache-Control: private이 있는 응답은 edge에서 cache되지 않으며 항상 origin에 도달합니다.
# Nginx: 상품 페이지에서 CDN edge caching을 활성화하는 headers
location ~* ^/produit/ {
add_header Cache-Control "public, max-age=3600, stale-while-revalidate=300";
add_header Vary "Accept-Language"; # 언어별로만 변경
proxy_hide_header Set-Cookie; # 쿠키가 CDN cache를 차단하지 않도록
proxy_pass http://backend;
}
Cloudflare와 Akamai: 고급 설정
query parameter 정규화는 CDN 레벨에서도 직접 설정할 수 있습니다. Cloudflare의 Cache Rules를 사용하면 edge cache key에 포함할 파라미터를 정확하게 지정할 수 있습니다. 정렬 및 UI 필터 파라미터를 제외하면 고유 cache 항목 수가 크게 줄어들며, 이는 애플리케이션 측 정규화와 동일한 효과입니다.
트래픽이 많은 인프라에서는 Akamai 설정이 세밀한 제어를 제공합니다. SureRoute는 origin 서버까지의 네트워크 경로를 최적화하고, Property Manager는 edge cache key를 관리하며, Cache-Control Modification Behavior는 애플리케이션 코드를 변경하지 않고 origin의 cache header를 재정의합니다. 상품 페이지의 cache hit ratio가 85% 미만이면 cache dilution 또는 TTL이 너무 짧다는 첫 번째 신호입니다.
Early Hints HTTP 103
HTTP 103 Early Hints는 완전한 200 응답이 준비되기 전에 서버가 Link: rel=preload 지시어를 전송할 수 있게 합니다. 브라우저는 서버가 페이지를 생성하는 동안 중요 리소스(CSS, 폰트, LCP 이미지)를 미리 로드합니다. TTFB가 600ms인 경우 Early Hints는 TTFB 자체를 건드리지 않고 중요 CSS와 브랜드 폰트를 병렬로 미리 로드하여 LCP를 200-400ms 줄일 수 있습니다. Nginx는 버전 1.25.1부터 HTTP 103을 지원하며, Cloudflare와 Akamai는 서버 설정 없이 edge에서 기본으로 전달합니다.
웹 성능 감사나 전반적인 서버 최적화 계획의 맥락에서 TTFB를 종합적으로 분석하려면 이러한 리소스에서 우선순위 지정과 다음 단계를 다룹니다.
출처
- Web Vitals — Time to First Byte (TTFB) — Google web.dev
- Optimize TTFB — Google web.dev
- HTTP 103 Early Hints — MDN Web Docs
- CrUX Dashboard — Chrome Developers