cookie & session - TEAM-ARK/inflearn-clone-front GitHub Wiki

Cookie

์ฟ ํ‚ค๋Š” ๋ธŒ๋ผ์šฐ์ €์— ์ €์žฅ๋˜๋Š” ๋ฌธ์ž์—ด๋กœ RFC 6265์—์„œ ์ •์˜ํ•œ HTTP ํ”„๋กœํ† ์ฝœ์˜ ์ผ๋ถ€์ด๋‹ค.

HTTP ํ”„๋กœํ† ์ฝœ์—๋Š” ๋น„์—ฐ๊ฒฐ์„ฑ (Connectionless)๊ณผ ๋น„์ƒํƒœ์„ฑ (Stateless)์˜ ํŠน์ง•์ด ์žˆ๋‹ค. ๋ชจ๋“  ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ๋งˆ๋‹ค ์—ฐ๊ฒฐ๊ณผ ํ•ด์ œ์˜ ๊ณผ์ •์„ ๊ฑฐ์น˜๋ฉฐ ์—ฐ๊ฒฐ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š๊ณ  ํ•ด์ œ ํ›„์—๋„ ์ƒํƒœ ์ •๋ณด๋ฅผ ์ €์ •ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„์˜ ์ž์›์„ ํฌ๊ฒŒ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋กœ ์ธํ•ด ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์ด๋ผ๋„ ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๋กœ ์ธ์‹ํ•˜๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŠน์„ฑ๋“ค์„ ๋ณด์™„ํ•œ ๊ธฐ์ˆ ์ด ์ฟ ํ‚ค์™€ ์„ธ์…˜์ด๋‹ค.

์„ธ์…˜์€ ์ฟ ํ‚ค๋ฅผ ์ด์šฉํ•œ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์„œ๋ฒ„์— ์š”์ฒญ์„ ํ•˜๋ฉด ์„œ๋ฒ„๋Š” ์„ธ์…˜ ์•„์ด๋””๋ฅผ ํ• ๋‹นํ•˜์—ฌ ์‘๋‹ต์‹œ ํ•จ๊ป˜ ์ „๋‹ฌํ•œ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” ์„ธ์…˜ ์•„์ด๋””๋ฅผ ์ฟ ํ‚ค์— ์ €์žฅํ•˜๊ณ  ๋งค ์š”์ฒญ๋งˆ๋‹ค ์„ธ์…˜์•„์ด๋””๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์„œ๋ฒ„๋Š” ์„ธ์…˜ ์•„์ด๋””๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•˜์—ฌ ์‚ฌ์šฉ์ž์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์— ์ €์žฅํ•˜์—ฌ ๊ด€๋ฆฌํ•œ๋‹ค.

์ฟ ํ‚ค๋Š” ์„œ๋ฒ„๊ฐ€ ์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์— ์ €์žฅํ•˜๋Š” ๋ฐ์ดํ„ฐ์ด๋ฉฐ ํ˜•ํƒœ๋Š” Key & Value๋กœ ๊ตฌ์„ฑ๋˜๊ณ  String์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค. 4KB ์ด์ƒ์˜ ์ €์žฅ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

์ฟ ํ‚ค์˜ ์„ธ ๊ฐ€์ง€ ๋ชฉ์ 

  1. ์„ธ์…˜ ๊ด€๋ฆฌ (Session management)
  • ๋กœ๊ทธ์ธ, ์žฅ๋ฐ”๊ตฌ๋‹ˆ, ์ ‘์† ์‹œ๊ฐ„ ๋“ฑ ์„œ๋ฒ„๊ฐ€ ์•Œ์•„์•ผ ํ•  ์ •๋ณด ์ €์žฅ
  1. ๊ฐœ์ธํ™” (Personalization)
  • ์‚ฌ์šฉ์ž๋งˆ๋‹ค ๋‹ค๋ฅธ ํŽ˜์ด์ง€ ๋ณด์—ฌ์ฃผ๊ธฐ
  1. ํŠธ๋ž˜ํ‚น (Tracking)
  • ์‚ฌ์šฉ์ž์˜ ํ–‰๋™๊ณผ ํŒจํ„ด ๋ถ„์„

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ์š”์ฒญ์„ ํ•˜๋ฉด ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต์‹œ ์ฟ ํ‚ค์— ์ €์žฅํ•˜๊ณ ์žํ•˜๋Š” ์ •๋ณด๋ฅผ ํ—ค๋”์˜ Set-Cookie๋กœ ์ „๋‹ฌํ•œ๋‹ค.

