TTFB
Time to First Byte
지표
브라우저가 요청을 보낸 뒤 응답의 첫 바이트가 도착할 때까지 걸린 시간으로, 화면이 그려지기 전 구간을 잽니다.
등장 배경
화면이 늦게 뜬다는 제보를 받으면 손대는 곳이 정해져 있던 시절이 있었습니다. 이미지를 줄이고 코드를 쪼개고 글꼴을 가볍게 바꿉니다. 화면에 보이는 것들이니 원인도 거기 있을 것 같습니다.
그런데 그렇게 해도 숫자가 움직이지 않는 경우가 많았습니다. 첫 화면 이미지를 1메가바이트에서 300킬로바이트로 줄였는데 페이지가 뜨는 시간은 3초에서 2.9초가 됩니다. 이미지를 받는 구간이 짧아진 것은 맞지만, 그 앞에 브라우저가 아무것도 못 하고 기다린 2.2초가 그대로 남아 있었습니다.
그 2.2초를 재는 값이 없었다는 것이 문제였습니다. 화면에 무엇이 그려졌는지를 재는 지표들은 이미 있었는데, 그 앞의 구간은 하나의 숫자로 묶여 있지 않았습니다. 그래서 프론트엔드만 반복해 고치고 원인은 서버와 망에 남는 상황이 이어졌습니다. TTFB 는 그 앞 구간을 하나의 값으로 떼어내, 화면을 고칠 문제인지 그 앞을 고칠 문제인지부터 가르게 만든 지표입니다.
계산 방법
요청을 보낸 시각과 응답의 첫 바이트가 도착한 시각의 차이입니다. 한 숫자이지만 안에 네 구간이 들어 있고, 줄이려면 어느 구간이 큰지부터 봅니다.
- 주소 조회입니다. 도메인 이름을 실제 서버 주소로 바꾸는 단계이고, 대개 20에서 120밀리초입니다. 처음 방문한 사용자에게만 생깁니다.
- 연결 수립입니다. 서버와 연결을 열고 암호화 설정을 맞추는 왕복이 여기 들어갑니다. 왕복이 필요하니 물리적 거리가 그대로 시간이 됩니다. 서울과 서버 사이가 멀면 이 구간만 200밀리초를 넘깁니다.
- 서버 처리입니다. 요청을 받아 응답을 만들기까지의 시간이고, 느린 페이지에서는 이 구간이 전체의 절반 이상을 차지합니다. 데이터베이스 질의가 대개 원인이고, 목록을 돌며 질의를 반복하는 N+1 문제가 여기서 자주 잡힙니다.
- 첫 바이트 전송입니다. 응답을 만든 뒤 첫 조각이 브라우저에 닿는 시간입니다.
재는 방법은 둘입니다. 하나는 실제 사용자의 브라우저에서 값을 모으는 것이고, 다른 하나는 정해진 조건에서 도구로 돌려 보는 것입니다. 앞엣것은 지역과 회선이 섞여 있어 실제를 보여 주고, 뒤엣것은 조건이 같아 변화를 비교하기 좋습니다. 둘 다 필요하고, 값을 볼 때는 평균이 아니라 중앙값과 75번째 백분위를 씁니다. 평균은 아주 느린 소수에 끌려갑니다.
좋은 수준의 기준
800밀리초 안쪽이면 좋은 수준이고, 1.8초를 넘으면 손대야 하는 쪽입니다. 이 선은 화면이 아무것도 없는 상태로 사용자가 기다리는 시간이라는 점에서 정해졌습니다. 1초가 넘으면 사람은 페이지가 멈췄는지 의심하기 시작합니다.
구간별로 나눠 보면 목표가 더 분명해집니다. 주소 조회와 연결 수립을 합쳐 200밀리초 안, 서버 처리를 400밀리초 안에 두면 전체가 800밀리초 아래로 들어옵니다. 어느 구간이 이 선을 넘는지 보면 고칠 곳이 바로 정해집니다.
지역을 함께 봐야 합니다. 서버가 한 지역에만 있으면 지구 반대편 사용자는 왕복만으로 300밀리초를 씁니다. 이때는 코드를 고쳐서 줄일 수 없고, 자원을 가까운 거점에서 내려 주는 CDN을 앞에 두거나 서버를 지역별로 늘려야 합니다. 국내 사용자만 보는 숫자로 판단하면 해외 고객이 겪는 2.4초가 보이지 않습니다.
캐시가 걸린 요청과 안 걸린 요청을 갈라 보는 것도 필요합니다. 한 번 만든 결과를 저장해 두고 다시 쓰는 것을 캐싱이라 하는데, 캐시에 있으면 서버 처리가 10밀리초로 끝납니다. 두 경우를 섞으면 중앙값이 300밀리초로 예쁘게 나오는데 캐시가 없는 사용자는 1.6초를 기다리고 있습니다.
이 값이 뒤따르는 지표의 바닥이 된다는 점도 함께 봅니다. TTFB 가 1.2초면 가장 큰 콘텐츠가 그려지는 시점은 절대 1.2초 아래로 내려가지 않습니다. 화면 쪽을 아무리 손봐도 그렇습니다.
실무 용례
"이미지 줄여도 안 바뀌어요. TTFB 가 2.2초입니다."
원인이 화면 앞 구간에 있다는 말입니다.
"서버 처리만 1.4초예요. 질의를 먼저 보죠."
네 구간 중 어디가 큰지 특정한 것입니다.
"국내는 300밀리초인데 해외는 2.4초예요."
지역을 섞어 보면 안 된다는 지적입니다.
페이지덱 문서 화면에서 태오가 이 값을 두 달에 걸쳐 1.9초에서 600밀리초로 줄였습니다. 처음에 구간을 나눠 보니 서버 처리가 1.5초였고, 문서 목록을 그리면서 문서마다 작성자를 따로 불러오는 질의가 원인이었습니다.
질의를 한 번으로 합쳐 서버 처리가 400밀리초가 됐고, 그다음에 해외 고객 값을 따로 뽑아 보니 여전히 2.1초였습니다. CDN 을 앞에 두어 정적 자원과 일부 응답을 가까운 거점에서 내려 주게 하자 1.1초가 됐습니다. 두 작업의 성격이 달랐고, 구간을 나눠 보지 않았으면 순서를 정할 수 없었습니다.
흔한 오해
이 값만 줄이면 페이지가 빨라진다고 보는 경우가 가장 많습니다. 앞 구간이니 앞을 줄이면 전체가 줄어든다는 계산은 맞습니다. 하지만 이것은 바닥을 낮추는 일이고, 바닥을 낮춰도 그 위에 쌓인 것이 두꺼우면 화면은 늦게 뜹니다. TTFB 를 1.9초에서 400밀리초로 줄였는데 첫 화면이 여전히 3초에 뜨는 경우가 있고, 그때 남은 2.6초는 이미지와 글꼴과 코드 실행 쪽에 있습니다. 두 구간은 따로 재고 따로 고칩니다.
서버 문제를 가리키는 값이라고 읽는 것도 자주 나옵니다. 이름에 응답이 들어 있고 실제로 서버 처리가 가장 큰 경우가 많으니 그렇게 들립니다. 그런데 안에 든 네 구간 중 서버가 맡는 것은 하나뿐입니다. 주소 조회가 느린 것은 도메인 설정 문제이고, 연결 수립이 느린 것은 거리와 회선 문제이며, 둘 다 서버 코드를 고쳐서는 줄지 않습니다. 구간을 나눠 보지 않고 서버부터 손댄 팀은 질의를 다 최적화한 뒤에도 값이 1.4초에 머무는 것을 보고서야 원인이 다른 데 있었다는 것을 알게 됩니다.
자주 헷갈리는 용어
| 용어 | 무엇이 끝나는 시점인가 | TTFB 와의 차이 |
|---|---|---|
| LCP | 화면에서 가장 큰 덩어리가 그려진 시점 | 사용자가 페이지를 봤다고 느끼는 순간까지를 잽니다. TTFB 가 그 안에 들어 있어서, 이 값은 TTFB 보다 작아질 수 없습니다 |
같이 보면 좋은 페이지
마지막 업데이트 2026-09-16