성능 튜닝 — 느린 쇼핑몰 빠르게
네트워크로 할 수 있는 마지막 한 뼘
마지막 강의입니다. 서버는 돌아가고, 안전하고, 감시도 붙었습니다. 이제 빠르게 만들 차례예요.
전자상거래에서 속도는 취향의 문제가 아닙니다. 페이지가 1초 느려지면 이탈률이 눈에 띄게 오르고, 그만큼 매출이 줄어요. 그리고 다행히, 네트워크 설정만으로 얻을 수 있는 개선이 꽤 큽니다.
한 페이지가 열리기까지
~20ms
~30ms
~50ms
~??ms
~??ms
손님이 첫 글자를 볼 때까지의 시간을 TTFB(Time To First Byte)라고 합니다. 위 그림에서 앞의 세 칸(DNS·TCP·TLS)은 아직 아무 내용도 안 받은 시간이에요. 연결 하나를 새로 맺는 데만 100ms가 날아갑니다.
① keep-alive — 연결을 재사용하기
페이지 하나에 이미지·CSS·JS가 30개 들어 있다고 합시다. 파일마다 연결을 새로 맺으면 악수 30번입니다. 3초가 그냥 날아가요.
keep-alive 는 한 번 맺은 연결을 끊지 않고 계속 씁니다. nginx는 기본으로 켜 두지만, 프록시 뒷단(14강)과의 연결도 챙겨야 합니다.
upstream mallshop {
server 127.0.0.1:8000;
keepalive 32; # 뒷단과도 연결 재사용
}
location / {
proxy_pass http://mallshop;
proxy_http_version 1.1; # keepalive 는 1.1 이상
proxy_set_header Connection ""; # 이 줄이 없으면 매번 끊깁니다
}
② 압축 — 보낼 양을 줄이기
HTML·CSS·JS는 글자라서 3분의 1로 줄어듭니다. 켜기만 하면 됩니다.
gzip on; gzip_comp_level 5; gzip_min_length 1024; gzip_types text/css application/javascript application/json image/svg+xml;
주의 — JPG·PNG·MP4는 이미 압축된 파일입니다.
다시 압축하면 CPU만 쓰고 크기는 그대로예요. gzip_types 에 넣지 마세요.
③ 캐시 — 두 번째 손님은 안 받아도 되게
로고 이미지가 1년째 안 바뀌는데 손님이 방문할 때마다 다시 보낼 이유가 없죠.
location /static/ {
expires 30d;
add_header Cache-Control "public, immutable";
}
immutable 은 "이 파일은 절대 안 바뀐다"는 약속입니다.
그럼 파일을 고쳐야 할 때는 어떻게 할까요? 파일 이름을 바꿉니다.
app.css 대신 app.9f3c1a.css 처럼요.
이걸 캐시 버스팅이라고 합니다.
④ HTTP/2 — 한 연결로 여러 개 동시에
HTTP/1.1은 한 연결에서 파일을 한 번에 하나씩 받습니다. 앞의 큰 파일이 뒤의 작은 파일을 막아요(head-of-line blocking).
HTTP/2는 한 연결 안에서 여러 파일을 동시에 주고받습니다. 헤더도 압축하고요. 설정은 한 단어면 끝납니다.
listen 443 ssl http2;
단, HTTP/2는 사실상 HTTPS 위에서만 동작합니다. 13강을 먼저 해야 해요.
⑤ 그리고 — 진짜 병목은 대개 여기가 아닙니다
솔직하게 말씀드립니다. 위의 네 가지를 다 해도 TTFB가 2초라면, 범인은 네트워크가 아니라 앱과 DB 입니다.
어느 쪽인지 먼저 재고 나서 고치세요. 안 그러면 엉뚱한 데를 몇 주 동안 만지게 됩니다.
🎓 수료를 축하합니다
1강에서 랜선 안의 전기 신호로 시작해, 지금은 이런 것들을 할 수 있습니다.
남은 것은 진짜 서버에서 해 보는 일뿐입니다. 클라우드에 가장 싼 인스턴스를 하나 띄우고, 도메인을 하나 사서, 이 20강을 그대로 따라 해 보세요. 가상 서버에서 이미 다 해 본 일들입니다.
gzip_types 에 image/jpeg 를 추가하면?