ETag (์ํฐํฐ ํ๊ทธ)๋ ๋ฆฌ์์ค ๋ฒ์ ์ ์๋ณํ๋ ๋ฐ ์ฌ์ฉ๋๋ HTTP ์๋ต ํ๋์ ๋๋ค. ์ด๋ HTTP/1.1 ์ฌ์์ ์ผ๋ถ์ ๋๋ค.
ETag์ ํจ๊ป ์๊ฒฉ ์๋ฒ๋ก ์์ฒญ์ด ์ ์ก๋๋ฉด ์๋ฒ๋ ETag๊ฐ์ ๋น๊ตํ์ฌ ํน์ ๋ฆฌ์์ค ๋ณ๊ฒฝ ๋์๋์ง ๋๋ ๋์ผํ๊ฒ ์ ์ง๋๋์ง๋ฅผ ์ ์ ์์ต๋๋ค. ๊ทธ ๊ฐ์ด ๊ฐ์ผ๋ฉด ์๋ฒ๋ ์์ฒญ๋ ์ฝํ ์ธ ์์ด ์ํ ์ฝ๋ 304๋ก ์๋ตํ ๊ฒ๋๋ค.
๋ถ์ธ ์ฑ๋ช ํ๊ตญ์ด ์ค๋ ฅ์ด ๋ถ์ ํ์ฌ ์ด ๊ธ์ด ๊ตฌ๊ธ ๋ฒ์ญ๊ธฐ๋ฅผ ์ฃผ๋ก ํ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ถ์ ํํ ๋ฌธ๋ฒ๊ณผ ์ดํ๊ฐ ์์์ ์์ต๋๋ค. ์ด ์ ์ํด ๋ถํ๋๋ฆฌ๋ฉฐ, ์ถํ์ ๋ค์ ๊ฒํ ํ์ฌ ์์ ํ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด๋ฌํ ๋์์ ํจ์จ์ ์ธ ์บ์ฑ๊ณผ ์กฐ๊ฑด๋ถ ์์ฒญ์ ์ฉ์ดํ๊ฒ ํ์ฌ ๋์ญํญ ์ฌ์ฉ๋์ ์ค์ด๊ณ ์น ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. ๋ํ, ETag๋ ๋์ ๋ฆฌ์์ค๋ฅผ ์ ๋ฐ์ดํธํ๋ ค๋ ์ฌ๋ฌ ์์ฒญ์ด ๋์์ ๋ฐ์ํ ๋ ๋ฐ์ํ๋ ๊ฒฝ์ ์กฐ๊ฑด์ ๋ฐฉ์งํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด ํ์์ "๊ณต์ค ์ถฉ๋"์ด๋ผ๊ณ ํฉ๋๋ค.
์๋์๋ฆฌ
- ์์ฑ: ์๋ฒ๋ ๋จผ์ ์ฌ์ฉ์ ๊ฐ์ฒด์ ๊ฐ์ ํน์ ๋ฆฌ์์ค์ ๋ํ ๊ณ ์ ์๋ณ์๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ ์ผ๋ฐ์ ์ผ๋ก ์ฝํ ์ธ ์ ํด์ ๋๋ ์ง๋ฌธ์ ๋๋ค. ๊ฐ์ฒด๊ฐ ์ ๋ฐ์ดํธ๋๋ฉด ๊ณ ์ ์๋ณ์๋ ๋ณ๊ฒฝ๋ฉ๋๋ค.
- ๊ฒ์ฆ: ๋์ผํ ๋ฆฌ์์ค์ ๋ํ ํ์ ์์ฒญ์ ๊ฒฝ์ฐ ํด๋ผ์ด์ธํธ๋
If-None-Matchํค๋๋ฅผ ํตํด ETag ๊ฐ์ ์ ์กํฉ๋๋ค. - ๋น๊ต: ์๋ฒ๋ ํด๋ผ์ด์ธํธ ETag ๊ฐ์ ์๋ฒ๊ฐ ๊ณ์ฐํ ํ์ฌ ETag ๊ฐ๊ณผ ๋น๊ตํ์ฌ ๋์ผํ์ง ํ๋จํ๊ณ ๋น๊ต ๊ฒฐ๊ณผ์ ๋ฐ๋ผ
304 Not Modified๋๋200 OK๋ฅผ ๋ฐํํฉ๋๋ค.
Node.js์ ๊ตฌํ
๋ค์ ์ฝ๋๋ Express.js์์ ETag(๊ฐ๋ ฅ)๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
app.get('/api/user/:id', (req, res) => {
const user = getUser(req.params.id);
const etag = '"' + hash(user) + '"';
if (req.headers['if-none-match'] === etag) {
return res.status(304).end();
}
res.set('ETag', etag);
res.json(user);
});๊ฐ๋ ฅํ E-Tag ์ฝํ E-Tag
ETag์๋ ๋ ๊ฐ์ง ์์ต๋๋ค.
- ๊ฐ๋ ฅํ ETags: ๋์ผํ ๋ฆฌ์์ค๋ฅผ ๋ณด์ฅํฉ๋๋ค. ์ฆ, ETag๋ ๋ฆฌ์์ค ์์ฒด ์ ์ฒด์์ ํ์๋๋ค๋ ์๋ฏธ์ ๋๋ค.
ETag: "abc123"- ์ฝํ ETags: ์๋ฏธ์ ๋๋ฑ์ฑ์ ๋ํ๋ด์ง๋ง ๋ฐ์ดํธ ๋จ์์ ๋์ผ์ฑ์ ๋ํ๋ด์ง ์์ผ๋ฉฐ
W/์ ๋์ฌ๊ฐ ๋ถ์ต๋๋ค.
ETag: W/"abc123"ํฐ๋ฐ์ดํ๋ก ๋ฌถ์ธ ETag ์ฌ๋ฐ๋ฅธ ETag๊ฐ ํฐ๋ฐ์ดํ๋ก ๋ฌถ์ด์ผ ํฉ๋๋ค.
๋ค์์ user ๋ฆฌ์์ค๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
{
"name": "Shaun",
"age": 27
}๋ค์ ํ๋ ๊ฐ๋ ฅํ ETag์ ์ฝํ ETag๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
| ์ ํ | ETag๋ฅผ ๊ณ์ฐํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์์ฑ | ETag | ์ค๋ช |
|---|---|---|---|
| ๊ฐ๋ ฅํ | ๋ชจ๋ ์์ฑ | "Abc123" | ์ ํํ ์ผ์น๊ฐ ํ์ํฉ๋๋ค |
| ์ฝํ | name ์์ฑ๋ง | W/"Abc124" | ๋ถ๋ถ ์ผ์น๋ ํ์ฉ๋ฉ๋๋ค |
E-Tag์ ๋จ์
๋ก๋ ๋ฐธ๋ฐ์ ์ถฉ๋