Set-Cookie: <cookie-name>=<cookie-value>

ํด๋ผ์ด์–ธํŠธ๋Š” ์ฟ ํ‚ค๋ฅผ ์‘๋‹ต๋ฐ›์€ ํ›„ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜๋Š” ๋ชจ๋“  ์š”์ฒญ์— ์ €์žฅ๋œ ์ฟ ํ‚ค๋ฅผ ํ—ค๋”์˜ Cookie๋กœ ์ „๋‹ฌํ•œ๋‹ค.

Cookie: <cookie-name>=<cookie-value>

์„œ๋ฒ„๊ฐ€ ์ฟ ํ‚ค์™€ ํ•จ๊ป˜ ์•„๋ž˜์™€ ๊ฐ™์€ ์‘๋‹ต์„ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ–ˆ๋‹ค๋ฉด

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

[page content]

ํด๋ผ์ด์–ธํŠธ๋Š” ์ €์žฅ๋œ ์ฟ ํ‚ค๋ฅผ ํ—ค๋”์— ํฌํ•จํ•ด ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.

GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ข…๋ฃŒ๋˜๋”๋ผ๋„ ์ฟ ํ‚ค๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์‹ถ์œผ๋ฉด Permanent ์ฟ ํ‚ค๋ฅผ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค. ์ฟ ํ‚ค ์ƒ์„ฑ์‹œ Expires & Max-Age ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

  • Expires : ์ฟ ํ‚ค๊ฐ€ ๋งŒ๋ฃŒ ๋  ๋‚ ์งœ๋ฅผ ์ง€์ •
  • Max-Age : ํ˜„์žฌ ์‹œ๊ฐ„์„ ๊ธฐ์ค€์œผ๋กœ ์–ผ๋งŒํผ ์œ ์ง€์‹œํ‚ฌ์ง€ ๊ฒฐ์ •
Set-Cookie: yummy_cokie=choco; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

Secure / HttpOnly / Path / Domain / samesite

  • ์ฟ ํ‚ค๋ฅผ ์ œ์–ดํ•˜๋Š” ์˜ต์…˜
    • Secure : https ํ”„๋กœํ† ์ฝœ ์ƒ์—์„œ ์•”ํ˜ธํ™” ๋œ ์š”์ฒญ์ผ ๊ฒฝ์šฐ์—๋งŒ ์ „์†ก
    • HttpOnly : Cross-site ์Šคํฌ๋ฆฝํŒ… ๊ณต๊ฒฉ์„ ๋ฐฉ์ง€ํ•œ๋‹ค. JS์˜ document.cookie API์—์„œ ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅ
    • Domain & Path : ์ฟ ํ‚ค๋ฅผ ํŠน์ • Domain & Path์—์„œ๋งŒ ์ œํ•œํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ, ํ•˜์œ„ ๋„๋ฉ”์ธ์—์„œ๋„ ๋™์ž‘ํ•จ
    • samesite : XSRF ๋ณดํ˜ธ ํ† ํฐ ์—†์ด ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ์š”์ฒญ ์œ„์กฐ๋ฅผ ๋ง‰์„ ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜, samesite=strict ์˜ต์…˜์ด ์žˆ๋Š” ์ฟ ํ‚ค๋Š” ์™ธ๋ถ€์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ผ๋•Œ ์ฟ ํ‚ค ์ „์†ก์ด ์ ˆ๋Œ€ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค

