Cache 와 Proxy

HTTP Cache 등장 : 웹 서버 부하 완화 및 웹 페이지 로드 성능 개선
HTTP Cache : 웹 브라우저와 웹 서버 사이 중간 저장소
- 웹 브라우저 : 웹 페이지 로드 응답이 똑같다면, 웹 브라우저는 매번 웹 서버에게 받아올 필요가 없다.
- 이전에 받았던 응답을 저장 후, 매번 요청할시 저장해놓은 응답을 재사용 반환하면 되지 않을까?
- HTTP Cache 중 Private (웹 브라우저 사이드 = 클라이언트 사이드)
- 웹 서버 : 웹 페이지 로드 응답이 똑같다면, 웹 서버는 매번 웹 브라우저에게 만들어 반환할 필요가 없다.
- 이전에 반환한 응답을 저장 후, 매번 요청받을시 저장해놓은 응답을 재사용 반환하면 되지 않을까?
- HTTP Cache 중 Shared (프록시 = CDN or Forward/Reverse Proxy)
- API Server 자체 Cache (서버 사이드 = Local or Global)
웹 서버 입장에서..
- 웹 서버 부하 완화
- 반복 연산 감소 : 웹 서버가 동적 웹 페이지를 생성하는 연산을 하지 않아도 된다 ← 캐시가 반환
- 트래픽 분산 : 웹 서버가 모든 요청 트래픽을 받아내지 않아도 된다 ← 캐시가 일부 트래픽 분담
웹 브라우저 입장에서..
- 네트워크 트래픽 감소 (레이턴시 및 네트워크 대역폭 사용 감소)
- 유저 경험 증진
HTTP Cache 종류

임시 저장 데이터를 누가 필요로 하는가? 특정된 한명인가, 불특정 다수인가?
- A. Private : 임시 중간 저장소가 웹 브라우저 안에 있다면, 해당 웹 브라우저 유저 한명만을 위한것
- 웹 브라우저에 위치
- 브라우저 캐시 : 웹 서버가 HTTP Cache 헤더 (Cache-control) 를 통한 제어 (웹 브라우저에 저장하라)
- 심화 : 서비스 개발자가 Service Worker (Cache API) 활용하여 오프라인 시 웹 페이지 렌더링 가능
- B. Shared : 임시 중간 저장소가 웹 브라우저와 웹 서버 사이에 있다면, 모든 웹 브라우저 유저 다수를 위한것
- 웹 브라우저와 (원본)웹 서버사이 프록시에 위치
서버 캐시 : HTTP Cache 가 아닌 웹 서버에서 사용하는 캐시
- 로컬 캐시 : LRU-Cache, Memcache, Ehcache
- 글로벌 캐시 : Redis (캐시 서버, 데이터베이스에 가까운 사용)
HTTP Cache 동작 : 재검증을 통한 캐시값의 준실시간성 보장
HTTP Cache 동작 과정

- 준실시간 : 캐시해놓은 데이터가 너무 오래된 데이터가 되지 않도록 특정 주기에 따라 재검증을 해주어야한다.
- 재검증 : 캐시한 데이터의 원본 주인인 웹 서버가 설정한 특정 주기에 따라, 캐시한 데이터가 오래됐는지 검증
- 검증 방법 : 조건부 요청 사용 = 재검증 기준이 되는 값을 서버에게 보낸다.
- 심화 : 우리가 마주할 조건부 요청 종류 2개 1. HTTP Cache 재검증 2. CORS 요청 가능여부 확인
- 재검증 주기 : 캐시해놓은 데이터를 얼마 간격으로 재검증할지 특정 주기 (예, 1년마다)
- 개발자들은 데이터의 갱신 특성에 따라 주기 설정 : 자주 바뀌는 데이터? or 잘 안바뀌는 데이터?
- 주기가 너무 길어도 안되고 : (두부받고 1년 뒤) “엄마, 이거 먹어도 돼?” → “미친놈아”
- 주기가 너무 짧아도 안된다 : (두부받을때 매번) “엄마, 이거 먹어도 돼?” → “그만 좀 물어봐”
- 재검증 기준 : 캐시해놓은 데이터가 오래됐는지 여부를 원본 주인인 웹 서버가 판단하기 위한 기준 근거
- 수정일 : Last-Modified
- 고유값 : ETag (Entity Tag, ETag 값으로 가장 많이 쓰이는것이 Hash-based)
304 Not Modified
캐시가 유효한 지 = 원본이 유효한 지 확인하는 과정에서, 바뀐 것이 없을 때
수정일 기반, 고유값 기반 재검증 및 ETag
Last-Modified (수정일) | ETag (고유값) |
---|
| 낮은 정확도
- 파일이 수정되지 않았는데 수정일이 변경되는 경우
- 텍스트 파일 수정 후, 다시 원상복구한 경우 수정일만 변경 | 높은 정확도
- 그렇기에 사실 Last-Modified 보다 ETag 사용이 좋다.
- 다만, HTTP 1.0 혹은 1.1 호환성을 위해 둘 다 사용하는편 |
| 검사 방법
- If-Modified-Since : 바뀌었어?
- If-Unmodified-Since : 안바뀌었어? | 검사 방법
- If-None-Match : 바뀌었어?
- If-Match : 안바뀌었어? |

