1. ๊ฐ๋
๋ฐ ์ฉ์ด ์ ๋ฆฌ
[1] Web Page Test
- webpagetest??
- ์ธํฐ๋ท ๊ตฌ๊ฐ์ ๊ดํ ์ ๋ฐ์ ์ธ ํ
์คํธ
- ํ
์คํธ ๋ฐฉ๋ฒ
- API ๋ณ ์์ฒญ ์๋ต ์๊ฐ ํ์ธ : ํฌ๋กฌ ๋ธ๋ผ์ฐ์ ๋๊ตฌ > ํผํฌ๋จผ์ค ํญ
- ์ ์ ์์๋ค์ ๊ดํ ์ธก์ ๋ฒ
- ์ ์ ์์ ๊ฒํ ์ฌํญ
- ์ฑ๋ฅ์ ์ํฅ์ ์ฃผ๋ ์์ : HTML, CSS, JS, image, web font ๋ฑ
- ์ฑ๋ฅ ๊ฐ์ ๊ฒํ ์์ : ์์ถ, HTTP Cache, CDN ๋ฑ๋ฑ
- ์น ์๋ฒ์ ์ํฅ์ ๋ฐ๋ ์งํ
- security score : TLS ๋ฐ HTTP ํค๋ ๋ณด์์ฑ + JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ณด์ ์ทจ์ฝ์ฑ
- first byte time : ์๋ฒ ์๋ต์๊ฐ + ๋คํธ์ํฌ ๋น์ฉ : ์น ์๋ฒ์์ ๋ฐ์ ์ปจํ
์ธ ์ ์ฒซ๋ฒ ์งธ ๋ฐ์ดํธ๊ฐ ์ผ๋ง ๋ง์ ๋์ฐฉํ๋์ง
- keep-alive enabled : keep-alive ์ค์ ํ๋์ง, ๋งค๋ฒ 3way handshake ๋ฑ ๊ณผ์ ์ ๊ฑฐ์ณ connection ์ ์์ฑํ์ง ์๊ณ ์ฌ์ฌ์ฉํ๋์ง
- compress transfer : gzip ์์ถ์ ํ๋์ง
- compress images : ์ด๋ฏธ์ง ์์ถ์ ํ๋์ง (์ฌ์ฉ์๋ ์ด๋ฏธ์ง ํ์ง๋ณด๋ค ๋คํธ์ํฌ ์ง์ฐ์ ๋ฏผ๊ฐ)
- cache static content
- JS, CSS ์ด๋ฏธ์ง, ์น ํฐํธ ๋ฑ ์ ์ ์ปจํ
์ธ ๋ฅผ ์บ์ฑํ๋์ง
- ์ ์ก ๋น์ฉ์ ์ค์ด๋ ๊ฒ๋ณด๋ค, ๋ถํ์ํ ์์ฒญ ์๋ฅผ ์ค์ด๋ ๊ฒ์ด ํจ๊ณผ์
[2] HTTP Header : Content-Encoding, Accept-Encoding
- HTTP Header : Content-Encoding
- Content-Encoding : ์๋ฒ๊ฐ ์ค์ํ content-encoding ํ์์ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํ๋ ์ํฐํฐ ํค๋ ํ๋์ด๋ค.
- ์ํฐํฐ ํค๋ ํ๋ : request ์ response ๋ฉ์ธ์ง์ ํฌํจ๋ ์ํฐํฐ์ ์ฌ์ฉ๋๋ ํค๋
- ์์ : Content-Encoding: gzip
- HTTP Header : Accept-Encoding
- Accept-Encoding : ๋ธ๋ผ์ฐ์ ๊ฐ ์ฒ๋ฆฌํ ์ ์๋ Content-Encoding ๊ณผ ์ฐ์ ์์๋ฅผ ์ ๋ฌํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ฆฌํ์คํธ ํค๋ ํ๋์ด๋ค.
- ์์ : Accept-Encoding: br;q=1.0, gzip;q=0.8, *;q=0.1
[3] ์์ถ ๋ฐฉ์
- gzip ์์ถ
- gzip์ ํ์ผ ์์ถ ๋ฐ ์์ถ ํด์ ์ ์ฌ์ฉ๋๋ ํ์ผ ํ์์ด๋ค. Deflate ์๊ณ ๋ฆฌ์ฆ์ ๊ธฐ๋ฐํ์ฌ ํ์ผ ํฌ๊ธฐ๋ฅผ ์๊ฒ ๋ง๋ค์ด ๋คํธ์ํฌ ์ ์ก ์๋๋ฅผ ๋์ผ ์ ์๋ค. gzip์ ์ผ๋ฐ์ ์ผ๋ก ์น ์๋ฒ์ ์ต์ ๋ธ๋ผ์ฐ์ ์์ ์ง์๋๋ฏ๋ก ์๋ฒ๋ ํ์ผ์ ๋ณด๋ด๊ธฐ ์ ์ ์๋์ผ๋ก gzip์ผ๋ก ์์ถํ๊ณ ๋ธ๋ผ์ฐ์ ๋ ํ์ผ์ ๋ฐ์ผ๋ฉด ์์ถ์ ํด์ ํ ์ ์๋ค.
[4] HTTP Cache
- ์๋ต ๊ฐ์ ๋ณต์ฌ๋ณธ์ ์ฌ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค๋ฅผ ๋ถ๋ฌ์ค๋ ์๋๋ฅผ ํฅ์์ํค๊ธฐ ์ํจ
- ์บ์ฑํ ๋ฆฌ์์ค์ ์์น๋ ๋ธ๋ผ์ฐ์ ์ private cache ์ ์กด์ฌํ ์๋ ์๊ณ , ํ๋ก์ ์๋ฒ(proxy, reverse proxy, CDN) ์ Shared Cache ๋ก ์กด์ฌํ ์๋ ์์
- ๊ด๋ จ ๋ด์ฉ์ https://dev-cooper.tistory.com/11 ์ ์ ๋ฆฌ
2. ์น ์ฑ๋ฅ ํ
์คํธ
[1] ์น ์ฑ๋ฅ ์ธก์ ํ๊ธฐ
- URL : https://www.webpagetest.org/
- ์น ํ์ด์ง ๋ก๋ฉ ์๋๋ฅผ ๋ฌด๋ฃ๋ก ํ
์คํธ ํ ์ ์๋ ์ฌ์ดํธ
- ํน์ง
- ์ฐ๊ฒฐ ์๋ ์์น ๋ฐ ํ๊ฒฝ ์ค์ ๊ฐ๋ฅ
- Repeat View(์บ์ฑ ๋ฑ ํ
์คํธ)
- ๋์ผ ์กฐ๊ฑด์ผ๋ก ์ฌ๋ฌ ์ฐจ๋ก ํ
์คํธ
- ์คํ๋ฒ
- ํ
์คํธ URL ์
๋ ฅ : https://cooper-subway.kro.kr/
- ํ
์คํธ ์ง์ญ ์ ํ (์์ธ ์ ํ) : advanced configuration > test setting > test location, browser ์ค์
- Start Test
NGINX + tomcat gzip ์ค์ ์ด์ 1
[2] ์น ์ฑ๋ฅ ์์ฐ ์ธก์
NGINX + tomcat gzip ์ค์ ์ด์ 2
์ง๋จ ๋ด์ฉ์ ์์ธํ๊ฒ ์๋ ค์ค๋ค.
[3] API ์๋ต ์๊ฐ ํ์ธ
- ์ญ ๊ด๋ฆฌ ์กฐํ API ์๋ต ์๊ฐ ํ์ธ
- chrmoe > ๊ฐ๋ฐ์ ๋ชจ๋ > performance tab > record > Network ํ์ธ
- ํ์ฌ GET /stations API duration 818.266ms ์์ ํ์ธ
3. reverse proxy ๊ฐ์ ํ๊ธฐ
[1] NGINX nginx.conf ํ์ผ ์ค์
(1) gzip ์์ถ
http {
gzip on; ## http ๋ธ๋ก ์์ค์์ gzip ์์ถ ํ์ฑํ
gzip_comp_level 9;
gzip_vary on;
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/rss+xml text/javascript image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype;
}
(2) cache
http {
## Proxy ์บ์ ํ์ผ ๊ฒฝ๋ก, ๋ฉ๋ชจ๋ฆฌ์ ์ ์ ํ ํฌ๊ธฐ, ์บ์ ์ ์ง๊ธฐ๊ฐ, ์ ์ฒด ์บ์์ ์ต๋ ํฌ๊ธฐ ๋ฑ ์ค์
proxy_cache_path /tmp/nginx levels=1:2 keys_zone=mycache:10m inactive=10m max_size=200M;
## ์บ์๋ฅผ ๊ตฌ๋ถํ๊ธฐ ์ํ Key ๊ท์น
proxy_cache_key "$scheme$host$request_uri $cookie_user";
server {
location ~* \.(?:css|js|gif|png|jpg|jpeg)$ {
proxy_pass http://app;
## ์บ์ ์ค์ ์ ์ฉ ๋ฐ ํค๋์ ์ถ๊ฐ
# ์บ์ ์กด์ ์ค์ (์บ์ ์ด๋ฆ)
proxy_cache mycache;
# X-Proxy-Cache ํค๋์ HIT, MISS, BYPASS์ ๊ฐ์ ์บ์ ์ ์ค ์ํ์ ๋ณด๊ฐ ์ค์
add_header X-Proxy-Cache $upstream_cache_status;
# 200 302 ์ฝ๋๋ 20๋ถ๊ฐ ์บ์ฑ
proxy_cache_valid 200 302 10m;
# ๋ง๋ฃ๊ธฐ๊ฐ์ 1 ๋ฌ๋ก ์ค์
expires 1M;
# access log ๋ฅผ ์ฐ์ง ์๋๋ค.
access_log off;
}
}
}
(3) TLS, HTTP/2 (HTTP2.0์ SSL ๊ณ์ธต ์์์๋ง ๋์ํฉ๋๋ค.)
http {
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/[๋๋ฉ์ธ์ฃผ์]/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/[๋๋ฉ์ธ์ฃผ์]/privkey.pem;
# Disable SSL
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ํต์ ๊ณผ์ ์์ ์ฌ์ฉํ ์ํธํ ์๊ณ ๋ฆฌ์ฆ
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
# Enable HSTS
# client์ browser์๊ฒ http๋ก ์ด๋ ํ ๊ฒ๋ load ํ์ง ๋ง๋ผ๊ณ ๊ท์ ํฉ๋๋ค.
# ์ด๋ฅผ ํตํด http์์ https๋ก redirect ๋๋ request๋ฅผ minimize ํ ์ ์์ต๋๋ค.
add_header Strict-Transport-Security "max-age=31536000" always;
# SSL sessions
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
}
}
(4) ์ฑ๋ฅ ์ง๋จ - PageSpeed Insights
- First Contentful Paint : 3.3s → 1.7s
- Largest Contentful Paint : 3.3s → 1.7s
- Total Blocking Time : 50ms → 0s
- Speed Index : 3.3s → 2.1s
(5) ์ฑ๋ฅ ์ง๋จ - Webpagetest
- start render : 4.7s → 1.5s (์ฒซ ํจํท ๋๋ฌ๊น์ง์ ์๊ฐ)
- First Contentful Paint : 4.708s → 1.503s (ํ
์คํธ์ ์ด๋ฏธ์ง๊ฐ ์ธ์ ๋ถํฐ ํ์๋๊ธฐ ์์ํ๋ ์๊ฐ)
- Speed Index 4.739s → 1.544s (ํ์ด์ง๊ฐ ์ฌ์ฉํ ์ํ๋ก ๊น์ง์ ์๊ฐ)
- Largest Contentful Paint : 4.901s → 1.602s (๊ฐ์ฅ ํฌ๊ฒ ํ์๋๋ ์ฝํ
์ธ ์ ๋ก๋ฉ ์๋ฃ ์๊ฐ)
- Page Weight : 2478KB → 615KB (๋ค์ด๋ก๋ํ ๋ฐ์ดํธ ์)
[2] tomcat compression ์ค์
(1) application.properties ์ค์
- server.compression.enabled - ์๋ฒ ์์ถ ํ์ฑํ ์ฌ๋ถ
- server.compression.mime-types - ์์ถํ MIME-TYPE ์ค์
- server.compression.min-response-size - ์์ถํ ํ์ผ ์ต์ ์ฌ์ด์ฆ (default = 2048)
# application.properties
server.compression.enabled: true
server.compression.mime-types: text/html,text/plain,text/css,application/javascript,application/json
server.compression.min-response-size: 500
(2) ์ฑ๋ฅ ์ง๋จ - PageSpeed Insights (NGINX + tomcat)
(3) ์ฑ๋ฅ ์ง๋จ - Webpagetest (NGINX + tomcat)
- NGINX ์์ HTTP ์์ฒญ ์ gzip compression ์ด ๋์ํ์ฌ ์ฑ๋ฅ์์ด ๋ณํ๊ฐ ๋ฏธ๋ฏธํ ๊ฒ์ผ๋ก ํ๋จ
Reference
- ์ฐธ๊ณ ๊ฐ์
- HTTP Content-Encoding, Accept-Encoding, gzip