์ฟ ํ‚ค์˜ ์šฉ๋„

  • ๋กœ๊ทธ์ธ ์ƒํƒœ ์œ ์ง€
  • 7์ผ๊ฐ„ ๋‹ค์‹œ ๋ณด์ง€ ์•Š๊ธฐ (์ฟ ํ‚ค์˜ ๋‚ ์งœ๋ฅผ ๊ธฐ๋กํ•˜์—ฌ ๋‹ค์‹œ ๋ฐฉ๋ฌธํ•˜์˜€์„๋•Œ ์‹œ๊ฐ„์ฐจ๋ฅผ ์ด์šฉ)
  • ์ตœ๊ทผ ๊ฒ€์ƒ‰ ์ƒํ’ˆ ์ถ”์ฒœ
  • ์žฅ๋ฐ”๊ตฌ๋‹ˆ

document.cookie ํ”„๋กœํผํ‹ฐ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ฟ ํ‚ค์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ ์ฝ๊ณ  ์“ฐ๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ฟ ํ‚ค์˜ ์ด๋ฆ„๊ณผ ๊ฐ’์—” ํŠน๋ณ„ํ•œ ์ œ์•ฝ์ด ์—†์œผ๋‚˜ ์œ ํšจ์„ฑ์„ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ˜๋“œ์‹œ ๋‚ด์žฅ ํ•จ์ˆ˜ encodeURIComponent๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด์Šค์ผ€์ดํ”„ ์ฒ˜๋ฆฌํ•ด์ค˜์•ผ ํ•œ๋‹ค.

// ์ฟ ํ‚ค ์ฝ๊ธฐ
alert( document.cookie ); // cookie1=value1; cookie2=value2;...

// ์ฟ ํ‚ค ์“ฐ๊ธฐ
document.cookie = "user=John"; // ์ด๋ฆ„์ด 'user'์ธ ์ฟ ํ‚ค์˜ ๊ฐ’๋งŒ ๊ฐฑ์‹ ํ•จ
alert(document.cookie); // ๋ชจ๋“  ์ฟ ํ‚ค ๋ณด์—ฌ์ฃผ๊ธฐ


// ํŠน์ˆ˜ ๊ฐ’(๊ณต๋ฐฑ)์€ ์ธ์ฝ”๋”ฉ ์ฒ˜๋ฆฌํ•ด ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
let name = "my name";
let value = "John Smith"

// ์ธ์ฝ”๋”ฉ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด, ์ฟ ํ‚ค๋ฅผ my%20name=John%20Smith ๋กœ ๋ณ€๊ฒฝํ•˜์˜€์Šต๋‹ˆ๋‹ค.
document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value);

alert(document.cookie); // ...; my%20name=John%20Smith

Session

์ฟ ํ‚ค๋งŒ์„ ์‚ฌ์šฉํ•˜์—ฌ ์•„์ด๋””, ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ฟ ํ‚ค์— ์ €์žฅํ•œ๋‹ค๋ฉด ๋กœ๊ทธ์ธ ์ƒํƒœ์˜ ์œ ์ง€๋Š” ๊ฐ€๋Šฅํ•˜๋‚˜ ๋ณด์•ˆ์ƒ ํฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. Session์€ ๋น„๋ฐ€๋ฒˆํ˜ธ์™€ ๊ฐ™์€ ์ธ์ฆ ์ •๋ณด๋ฅผ ์ฟ ํ‚ค์— ์ €์žฅํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉ์ž ์‹๋ณ„์ž์ธ JSESSIONID๋ฅผ ์ €์žฅํ•œ๋‹ค. ์„œ๋ฒ„์—๋Š” ์ธ์ฆ ์ •๋ณด ๋ฐ ID์— ํ•ด๋‹นํ•˜๋Š” ๋กœ๊ทธ์ธ ์ƒํƒœ, ์‹œ๊ฐ„, ๋งŒ๋ฃŒ๊ธฐํ•œ ๋“ฑ์˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•œ๋‹ค. ์„œ๋ฒ„๋Š” ๋ณด์•ˆ์ƒ์˜ ๋ฌธ์ œ๋กœ ์ธ์ฆ์— Session์„ ์‚ฌ์šฉํ•œ๋‹ค.