웹 서버가 해당 헤더를 주었다면 Last-Modified : 전송 Resource 의 마지막 수정일
캐시가 유효한지 여부(= 원본이 바뀌었는지 여부)를 시간을 기반으로 판단한다
재검증 시 캐시 소유자 (웹 브라우저) : 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 부정 응답)

웹 서버가 해당 헤더를 주었다면 Etag : 전송 Resource 의 고유값(해시, ID)
캐시가 유효한지 여부(= 원본이 바뀌었는지 여부)를 고유값(해시, ID)을 기반으로 판단한다
재검증 시 캐시 소유자 (웹 브라우저) : If-None-Match (달라? = 바뀌었어?)
- 서버 답변 : 응 (바뀌었어) : 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 부정 응답)
Hash 및 HMAC
- 객체의 대명사 = 객체의 고유성을 대표하는데 사용

HMAC (Hash-based Message Authentication Code) : 고유성 검증을 위한 Hash 활용의 다른 예

본 예시는 파일 다운로드의 예시지만, 파일을 JSON 으로 바꾸면 Open API 예시가 된다.
- HMAC 은 다음과 같은 상황에서 사용
- 다운로드 받은 파일이 변조되었는지 알기 위해
- (Open) API 를 통해 받은 결과값이 변조되었는지 알기 위해
- HMAC 을 통해 변조되었는지 여부 판단하는 방법
- 파일을 다운받거나 혹은 API 결과와 함께
- 동시에, 서버가 파일 혹은 API 결과로 계산한 Hash 값 을 함께 받음
- 받은 파일 과 API 결과 에 대해 클라이언트와 서버가 미리 공유한 키 값 으로 Hash 값 생성
- 생성된 Hash 값 과 앞서 받은 Hash 값 과 비교
- 두 값이 같다면 → 위조되지 않은 파일 혹은 API 결과라고 인지
HTTP Cache 사용법 : Cache-control 헤더를 통한 세부 설정
HTTP Cache 의 캐시 저장 여부 옵션
no-store
: 캐시 안함
no-cache
: 캐시 함. 단, 매번 재검증 후 사용 (패킷 경량화) ← 헷갈리지 말것! 캐시안하는게 아님
- 캐시 데이터 쓰기전에 꼭 나한테 재검증해야해 = 나한테 검사받아 = 경량화된 요청-응답
HTTP Cache 의 캐시 저장 장소 옵션
public
: Private(웹 브라우저) + Shared(프록시) 모두에 저장 ← 헷갈리지 말것! 브라우저에도 저장
private
: Private(웹 브라우저) 에만 저장
HTTP Cache 의 캐시 재검증 주기 옵션
max-age
: Expires(유효시간)으로 변환 (기존 Expires 가 있다면 덮어쓴다)
- *이해를 돕기위한 연습 문제 :
max-age=0
는 무엇과 같은 의미일까요? no-cache
= 매번 재검증*
s-maxage
: 프록시 캐시에만 적용되는 유효기간
- *이해를 돕기위한 연습 문제 :
s-maxage=31536000(1년), max-age=0
는 무엇을 의미할까요?*
- 웹 브라우저는 계속 CDN 에게 재검증을 수행, CDN 은 1년을 주기로 본 웹 서버에게 재검증
- 웹 브라우저는 CDN 이 자체적으로 Invalidation(무효화)하지 않는한 1년 동안 같은 데이터만
HTTP Cache 의 캐시 재검증 강제 옵션
must-revalidate
: 재검증 시 무조건 서버를 통해 재검증 된 값만 보겠다는 뜻
- 서버와의 접속 문제로 재검증이 실패한 경우 기본 행동은 그냥 기존 캐시되어있는 데이터를 반환
- 하지만,
must-revalidate
가 활성화되어있다면 504 에러 발생 = 웹 서버가 연락이 안돼요!
proxy-revalidate
: 프록시 캐시에 적용되는 must-revalidate
옵션
HTTP Cache 에서 Revalidate
“재검증 시 꼭 재검증이 제대로되어야해!”
SWR(stale-while-revalidate) = 캐시의 즉시성과 최신성을 한번에
HTTP Cache 제어 중 SWR (stale-while-revalidate) 확장 디렉티브 전략
- 현재에(당장에) 캐싱된 컨텐츠를 즉시 로드하는 즉시성 (Stale 이더라도)
- 미래에 업데이트된 캐싱 컨텐츠가 사용될 수 있도록 보장하는 최신성
- 60초 이내에 요청이 오는 경우 (stale-while-revalidate = 60)
- 재검증 요청을 동시에 하면서 오래된 캐시(Stale) 를 반환


