🤔 304 코드?
요청을 보내고 찍힌 로그를 보면서 200이 아니라 304 코드가 찍힌 걸 보고 무슨 의미일까해서 찾아보니, 캐시된 자원이기 때문에 요청된 내용을 재전송할 필요가 없음을 의미한다고 한다.
브라우저는 어떻게 요청한 자원이 캐시된 자원임을 확인하는 걸까?
본 글에서는 그 과정과, 핵심 키워드인 ETag에 관해 알아볼 것이다.
브라우저 캐시는 파일들을 저장하는 작은 데이터베이스로 이미지, CSS, Javascript와 같은 웹페이지 리소스들이 저장되는 곳이다.
서버가 특정 자원에 대한 HTTP 요청을 받으면, 응답코드 200과 함께 헤더에 ETag를 실어보낸다.
response.headers.get("ETag")
위와 같이 헤더에 ETag이 포함되어 있는 것을 확인할 수 있다.
✔️ E-Tag: 자원의 특정 버전에 대한 식별자
브라우저는 헤더 정보와 함께 자원을 캐시해둔다.
다음에 동일한 자원에 대한 요청을 보낼 때, 요청 헤더의 If-None-Match 값에 저장해두었던 ETag를 함께 실어보낸다.
e.g.) If-None-Match: W/"964-XDp2nn7kcWG+zsbmcc3+Hmq3x10”
그 외 If-Modified-Since
헤더를 사용할 수도 있다.
서버에서 If-None-Match 헤더를 포함한 요청을 받으면, 서버 측의 ETag 값과 요청 헤더의 값을 비교한다.
만약 그 값이 서로 동일하면, 304 코드와 함께 비어있는 body를 보낸다.
브라우저에서는 응답 코드가 304라면 캐시된 자원을 사용한다.
만약 ETag 값이 일치하지 않으면 200 코드와 함께 요청된 자원을 body에 실어보낸다.
⇒ Content가 변하지 않았다면 웹 서버가 전체 response를 전송할 필요가 없다.
❗여러 대의 서버를 운영하고 있다면 같은 컨텐츠이지만 ETag가 다를 수 있다.
app.**set**("etag", "strong");
var hash = crypto
.createHash('md5')
.update(body, encoding)
.digest('base64')
return '"' + hash + '"'
};
Express는 MD5 알고리즘 이용하여 인코딩.‘W/’
가 붙는다. Strong validator보다 생성하기는 쉽지만 정확성이 떨어진다.var buf = Buffer.isBuffer(body)
? body
: new Buffer(body, encoding)
var len = buf.length
return 'W/"' + len.toString(16) + '-' + crc32.unsigned(buf) + '"'
Express에선 CRC32 방식을 사용하여 인코딩. Semantically equivalent 하지만 모든 byte가 일치한다는 것을 보장할 순 없음참고자료
304 Not Modified - HTTP | MDN
What is HTTP ETag? - GeeksforGeeks
ETag - HTTP | MDN
Express.js 서버는 왜 304를 반환하는 걸까?