본 포스팅은 수업내용의 단순 정리글입니다.
들어가며 : 03. 웹 브라우저 성능 개선 및 웹 서버 부하 완화를 위한 HTTP Cache 와 Proxy
웹 브라우저 성능을 개선하는 http cache와 웹 서버 부하 완화를 위한 Proxy에 대해 알아본다.
HTTP cache는 자주 요청되는 리소스를 중간 서버에 임시로 저장해 웹 브라우저의 속도를 개선, 네트워크의 트래픽을 줄이는 기술이다. 브라우저에 위치한 것을 Private cache, proxy측에 위치한 것을 Shared cache라고 한다.
Proxy는 클라이언트와 서버 사이에서 요청을 중계하고, 웹 서버의 부하를 줄이거나 보안을 강화하고 IP주소를 숨기는 등의 역할을 수행하는 중간서버이다. 웹 브라우저측에 위치한 것이 Forward Proxy, 웹 서버측에 위치한 것이 Reverse Proxy다.
이 개념들이 웹 상에서 어떻게 동작하는지, 동작원리와 장단점 등을 알아보자.
01. 중간서버에 리소스를 저장하는 HTTP Cache.
03-01. HTTP Cache 등장 : 웹 서버 부하 완화 및 웹 페이지 로드 성능 개선
무엇을 배웠는가?
캐시는 HTTP Cache캐시와 Server Cache로 나뉜다. HTTP Cache란 자주 요청되는 리소스를 중간 서버에 임시로 저장하는 것이며, 웹 브라우저의 속도 개선과 네트워크 트래픽을 줄이기 위해 사용한다. HTTP Cache의 종류는 Private과 Shared로 나뉘며 Private은 브라우저에 있는 캐시, Shared는 웹 서버의 프록시 안에 있는 캐시이다.Shared 캐시는 프록시캐시, 관리형캐시로 나뉘며 대표적인 예로는 Reverse Proxy, CDN이 있다. Server Cache란 local 캐시, Global 캐시로 나뉜다.
1) HTTP Cache의 장점
- 웹 서버 입장에서
- 반복연산감소 (동적 웹페이지를 생성하는 연산)
- 트래픽 분산(캐시가 일부 트래픽 분담)/ 부분 DDoS방어
- 웹 브라우저 입장에서
- 네트워크 트래픽 감소
- UX 향상
2) HTTP Cache란? 웹 브라우저와 웹 서버 사이의 중간 저장소이다.
3) Server Cache란? HTTP Cache가 아닌 웹 서버에서 사용하는 캐시
- 로컬 캐시 : LRU-Cache, Memcache, Ehcache
- 글로벌 캐시 : Redis (캐시 서버, 데이터베이스에 가까운 사용)
4) HTTP Cache 종류
- Private
- 웹 브라우저 안에 있는 캐시
- 유저 한명만을 위한 것
- 웹 서버가 HTTP Cache헤더(Cache-control)를 통해 웹 브라우저에 저장하라고 제어한다.
- 심화 : 서비스 개발자가 Service Worker (Cache API) 활용하여 오프라인 시 웹 페이지 렌더링 가능(‼️)
- 신입 프론트엔드 개발자가 이런 기능을 구현한다면 좋은 포트폴리오가 될 수 있다.
- Shared
- 웹 브라우저<->웹 서버 사이 프록시에 있는 캐시
- 모든 웹 브라우저 유저 다수를 위한 것
- 종류: Reverse Proxy, CDN
- 프록시 캐시: 웹 서버 HTTP Cache 헤더 (Cache-control) 를 통한 제어
- 관리형 캐시: 서비스 개발자가 직접 정책 제어, 배포, 캐싱할 데이터 직접 업로드로 관리 (❓)
- 프록시 캐시와 관리형 캐시의 구분은 Cache-Control 헤더를 통해 제어하느냐 직접하냐의 여부(❓)
02. HTTP Cache가 동작하는 원리에 대해 알아보자 : 재검증(Revalidate), 무효화(Invalidate)
03-02. HTTP Cache 동작 : 재검증을 통한 캐시값의 준실시간성 보장
무엇을 배웠는가?
HTTP Cache는 데이터의 임시 저장을 위한 전략이자 준실시간성을 보장하는 정책이므로 캐시해놓은 데이터가 너무 오래된 데이터가 되지않도록 특정주기에 따라 "재검증"을 해주어야한다. 그런의미에서 HTTP Cache의 동작할 때 중요한 재검증에 대해 알아보았다. 재검증은 재검증 주기와 재검증 기준이 있는데 재검증 기준은 Last-Modified와 ETag가 있다.
1) HTTP Cache 동작 원리를 왜 알아야할까? 간단하게 알아보자.
- 동작원리를 알아야 하는 이유 : 캐시는 임시(반영구적) 저장을 위한 전략이자 실시간을 아예 포기하자는 것이 아닌 준실시간성을 보장하는 정책이다. 그렇기에 캐시해놓은 데이터가 너무 오래된 데이터가 되지않도록 특정 주기에 따라 재검증을 해주어야 한다.
- 재검증(Revalidate)
- 재검증 주기(max-age): 캐시해놓은 데이터를 얼마 간격으로 재검증할지 특정 주기
- 재검증 기준: 캐시해놓은 데이터가 오래됐는지 여부를 원본 주인인 웹 서버가 판단하기 위한 기준근거
- 수정일 : Last-Modified
- 고유값 : ETag (Entity Tag, ETag 값으로 가장 많이 쓰이는것이 Hash-based)
2) HTTP Cache 재검증 기준
Last-Modified (수정일) | ETag (고유값) |
낮은 정확도 - 파일이 수정되지 않았는데 수정일이 변경되는 경우 - 텍스트 파일 수정 후, 다시 원상복구한 경우 수정일만 변경 |
높은 정확도 - 그렇기에 사실 Last-Modified 보다 ETag 사용이 좋다. - 다만, HTTP 1.0 혹은 1.1 호환성을 위해 둘 다 사용하는편 |
검사 방법 - If-Modified-Since : 바뀌었어? - If-Unmodified-Since : 안바뀌었어? |
검사 방법 - If-None-Match : 바뀌었어? - If-Match : 안바뀌었어? |
3) HTTP Cache 재검증 기준 1. Last-Modified : 수정일(시간) 기반(❓❓)
캐시가 유효한지 여부(= 원본이 바뀌었는지 여부)를 시간을 기반으로 판단한다
재검증 시 캐시 소유자 (웹 브라우저) : If-Modified-Since (바뀌었어?) (GET, HEAD)
- 서버 답변 : 응 (바뀌었어) : 200 Resource Cache + 새 응답(새로운 캐시)
- 서버 답변 : 아니 (안바뀌었어) : 304 Not Changed
재검증 시 캐시 소유자 (웹 브라우저) : If-Unmodified-Since (안바뀌었어?) (POST 서버 상태 변경 Method)
- 서버 답변 : 응 (안바뀌었어) : 2XX 성공 응답 (200 OK, 204 No Content, 206 Partial Content 등)
- 서버 답변 : 아니 (바뀌었어) : 412 Precondition Failed (조건부 요청에 대한 False 부정 응답)
4) HTTP Cache 재검증 기준 2. ETag : 고유값(해시) 기반(❓❓)
캐시가 유효한지 여부(= 원본이 바뀌었는지 여부)를 고유값(해시, ID)을 기반으로 판단한다
재검증 시 캐시 소유자 (웹 브라우저) : If-None-Match (달라? = 바뀌었어?)/ GET
- 서버 답변 : 응 (바뀌었어) : 200 Resource Cache + 새 응답(새로운 캐시)
- 서버 답변 : 아니 (안바뀌었어) : 304 Not Changed (GET, HEAD)
-
- 412 Precondition Failed (POST 서버 상태 변경 Method) 서버의 상태조작이 일어날때
-
재검증 시 캐시 소유자 (웹 브라우저) : If-Match (같아? = 안바뀌었어?)
- 서버 답변 : 응 (안바뀌었어) : 2XX 성공 응답 (200 OK, 204 No Content, 206 Partial Content 등)
- 서버 답변 : 아니 (바뀌었어) : 412 Precondition Failed 이건 예외 (조건부 요청에 대한 False 부정 응답)
03. HTTP Cache의 사용법과 Cache-control 헤더 세부 설정을 알아보자.
03-03. HTTP Cache 사용법 : Cache-control 헤더를 통한 세부 설정
무엇을 배웠는가?
HTTP Cache에 대한 세부적인 설정 및 전략들은 모두 웹 서버에서 설정하고 판단한다. 웹 서버에서 반환할 때 Response Header에 Cache-control을 포함해서 세부 설정값들을 포함해서 반환한다. 캐시 저장여부, 캐시 저장장소, 캐시 재검증 주기, 재검증필수여부에 따른 헤더 설정값을 알아보고, 캐시의 즉시성과 최신성을 둘 다 컨트롤할 수 있는 설정값인 stale-while-revalidate 에 대해서 알아보았다.
1) 캐시 저장여부에 관한 헤더 설정값
- no-store: 캐시 안함
- no-cache: 캐시 함. 단 매번 재검증 후 사용(패킷 경량화)
2) 캐시 저장장소에 관한 헤더 설정값
- public: Private(웹 브라우저) + Shared(프록시) 모두에 저장
- private: Private(웹 브라우저)에만 저장
3) 캐시 재검증 주기에 관한 헤더 설정값
- max-age: Expires(유효시간)으로 변환(기존 Expires가 있다면 덮어쓴다)
- s-maxage: 프록시 캐시가 웹서버로 요청을 보낼 때 적용되는 유효기간
- 이해를 돕기위한 연습 문제 : s-maxage=31536000(1년), max-age=0 는 무엇을 의미할까요?
- 브라우저에서 CDN으로는 매번 재검증을 수행하는 것이고, CDN이 웹서버에 1년마다 재검증을 수행하는 것.
4) 재검증 필수에 관한 헤더 설정값
- must-revalidate
- 재검증 시 무조건 서버를 통해 재검증 된 값만 보겠다는 뜻
- 재검증 꼭 하세요 라는 뜻이 아님
- 이 설정값의 역할
- 캐시의 기본행동은 서버와의 접속 문제로 재검증이 실패한 경우, 그냥 기존 캐시되어있는 데이터를 반환하게 되어있다.
- 하지만 이 설정값이 활성화되어있다면 504에러가 발생한다.(웹서버가 연락이 안되기 때문에)
- proxy-revalidate
- 프록시 캐시에 적용되는 must-revalidate 옵션
5) SWR (stale-while-revalidate) = 캐시의 즉시성과 최신성을 한번에
- 사용법
Cache-Control: max-age=1, stale-while-revalidate=60
- 60초 이내에 요청이 오는 경우 (stale-while-revalidate = 60)
- 재검증 요청을 동시에 하면서 오래된 캐시(Stale) 를 반환한다.
- 현재에(당장에) 캐싱된 컨텐츠를 즉시 로드하는 즉시성 (Stale 이더라도)
- 미래에 업데이트된 캐싱 컨텐츠가 사용될 수 있도록 보장하는 최신성
6) 주의할 점
- 모든 헤더값 무지성 때려넣지 않기
Cache-Control: no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate
7) Spring(java)에서의 HTTP cache설정 구현 예제
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
@RestController
public class CacheController {
@GetMapping("/example")
public String cachedResponse(HttpServletResponse response) {
// Cache-Control 설정
response.setHeader("Cache-Control", "public, max-age=3600");
// Expires 설정
Instant expiresAt = Instant.now().plusSeconds(3600);
response.setHeader("Expires", DateTimeFormatter.RFC_1123_DATE_TIME
.withZone(ZoneId.of("GMT"))
.format(expiresAt));
// ETag 설정
response.setHeader("ETag", "abc123");
return "This response is cached for 1 hour.";
}
}
04. Proxy : 서버 부하를 완화와 보안을 위해
03-04. 서버 부하 완화 및 보안(요청/응답 변조)을 위한 Proxy
무엇을 배웠는가?
프록시를 사용하는 이유는 보안과 속도, ACL, log, 지역 네트워크의 제한을 우회하기 위해 사용한다. 프록시는 브라우저단에서 동작하는 Forward Proxy, 서버 측에서 동작하는 Reverse Proxy로 구성되어 있다. 그 중에서도 Reverse Proxy의 대표적인 예로는 Load Balancer와 CDN이 있다.
0) Proxy를 사용하는 이유
- 보안 : IP 숨기기 혹은 프록시 서버를 방화벽으로 사용하기도 한다(프록시 방화벽)
- 속도(캐시) : 동일 요청이 들어오면 서버에 따로 접속할 필요가 없이 저장된 Cache 자원을 반환
- 전송 시간 절약, 외부 트래픽을 줄여 네트워크 병목 현상도 방지 = 이는 서비스의 속도를 높여준다.
- ACL : 사이트 접근 범위 정책 정의 (Proxy Server 에 접속할 수 있는 범위를 설정하는 옵션)
- Log / Audit : 리포트, 모니터링 (회사 내 직원의 인터넷/인트라넷 사용을 레포팅)
- 지역 네트워크 제한 우회 : 한국에서는 접속이 제한이 되는 사이트 (IP 검사로 한국에서의 접속임을 감지)
- 이런 경우 프록시 서버를 사용하면 접속을 다른나라로 우회
1) Forward Proxy : 웹 클라이언트 보안 및 접근 제어(‼️❓)
요청 보내는 측 : 클라이언트 (웹 브라우저) 측에 위치하며, 요청에 대한 세부적 추가 작업을 제공한다.
- 클라이언트 은닉 : IP 변환을 통해 원 요청자 은닉
- 우회 (Bypass) : 특정 클라이언트 IP 가 블락되어있다면, 그걸 피해서 접속하기 위해 IP 감춤
- 클라이언트 접근 제어 : 특정 IP 혹은 웹 페이지에 대한 접근 금지
- 캐싱 : 클라이언트가 받을 응답을 중간에 임시 저장 (개인이 소비하는 입장에서)
2) Reverse Proxy : 웹 서버 부하 완화 및 보안(‼️❓)
예시 : Nginx 와 같은 WS 를 서버 앞단에 놓아 Reverse Proxy 로 사용하기도하며, AWS ELB
- 요청 전달
- 로드 밸런싱 (요청 분산) = 웹 서버 부하 완화
- 웹 서버 수 동적으로 늘리기 → SRE 의 업무 (고가용성)
- 요청변환: Header 세팅
- 서버은닉 : 서버 고유의 IP가 외부로 노출되지 않음
- 서버 접근제어
- DDoS 방지 : Traffic 제어
- Rate Limiting : 짧은 시간(예, 1초) 내 너무 많은 요청이 오는걸 막기위한 정책
- 참고 : WS 나 WAS 같은 원 서버에서도 적용 가능
- WAF (Web Application Firewall)
- Honeypot 에 저장된 악성 IP 리스트 활용한 블럭
- Custom IP 추가 가능 (예, 악성 크롤링 봇 블럭)
- Rate Limiting : 짧은 시간(예, 1초) 내 너무 많은 요청이 오는걸 막기위한 정책
- Response Max Size 세팅 : 너무 큰 파일을 반환하는 경우 블락 (Nginx 설정)
- Timeout 세팅 (Nginx 설정)
- DDoS 방지 : Traffic 제어
- 보안: HTTPS
2-1) L2 Reverse Proxy : Load Balancer(‼️❓)
대량 트래픽에 의한 서버부담을 어떻게 분산할까
가장 기초적으로 단 한개의 웹 서버를 통해 우리의 웹 어플리케이션 서비스를 제공하는 경우 아래 두 문제가 발생
1. 대량의 트래픽이 한개의 웹 서버에 집중되는 경우
- 한개의 웹 서버가 트래픽을 감당하지 못해 터져버린다 → 수직적 확장 혹은 수평적 확장이 필요
2. 새 버전의 웹 어플리케이션을 배포 시
- 새로운 웹 서버에 배포하는 경우 IP 가 변경
- 기존의 웹 서버에 배포를 하더라도 기존 버전을 정지하고 새 버전을 구동하는 동안 유저는 사용하지 못함
- 이를 해결할 수 있는것이 로드밸런서
- 로드밸런서를 웹 서버 앞단에 두고, IP부여 한 뒤 웹 클라이언트가 해당 로드밸런서를 호출하게 하면
- 로드밸런서는 앞단의 모든 웹 클라이언트의 요청을 받아, 뒷단의 모든 웹서버에게 요청을 분산
- 배포 이슈 해결 : 클라이언트는 고정된 IP의 로드밸런서만 호출하기에 웹 서버가 몇개가 죽든말든 괜찮
- 트래픽 이슈 해결 : 아무리 많은 요청이 들어와도 로드밸런서 뒷단에 서버 수만 늘리면 된다. (수평적확장)
2-2) L1 Reverse Proxy : CDN (Contents Delivery Network)(‼️❓)
- CDN은 캐싱 + 지역성 해결을 위해 사용
- 캐싱 : 요청에 따른 응답을 중간 저장해놓은 뒤 동일 요청 시 저장값 반환
- 원본 데이터를 가진 웹 서버에 문제가 생기면 CDN 가 대신 응답을 반환하여 고가용성 보장
- CDN : 고가용성을 보장해주는 버퍼의 역할
- 원본 데이터를 가진 웹 서버에 DDoS 공격이 가해지는것을 CDN 이 대신 방어
- 원본 데이터를 가진 웹 서버에 문제가 생기면 CDN 가 대신 응답을 반환하여 고가용성 보장
- 지역성 해결 : HTTP Resource 제공 서버와 클라이언트가 멀리 떨어진 경우 클라이언트에 가까운곳에 저장
- 한국 웹 브라우저에서 미국 웹 서버로부터 응답을 받으려면 긴 응답시간
- 전세계적으로 캐시 서버를 곳곳에 두어 캐시 서버 내 응답 데이터를 캐싱(저장)한다면 속도 개선
- 캐시 서버로 동작하는 만큼 원 서버에 문제가 생기면 CDN 이 False Tolerance 장애허용을 해주기도 함
'ASAC > 복습 내용정리' 카테고리의 다른 글
[ASAC 7기] Cookie, Storage, Session과 HTTPS와 CORS 보안 (1) | 2024.12.18 |
---|---|
[ASAC 7기] 웹 개발 백엔드 : 운영체제, 서버, 배포방법론 (0) | 2024.12.12 |
[ASAC 7기] 프론트엔드 관점에서 웹 개발을 알아보자 (1) | 2024.12.11 |
[ASAC 7기] 웹의 본질과 흐름을 알아보자 : 요청반환동작원리, 웹접근성, 네트워크 (1) | 2024.12.11 |