이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.
원본을 바꿨는데 왜 사용자는 아직 옛 파일을 받나
CDN은 원본 서버(오리진)가 가진 파일의 사본을 사용자와 가까운 서버(엣지)에 보관해 두고, 엣지가 대신 답하게 하는 방식입니다. 처음 요청은 엣지에 사본이 없어 오리진까지 다녀오지만(MISS), 그 뒤로는 엣지가 바로 답합니다(HIT). 대신 엣지는 정해진 유효 시간 동안 오리진에 다시 묻지 않으므로, 그사이 오리진의 파일을 바꿔도 사용자는 옛 사본을 받습니다.
일부만 실행으로 확인 · 오리진과 직접 만든 캐싱 서버(엣지 역할)를 127.0.0.1에 띄워 열여섯 가지 조합을 실행해 대조. 실제 CDN 서비스로는 확인하지 않음
# 오리진이 app.css를 줄 때 붙이는 응답 헤더
Cache-Control: public, s-maxage=300 # 공유 캐시(엣지)는 300초 동안 사본을 그대로 써도 된다
// 엣지: 사본을 보관했다가 대신 답하는 서버 (Node.js로 줄여 쓴 모습)
const store = new Map(); // 주소(경로 + 쿼리 문자열) → 보관한 사본
http.createServer(async (req, res) => {
if (req.method === 'PURGE') { // 무효화: 그 주소의 사본을 지운다
store.delete(req.url);
return res.end('purged');
}
const copy = store.get(req.url);
if (copy && age(copy) < copy.ttl) { // 사본이 있고 유효 시간 안
res.setHeader('X-Cache', 'HIT');
return res.end(copy.body); // 오리진에 묻지 않고 바로 답한다
}
const fresh = await fetchFromOrigin(req.url); // 없거나 유효 시간이 지났으면 오리진으로
store.set(req.url, fresh);
res.setHeader('X-Cache', copy ? 'EXPIRED' : 'MISS');
res.end(fresh.body);
});
// 요청 순서
// 0초 curl https://cdn.shop.example/app.css?v=1
// 10초 curl https://cdn.shop.example/app.css?v=1
// 30초 오리진의 app.css를 새 내용으로 배포
// 40초 curl https://cdn.shop.example/app.css?v=1
// 80초 curl https://cdn.shop.example/app.css?v=1
열여섯 가지 조합(파일을 바꾸지 않으면 "바꾼 뒤에 하는 일"은 쓰이지 않음)을 127.0.0.1에 띄운 오리진 서버와 엣지 역할의 작은 캐싱 프록시로 실행해, 네 번의 요청이 각각 MISS, HIT, EXPIRED 가운데 무엇이었는지와 받은 내용, 오리진에 도착한 요청 수가 모형과 같은 것을 확인했습니다. 엣지는 Node.js 24로 직접 만든 시험용이며, 사본을 보관해도 되는지와 유효 시간이 남았는지는 HTTP 캐시 규칙 구현인 http-cache-semantics 4.2(공유 캐시 모드)에 맡겼습니다. 80초를 기다리지 않도록 엣지의 시계를 빠르게 돌려(모형의 1초를 실제 30ms로) 시험했고, 사용자 역할은 Node의 fetch와 curl 8.21이 번갈아 맡았습니다. 실제 CDN 서비스에서 확인한 것은 아닙니다. 걸린 시간(20ms, 220ms)과 "가깝다, 멀다"는 측정값이 아니라 차이를 보이기 위한 예시입니다. s-maxage가 공유 캐시의 유효 시간을 정한다는 것과 유효 시간이 지난 사본을 그대로 쓰지 않는다는 것은 RFC 9111 4.2절과 5.2.2.10절, 사본을 요청 메서드와 주소로 찾는다는 것은 2절을 따랐습니다. HIT, MISS, EXPIRED라는 이름과 X-Cache 헤더는 표준이 아니라 여러 CDN과 프록시가 쓰는 관례이고 제품마다 표기가 다릅니다. 무효화(purge)도 표준에 없는 제품별 기능이며, 여기서는 PURGE 메서드로 한 주소의 사본을 지우는 흔한 방식을 따랐습니다. 유효 시간이 지났을 때 이 모형의 엣지는 파일 전체를 다시 받지만, 실제 CDN은 대개 조건부 요청으로 "바뀌었는지"만 먼저 묻습니다(HTTP 캐시와 ETag 실습 참고). 엣지가 여러 지역에 여러 대 있고 저마다 사본을 따로 보관한다는 것, 브라우저가 따로 보관하는 사본, 사본을 미리 채워 두는 기능은 다루지 않았습니다.
앞 실습: 프록시와 리버스 프록시
줄을 그은 곳은 처음 코드에서 지운 것이고, 색을 칠한 곳은 새로 쓴 것입니다.