📌 webpagetest, pagespeed 등으로 테스트하여, 인터넷 구간에서 성능에 영향을 주는 요소를 이해해봅니다.
HTTP를 활용하여 서비스의 성능을 개선해봅니다.

1. 웹 성능 테스트

  • 크롬 브라우저 도구를 활용하면, 퍼포먼스 탭에서 각 api별 요청 응답시간을 확인할 수 있어요.

2. Reverse Proxy 개선하기

Proxy cache · MISS → HIT
Proxy cache · MISS → HITClient · Proxy cache · Origin · GET /app.css · 저장 응답 200 · public · max-age=600 · X-Proxy-Cache: HIT · 클라이언트 요청 2 원본 요청 1 · ② 같은 키 · HIT. 신선한 캐시에서 응답합니다. 원본 서버 요청은 한 번입니다.ClientProxy cacheOriginGET /app.css저장 응답 200 · publicmax-age=600X-Proxy-Cache: HIT클라이언트 요청 2 원본 요청 1② 같은 키 · HIT
Proxy cache · MISS → HITClient · Proxy cache · Origin · GET /app.css · 저장 응답 200 · public · max-age=600 · X-Proxy-Cache: HIT · 클라이언트 요청 2 원본 요청 1 · ② 같은 키 · HIT. 신선한 캐시에서 응답합니다. 원본 서버 요청은 한 번입니다.ClientProxy cacheOriginGET /app.css저장 응답 200 · publicmax-age=600X-Proxy-Cache: HIT클라이언트 요청 2 원본 요청 1② 같은 키 · HIT

신선한 캐시에서 응답합니다. 원본 서버 요청은 한 번입니다.

단계별 장면

1. 첫 요청 → MISS → 원본 서버.

Proxy cache · MISS → HIT · 1Client · Proxy cache · Origin · GET /app.css · 저장 응답 없음 · max-age=600 · X-Proxy-Cache: MISS · 클라이언트 요청 1 원본 요청 1 · ① 첫 요청 · MISS. 원본 서버의 응답 본문을 받는 중입니다.ClientProxy cacheOriginGET /app.css저장 응답 없음max-age=600X-Proxy-Cache: MISS클라이언트 요청 1 원본 요청 1① 첫 요청 · MISS
Proxy cache · MISS → HIT · 1Client · Proxy cache · Origin · GET /app.css · 저장 응답 없음 · max-age=600 · X-Proxy-Cache: MISS · 클라이언트 요청 1 원본 요청 1 · ① 첫 요청 · MISS. 원본 서버의 응답 본문을 받는 중입니다.ClientProxy cacheOriginGET /app.css저장 응답 없음max-age=600X-Proxy-Cache: MISS클라이언트 요청 1 원본 요청 1① 첫 요청 · MISS

2. 완전한 응답을 받은 뒤 저장합니다. 헤더 수신만으로 HIT가 되지 않습니다.

Proxy cache · MISS → HIT · 2Client · Proxy cache · Origin · GET /app.css · 저장 응답 200 · public · max-age=600 · X-Proxy-Cache: MISS · 클라이언트 요청 1 원본 요청 1 · ① 첫 요청 · MISS. 응답을 모두 받은 뒤 캐시에 저장합니다.ClientProxy cacheOriginGET /app.css저장 응답 200 · publicmax-age=600X-Proxy-Cache: MISS클라이언트 요청 1 원본 요청 1① 첫 요청 · MISS
Proxy cache · MISS → HIT · 2Client · Proxy cache · Origin · GET /app.css · 저장 응답 200 · public · max-age=600 · X-Proxy-Cache: MISS · 클라이언트 요청 1 원본 요청 1 · ① 첫 요청 · MISS. 응답을 모두 받은 뒤 캐시에 저장합니다.ClientProxy cacheOriginGET /app.css저장 응답 200 · publicmax-age=600X-Proxy-Cache: MISS클라이언트 요청 1 원본 요청 1① 첫 요청 · MISS

3. 두 번째 요청 → HIT → 저장 응답. 원본의 전체 HTTP 헤더는 아래 이미지로 보존합니다.

Proxy cache · MISS → HIT · 3Client · Proxy cache · Origin · GET /app.css · 저장 응답 200 · public · max-age=600 · X-Proxy-Cache: HIT · 클라이언트 요청 2 원본 요청 1 · ② 같은 키 · HIT. 신선한 캐시에서 응답합니다. 원본 서버 요청은 한 번입니다.ClientProxy cacheOriginGET /app.css저장 응답 200 · publicmax-age=600X-Proxy-Cache: HIT클라이언트 요청 2 원본 요청 1② 같은 키 · HIT
Proxy cache · MISS → HIT · 3Client · Proxy cache · Origin · GET /app.css · 저장 응답 200 · public · max-age=600 · X-Proxy-Cache: HIT · 클라이언트 요청 2 원본 요청 1 · ② 같은 키 · HIT. 신선한 캐시에서 응답합니다. 원본 서버 요청은 한 번입니다.ClientProxy cacheOriginGET /app.css저장 응답 200 · publicmax-age=600X-Proxy-Cache: HIT클라이언트 요청 2 원본 요청 1② 같은 키 · HIT
공유 proxy cache · GET /app.css · 동일 키 · public, max-age=600인 200 응답. 두 번째 조회는 유효 기간 안입니다. 설명용 응답입니다.
원본 도해
  • 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;
    }
  • 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;
            }
        }
    }
  • 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; 
      }
    }

3. Tomcat 개선하기

HTTP Cache, gzip 등 학습 테스트를 통해 학습한 후, 운영 코드에 반영해보세요.

  • gzip 압축

    # 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