์„ธ์…˜์˜ ๋™์ž‘ ์ˆœ์„œ

  1. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค (์ฒซ ์š”์ฒญ์€ ์„ธ์…˜ ID๊ฐ€ ์—†์Œ)
  2. ์„œ๋ฒ„์—์„œ ์ฟ ํ‚ค ๊ฐ’์— session id ์—†๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜๊ณ  ๋ฐœ๊ธ‰ํ•˜์—ฌ ์‘๋‹ต
  3. ํด๋ผ์ด์–ธํŠธ๋Š” ์ „๋‹ฌ๋ฐ›์€ session id๊ฐ’์„ ์š”์ฒญ๋งˆ๋‹ค ์ฟ ํ‚ค ํ—ค๋”์— ๋„ฃ์–ด์„œ ์š”์ฒญ
  4. ์„œ๋ฒ„๋Š” session id๋ฅผ ํ™•์ธํ•˜์—ฌ ์‚ฌ์šฉ์ž ์‹๋ณ„
  5. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋กœ๊ทธ์ธ์„ ์š”์ฒญ ํ•  ๋•Œ ๋งˆ๋‹ค ์„œ๋ฒ„๋Š” ์ƒˆ๋กœ์šด session id๋ฅผ ๋ฐœ๊ธ‰ํ•˜์—ฌ ์‘๋‹ต
  6. ํด๋ผ์ด์–ธํŠธ ์ข…๋ฃŒ์‹œ session id ์ œ๊ฑฐ, ์„œ๋ฒ„์—์„œ session ์ œ๊ฑฐ

์„ธ์…˜ ํŠน์ง•

  • ์„ธ์…˜ ์•„์ด๋””๋Š” ๋ธŒ๋ผ์šฐ์ € ๋‹จ์œ„๋กœ ์ €์žฅ๋˜๊ณ  ์‚ญ์ œ๋œ๋‹ค
  • ๋กœ๊ทธ์•„์›ƒ ํ›„ ๋กœ๊ทธ์ธ์‹œ ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๋กœ ์ธ์‹ํ•˜์—ฌ ์ƒˆ๋กœ์šด ์„ธ์…˜์ด ์ƒ์„ฑ๋œ๋‹ค
  • ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญ ํ•  ๋•Œ ๋งˆ๋‹ค ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์„ธ์…˜์— ๋‹ด์•„๋‘๋ฉด DB์— ์ ‘๊ทผํ•  ํ•„์š”๊ฐ€ ์—†์–ด ํšจ์œจ์ ์ด๋‹ค

๋ณด์•ˆ ์„ธ์…˜ ์•„์ด๋””๋ฅผ ํ›”์นœ๋‹ค๋ฉด ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ๊ทธ์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. https๋กœ ํ†ต์‹ ํ•˜๋Š”๊ฒƒ์ด ๋ณด์•ˆ์ƒ ์ข‹์œผ๋ฉฐ ์ฟ ํ‚ค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์„ธ์…˜์˜ ์˜ต์…˜์„ secure true๋กœ ํ•˜๋ฉด https์—์„œ๋งŒ ์š”์ฒญ/์‘๋‹ต์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ HttpOnly true๋กœ ํ•˜๋ฉด JS๋ฅผ ํ†ตํ•˜์—ฌ ์„ธ์…˜ ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋„๋ก ๊ฐ•์ œ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค

ํ”„๋ก ํŠธ์—์„œ ์šฐ์•„ํ•˜๊ฒŒ ์ฟ ํ‚ค ์กฐํšŒํ•˜๊ธฐ

// ์ฟ ํ‚ค ์กฐํšŒ
const cookies = Object.fromEntries(
  document.cookie.split(';').map((cookie) => cookie.trim().split('=')),
);

// ์›ํ•˜๋Š” key๋ฅผ ํ™•์ธํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ
const isExistCookie = Object.prototype.hasOwnProperty.call(cookies, [target-cookie]);

์ฐธ๊ณ 

MDN ํ•ธ๋“œ๋ถ ํ”„๋ก ํŠธ์—์„œ ์šฐ์•„ํ•˜๊ฒŒ ์ฟ ํ‚ค ์กฐํšŒ