리소스의 특정 버전을 가리키는 식별자를 담은 HTTP 응답 헤더(entity tag). 클라이언트가 이 값을 다시 보내 "그사이 바뀌었는지"를 묻는 조건부 요청(Conditional Request)의 기준이 된다. RFC(Request for Comments) 9110에 정의된 표준 헤더다.
GET /style.css
→ 200 OK
ETag: "33a64df5"
GET /style.css
If-None-Match: "33a64df5"
→ 304 Not Modified (본문 없음, 캐시 재사용)- 같으면
304로 본문 전송을 생략해 대역폭을 아낀다. 다르면200과 새 본문, 새 ETag가 온다 → 브라우저 캐시 Last-Modified/If-Modified-Since와 같은 역할이지만 초 단위 시각이 아니라 버전 자체를 비교하므로 더 정확하다W/"..."는 약한 ETag다. 바이트가 똑같지 않아도 의미상 같으면 같은 값으로 친다(압축 방식만 다른 경우 등)
버전 토큰으로 다루기
표준은 "버전을 식별한다"는 역할만 정하고 만드는 방법은 정하지 않는다. AWS S3(Amazon Simple Storage Service)나 Cloudflare R2 같은 객체 저장소도 객체마다 ETag를 붙이는데, 단일 업로드에서는 MD5(Message-Digest Algorithm 5)처럼 보여도 멀티파트 업로드나 암호화 방식에 따라 MD5가 아니다. 그래서:
- ETag를 파일 내용 해시로 해석하지 않는다. "이 객체의 현재 버전 토큰"으로만 쓴다
- 낙관적 잠금(Optimistic Locking)에 쓰기 좋다. 읽을 때 받은 ETag를 저장할 때
If-Match로 보내면, 그사이 누가 바꿨을 경우412 Precondition Failed로 실패한다. 덮어쓰기 충돌을 막는다 → 멱등성 - 사용자에게 보여 줄 수정 시각은 ETag가 아니라
Last-Modified(또는 저장소의 수정 시각 필드)를 쓴다