- 0-1 초 (신선 = 즉시성) ⇒ 캐싱된 응답을 “재검증” 없이 바로 반환

- 1-60 초 (오래되었지만 반환과 동시 재검증) ⇒ 캐싱된 응답을 바로 반환 + “재검증” 요청 (백그라운드)

- 60+ 초 (재검증 = 최신성) ⇒ 캐싱된 응답을 사용하지 않음 + 서버에 요청보내어 응답 캐싱 및 반환
서버 부하 완화 및 보안(요청/응답 변조)을 위한 Proxy
Proxy의 정의 및 사용 이유

: 클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해 주는 컴퓨터 시스템이나 응용 프로그램
- 보안 : IP 숨기기 혹은 프록시 서버를 방화벽으로 사용하기도 한다(프록시 방화벽)
- 속도(캐시) : 동일 요청이 들어오면 서버에 따로 접속할 필요가 없이 저장된 Cache 자원을 반환
- 전송 시간 절약, 외부 트래픽을 줄여 네트워크 병목 현상도 방지 = 이는 서비스의 속도를 높여준다.
- ACL : 사이트 접근 범위 정책 정의 (Proxy Server 에 접속할 수 있는 범위를 설정하는 옵션)
- Log / Audit : 리포트, 모니터링 (회사 내 직원의 인터넷/인트라넷 사용을 레포팅)
- 지역 네트워크 제한 우회 : 한국에서는 접속이 제한이 되는 사이트 (IP 검사로 한국에서의 접속임을 감지)
- 이런 경우 프록시 서버를 사용하면 접속을 다른나라로 우회
WAF (Web Application Firewall) & Rate Limiting
- Rate Limiting : 짧은 시간(예, 1초) 내 너무 많은 요청이 오는걸 막기위한 정책
- 참고 : WS 나 WAS 같은 원 서버에서도 적용 가능
- WAF (Web Application Firewall)
- Honeypot 에 저장된 악성 IP 리스트 활용한 블럭
- Custom IP 추가 가능 (예, 악성 크롤링 봇 블럭)
Forward Proxy : 웹 클라이언트 보안 및 접근 제어 (은닉)
요청 보내는 측 : 클라이언트 (웹 브라우저) 측에 위치하며, 요청에 대한 세부적 추가 작업을 제공한다.
- 앞서 배웠던 ISP(Internet Service Provider) 가 Forward Proxy
- 라이언트 은닉 : IP 변환을 통해 원 요청자 은닉
- 우회 (Bypass) : 특정 클라이언트 IP 가 블락되어있다면, 그걸 피해서 접속하기 위해 IP 감춤
- 클라이언트 접근 제어 : 특정 IP 혹은 웹 페이지에 대한 접근 금지
- 캐싱 : 클라이언트가 받을 응답을 중간에 임시 저장 (개인이 소비하는 입장에서)
Reverse Proxy : 웹 서버 부하 완화 및 보안 (분산)
요청을 받는 측 : 웹 서버 측에 위치하며, 요청에 대한 세부적 추가 작업을 제공한다.