ETag๋ฅผ ์ฌ๋ฌ ์๋ฒ ์ธ์คํด์ค์ ์ญ๋ฐฉํฅ ํ๋ก์ ์ญํ ์ ํ๋ ๋ก๋ ๋ฐธ๋ฐ์์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ๋ฆฌ์์ค๊ฐ ์์ ๋์ง ์์๋๋ผ๋ ๊ฐ๋ณ ์๋ฒ์์ ์ ์ก๋๋ ETag๊ฐ ๋ค๋ฅผ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ETag๋ ์ฌ์ค์ ์ธ๋ชจ๊ฐ ์์ผ๋ฉฐ ํด๋ผ์ด์ธํธ์ ์๋ฒ์ ์ค๋ฒํค๋๋ฅผ ๋ฐ์์ํต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ์น ์๋ฒ๋ฅผ ๊ตฌ์ฑํ์ฌ ๊ฒฐ์ ์ ETag๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
๋ณต์กํ ๊ตฌํ
ETag๋ฅผ ์ธ์ํ๋ ํ๊ฒฝ์ ๊ตฌํํ๋ ๊ฒ์ ๋ณต์กํฉ๋๋ค. ํด๋ผ์ด์ธํธ๋ If-None-Match ํค๋์ ํจ๊ป ์์ฒญ์ ์ ์กํ๋ ๋ก์ง์ ๊ฐ์ง๊ณ ์์ด์ผ ํ๋ฉฐ, ์๋ฒ๋ ํด๋น ํค๋๋ฅผ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.

๋น์ค๋ฆฌ์ ์ธ ์ถ์
Hulu๋ฐ ๋ค๋ฅธ ๋๊ธฐ์ ๊ฐ ETag๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๋ค์ ์ถ์ ํฉ๋๋ค. ์ฌ์ฉ์๊ฐ ์ฝ๊ฒ ์ ๊ทผํ๊ณ ์ญ์ ํ ์ ์๋ ์ฟ ํค์ ๋ฌ๋ฆฌ, ETag๋ ๋ธ๋ผ์ฐ์ ์์ ์์ ํ ๊ด๋ฆฌ๋ฉ๋๋ค. ์ฌ์ฉ์๊ฐ ์์ฒญ์ ์คํํ๊ธฐ ์ ์ ETag ํค๋๋ฅผ ์๋์ผ๋ก ์ญ์ ํ ๋งํผ ๊ธฐ์ ์ ๋ฅ์ํ์ง ์๋ค๋ฉด, ์ด๋ฅผ ์ฐํํ ๋ฐฉ๋ฒ์ด ์ฌ์ค์ ์์ต๋๋ค.
์ด ํ์ฌ๋ ETag๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์๊ฒ 1ํฝ์ ์ด๋ฏธ์ง์ ๊ฐ์ ์์ฒญ๋์ง ์์ ๋ฆฌ์์ค๋ฅผ ์์ฑํ๊ณ , ๋ธ๋ผ์ฐ์ ๊ฐ ์์ฒญ์ ์์ ํ ๋๋ง๋ค ํญ์ 304 ์๋ต์ ๋ฐํํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ์ด๋ฌํ ๋์์ ์ฌ์ฉ์๊ฐ ์์ฒญํ ์ํ์ ๊ฐ์ด ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉ์์ ํ๋์ ์ถ์ ํ ์ ์๋ ์๋ฒ์์ ์ธ์ ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค์ ํฉ๋๋ค.