cookie & session - TEAM-ARK/inflearn-clone-front GitHub Wiki
Cookie
์ฟ ํค๋ ๋ธ๋ผ์ฐ์ ์ ์ ์ฅ๋๋ ๋ฌธ์์ด๋ก RFC 6265์์ ์ ์ํ HTTP ํ๋กํ ์ฝ์ ์ผ๋ถ์ด๋ค.
HTTP ํ๋กํ ์ฝ์๋ ๋น์ฐ๊ฒฐ์ฑ (Connectionless)๊ณผ ๋น์ํ์ฑ (Stateless)์ ํน์ง์ด ์๋ค. ๋ชจ๋ ์ฌ์ฉ์์ ์์ฒญ๋ง๋ค ์ฐ๊ฒฐ๊ณผ ํด์ ์ ๊ณผ์ ์ ๊ฑฐ์น๋ฉฐ ์ฐ๊ฒฐ ์ํ๋ฅผ ์ ์งํ์ง ์๊ณ ํด์ ํ์๋ ์ํ ์ ๋ณด๋ฅผ ์ ์ ํ์ง ์๊ธฐ ๋๋ฌธ์ ์๋ฒ์ ์์์ ํฌ๊ฒ ์ ์ฝํ ์ ์๋ค. ํ์ง๋ง, ์ด๋ก ์ธํด ์ฌ์ฉ์๋ฅผ ์๋ณํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ ์ฌ์ฉ์์ ์์ฒญ์ด๋ผ๋ ๋งค๋ฒ ์๋ก์ด ์ฌ์ฉ์๋ก ์ธ์ํ๋ ๋จ์ ์ด ์๋ค. ์ด๋ฌํ ํน์ฑ๋ค์ ๋ณด์ํ ๊ธฐ์ ์ด ์ฟ ํค์ ์ธ์ ์ด๋ค.
์ธ์ ์ ์ฟ ํค๋ฅผ ์ด์ฉํ๋ค. ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ฒ์ ์์ฒญ์ ํ๋ฉด ์๋ฒ๋ ์ธ์ ์์ด๋๋ฅผ ํ ๋นํ์ฌ ์๋ต์ ํจ๊ป ์ ๋ฌํ๋ค. ๋ธ๋ผ์ฐ์ ๋ ์ธ์ ์์ด๋๋ฅผ ์ฟ ํค์ ์ ์ฅํ๊ณ ๋งค ์์ฒญ๋ง๋ค ์ธ์ ์์ด๋๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ด๋ค. ์๋ฒ๋ ์ธ์ ์์ด๋๋ฅผ ๋ฐํ์ผ๋ก ์ฌ์ฉ์๋ฅผ ์๋ณํ์ฌ ์ฌ์ฉ์์ ๋ฐ์ดํฐ๋ฅผ ์๋ฒ์ ์ ์ฅํ์ฌ ๊ด๋ฆฌํ๋ค.
์ฟ ํค๋ ์๋ฒ๊ฐ ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ์ ์ ์ฅํ๋ ๋ฐ์ดํฐ์ด๋ฉฐ ํํ๋ Key & Value๋ก ๊ตฌ์ฑ๋๊ณ String์ผ๋ก ์ด๋ฃจ์ด์ ธ ์๋ค. 4KB ์ด์์ ์ ์ฅ์ ๋ถ๊ฐ๋ฅํ๋ค.
์ฟ ํค์ ์ธ ๊ฐ์ง ๋ชฉ์
- ์ธ์ ๊ด๋ฆฌ (Session management)
- ๋ก๊ทธ์ธ, ์ฅ๋ฐ๊ตฌ๋, ์ ์ ์๊ฐ ๋ฑ ์๋ฒ๊ฐ ์์์ผ ํ ์ ๋ณด ์ ์ฅ
- ๊ฐ์ธํ (Personalization)
- ์ฌ์ฉ์๋ง๋ค ๋ค๋ฅธ ํ์ด์ง ๋ณด์ฌ์ฃผ๊ธฐ
- ํธ๋ํน (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์ ์ฌ์ฉํ๋ค.
์ธ์ ์ ๋์ ์์
- ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์ ์์ฒญ์ ๋ณด๋ธ๋ค (์ฒซ ์์ฒญ์ ์ธ์ ID๊ฐ ์์)
- ์๋ฒ์์ ์ฟ ํค ๊ฐ์ session id ์๋ ๊ฒ์ ํ์ธํ๊ณ ๋ฐ๊ธํ์ฌ ์๋ต
- ํด๋ผ์ด์ธํธ๋ ์ ๋ฌ๋ฐ์ session id๊ฐ์ ์์ฒญ๋ง๋ค ์ฟ ํค ํค๋์ ๋ฃ์ด์ ์์ฒญ
- ์๋ฒ๋ session id๋ฅผ ํ์ธํ์ฌ ์ฌ์ฉ์ ์๋ณ
- ํด๋ผ์ด์ธํธ๊ฐ ๋ก๊ทธ์ธ์ ์์ฒญ ํ ๋ ๋ง๋ค ์๋ฒ๋ ์๋ก์ด session id๋ฅผ ๋ฐ๊ธํ์ฌ ์๋ต
- ํด๋ผ์ด์ธํธ ์ข ๋ฃ์ 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]);