- 요청 전달 : URL/I Mapping (URI 기반 Routing), 로드 밸런싱 (요청 분산)
- 로드 밸런싱 (요청 분산) = 웹 서버 부하 완화
- 웹 서버 수 동적으로 늘리기 → SRE 의 업무 (고가용성)
- 요청 변환 : Header 세팅 (예, X-FORWARDED-BY 로 근원 클라이언트 IP 를 서버에게 전달)
- X-FORWARDED-BY : 123, 456, 789 → 가장 마지막에 있는게 최초 호출자
- 서버 은닉 : 서버 고유의 IP 가 외부로 노출되지 않음
- 서버 접근 제어 (요청 필터)
- DDoS 방지 : Traffic 제어
- Rate Limiting : 짧은 시간(예, 1초) 내 너무 많은 요청이 오는걸 막기위한 정책
- 참고 : WS 나 WAS 같은 원 서버에서도 적용 가능
- WAF (Web Application Firewall)
- Honeypot 에 저장된 악성 IP 리스트 활용한 블럭
- Custom IP 추가 가능 (예, 악성 크롤링 봇 블럭)
- Response Max Size 세팅 : 너무 큰 파일을 반환하는 경우 블락 (Nginx 설정)
- Timeout 세팅 (Nginx 설정)
- 보안 : HTTPS
- 모든 서버가 Private Key 를 가지고 있어야하는 단점
- 한 서버(Reverse Proxy)가 Private Key 를 가지고 있으면 관리 및 인증 간편
- 캐싱 : 클라이언트가 자주하는 요청에 대한 응답을 중간에 임시 저장 (다수에 제공하는 관점)
Load Balancer 사용 이유 및 장점
L2 Reverse Proxy : Load Balancer → 대량 트래픽에 의한 서버 부담을 분산하기 위해
- 대량의 트래픽이 한개의 웹 서버에 집중되는 경우
- 한개의 웹 서버가 트래픽을 감당하지 못해 터져버린다 → 수직적 확장 혹은 수평적 확장이 필요
- 새 버전의 웹 어플리케이션을 배포 시
- 새로운 웹 서버에 배포하는 경우 IP 가 변경
- 기존의 웹 서버에 배포를 하더라도 기존 버전을 정지하고 새 버전을 구동하는 동안 유저는 사용하지 못함
트래픽 분산뿐만 아니라, 트래픽이 급증하거나 급감하는 경우 서버의 수를 동적으로 제어하여 고가용성 제공
로드밸런서를 웹 서버의 앞단에 두고, IP 를 부여한 뒤 웹 클라이언트가 해당 로드밸런서를 호출하게 하면
- 로드밸런서는 앞단의 모든 웹 클라이언트의 요청을 받아, 뒷단의 모든 웹 서버에게 요청을 분산합니다.
- 배포 이슈 해결 : 클라이언트는 고정된 IP 의 로드밸런서만 호출하기에 웹 서버가 몇개든 죽든말든 노상관
- 트래픽 이슈 해결 : 아무리 많은 요청이 들어와도 로드밸런서 뒷단에 서버 수만 늘리면된다 (수평적 확장)

L1 Reverse Proxy : CDN (Contents Delivery Network)
Proxy 는 캐싱 + 요청에 대한 세부적 추가 작업 를 위해 사용
- 캐싱 : 요청에 따른 응답을 중간 저장해놓은 뒤 동일 요청 시 저장값 반환
- 요청에 대한 세부적 추가 작업 : 요청 변환, 필터 등의 추가 작업 수행
그렇다면 CDN 은 어떤 목적을 위해 사용하는가? = 캐싱 + 지역성 해결 을 위해 사용
- 캐싱 : 요청에 따른 응답을 중간 저장해놓은 뒤 동일 요청 시 저장값 반환
- 원본 데이터를 가진 웹 서버에 문제가 생기면 CDN 가 대신 응답을 반환하여 고가용성 보장
- 원본 데이터를 가진 웹 서버에 DDoS 공격이 가해지는것을 CDN 이 대신 방어
- 지역성 해결 : HTTP Resource 제공 서버와 클라이언트가 멀리 떨어진 경우 클라이언트에 가까운곳에 저장
- 한국 웹 브라우저에서 미국 웹 서버로부터 응답을 받으려면 긴 응답시간
- 전세계적으로 캐시 서버를 곳곳에 두어 캐시 서버 내 응답 데이터를 캐싱(저장)한다면 속도 개선
- 캐시 서버로 동작하는 만큼 원 서버에 문제가 생기면 CDN 이 False Tolerance 장애 허용을 해주기도 함

CDN의 정의 및 역할, 사용 예시
- 고가용성을 보장해주는 버퍼의 역할
- → 캐싱 + 지역성 해결을 위해 사용
- ex) 한국에 있는 사용자가 아르헨티나에 원본 서버를 가진 웹 사이트의 고양이 사진을 보고싶을 때, 한국에 위치한 엣지 서버에서 PoP(Points of presence)를 통해 사용자에게 보내는 방식
- CDN의 세 가지 주요 구성 요소
- 원본 서버 텍스트, 이미지, 비디오 등과 같은 실제 웹사이트 콘텐츠를 호스팅하는 원본 서버
- 엣지 서버 CDN은 서버를 지리적으로 분산하여 최종 사용자와 더 가까운 곳에 배치 웹 콘텐츠를 저장하여 사용자에게 더 빠르게 전송
- PoP(Points of presence) 엣지 서버를 포함하는 데이터 센터 → 교통 허브와 같은 역할 콘텐츠는 사용자와 더 가까운 다른 엣지 서버 위치로 이동하기 전에 이러한 데이터 센터에서 중지