-
[Node.js] JWT(Json Web Token)๋ฅผ ์ด์ฉํ ๋ก๊ทธ์ธ ์ธ์ฆ ๊ตฌํ๐ Node.js 2026. 7. 14. 01:25
๐ JWT๋?
JWT(Json Web Token)๋ ์๋ฒ๊ฐ ์ฌ์ฉ์์ ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ์ธ์ฆํ ํ ๋ฐ๊ธํ๋ ํ ํฐ(Token) ๊ธฐ๋ฐ์ ์ธ์ฆ ๋ฐฉ์์ด๋ค.
๊ธฐ์กด์ Session ๋ฐฉ์์ ์๋ฒ๊ฐ ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ๋ฉ๋ชจ๋ฆฌ๋ DB์ ์ ์ฅํ์ฌ ๊ด๋ฆฌํ์ง๋ง,
JWT๋ ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ํ ํฐ ์์ ๋ด์ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌํ๋ค.
์ดํ ํด๋ผ์ด์ธํธ๋ ์๋ฒ์ ์์ฒญํ ๋๋ง๋ค JWT๋ฅผ ํจ๊ป ์ ์กํ๊ณ , ์๋ฒ๋ ํ ํฐ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ์ฌ ์ฌ์ฉ์๋ฅผ ์ธ์ฆํ๋ค.
์ฆ, ์๋ฒ๊ฐ ๋ณ๋์ ๋ก๊ทธ์ธ ์ธ์ ์ ์ ์ฅํ์ง ์์๋ ์ฌ์ฉ์๋ฅผ ์๋ณํ ์ ์๋ค.
JWT ๋์๊ณผ์
JWT ์ธ์ฆ์ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ๋์ํ๋ค.
1. ์ฌ์ฉ์ ๋ก๊ทธ์ธ
2. ์์ด๋ / ๋น๋ฐ๋ฒํธ ์ ์ก
3. ์๋ฒ์์ ์ฌ์ฉ์ ํ์ธ
4. JWT ์์ฑ
5. HttpOnly Cookie ์ ์ฅ
6. ๋ธ๋ผ์ฐ์ ๊ฐ ์ดํ ์์ฒญ๋ง๋ค Cookie ์๋ ์ ์ก
7. ์๋ฒ๊ฐ JWT ๊ฒ์ฆ
8. ์ธ์ฆ ์ฑ๊ณต ํ ์์ฒญ ์ฒ๋ฆฌ
์ฌ๊ธฐ์์ ์ HttpOnly Cookie์ ์ ์ฅ์ ํ๋์ง ๊ฐ๋ตํ ์์๋ณด์.
๋ณดํต JWT๋ ํฌ๊ฒ ์ธ ๊ณณ์ ์ ์ฅ์ ํ ์ ์๋ค.
1. LocalStorage
- ์ฌ์ฉ๋ฐฉ์
localStorage.setItem("token", token)- ๋ธ๋ผ์ฐ์ ๋ฅผ ์ข ๋ฃํด๋ ๋จ์ ์๋ค.
- ์ปดํจํฐ๋ฅผ ์ฌ๋ถํ ํด๋ ๋จ์ ์๋ค.
- ์ฌ์ฉ์๊ฐ ์ง์ ๋ก๊ทธ์์ํ๊ฑฐ๋ localStorage.removeItem()์ ํธ์ถํด์ผ ์ญ์ ๋๋ค.
2. SessionStorage
- ์ฌ์ฉ๋ฐฉ์
sessionStorage.setItem("token",token)- ํ์ฌ ๋ธ๋ผ์ฐ์ ํญ์์๋ง ์ ์ง๋๋ค.
- ํญ์ ๋ซ์ผ๋ฉด ์ฌ๋ผ์ง๋ค.
- ๋ค๋ฅธ ํญ์์๋ ๊ณต์ ๋์ง ์๋๋ค.
3. HttpOnly Cookie
- ์ฌ์ฉ๋ฐฉ์
res.cookie("token",token, { httpOnly:true, maxAge:60*60*1000 })๊ทผ๋ฐ ์ฌ๊ธฐ์๋ 2๊ฐ์ง ๋ฐฉ์์ธ Session Cookie, Persistent Cookie ๋ก ๋๋๋ค.
Session Cookie๋
- res.cookie("token", token, { httpOnly: true })
maxAge๋ expires๋ฅผ ์ง์ ํ์ง ์์ผ๋ฉด, ๋ธ๋ผ์ฐ์ ๋ฅผ ์ข ๋ฃํ๋ ์๊ฐ ์ญ์ ๋๋ค.
Persistent Cookie ๋
- res.cookie("token", token, { httpOnly: true, maxAge: 1000 * 60 * 60 * 24 * 7 })
์์ ๊ฐ์ด maxAge๋ฅผ ์ค์ ํจ์ผ๋ก์จ 7์ผ๋์ ์ ์ง๋๋ค.
๊ทธ๋์ ์ฌ์ฉ๋ฐฉ์ ์๋์ ์๋ ์ฝ๋๋ฅผ ๊ธฐ์ค์ผ๋ก๋
- ๋ธ๋ผ์ฐ์ ๋ฅผ ๊ป๋ค ์ผ๋ 1์๊ฐ ๋์์ ๋ก๊ทธ์ธ ์ ์ง
- 1์๊ฐ์ด ์ง๋๋ฉด Cookie๊ฐ ๋ง๋ฃ๋์ด ๋ค์ ๋ก๊ทธ์ธํด์ผ ํจ
- JavaScript์์๋ ํ ํฐ์ ์ฝ์ ์ ์์
- ๋ธ๋ผ์ฐ์ ๊ฐ API ์์ฒญ ์ Cookie๋ฅผ ์๋์ผ๋ก ์ ์ก
์ ๊ฐ์ ํน์ง์ด ์๋ค.
๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ XSS(Cross Site Scripting) ์ด๋ค.
๋ง์ฝ LocalStorage๋ฅผ ์ฌ์ฉํ๋ ์ํ์์ ์ฌ์ดํธ์ ์ ์ฑ ์คํฌ๋ฆฝํธ๊ฐ ์ฝ์ ๋๋ฉด
const token = localStorage.getItem("token")์ด๋ ๊ฒ JWT๋ฅผ ๊ทธ๋๋ก ์ฝ์ด๊ฐ ์ ์๋ค.๋ฌผ๋ก SessionStorage์์๋sessionStorage.getItem("token")์์ ๊ฐ์ ํ๋๋ก ํ์ทจ๋นํ๊ธฐ ์ฌ์ด ๊ฒ์ ๋ง์ฐฌ๊ฐ์ง์ด๋ค.ํ์ง๋ง HttpOnly Cookie๋ ๋ก๊ทธ์ธ์ ํ๊ฒ ๋๋ฉดres.cookie("token", token, { httpOnly: true })๋ฅผ ๋ณด๋ธ๋ค.
๊ทธ๋ฌ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ Cookie๋ฅผ ์ ์ฅํ๋๋ฐ, ์ด Cookie๋
document.cookie์์๋ ๋ณด์ด์ง ์๋๋ค. ์ฆ JavaScript๊ฐ ์ ๊ทผ ์์ฒด๋ฅผ ๋ชปํ๊ธฐ ๋๋ฌธ์ ํ ํฐ์ ํ์ทจํ๊ธฐ ํจ์ฌ ์ด๋ ต๋ค.
๋ฌผ๋ก HttpOnly Cookie๋ ๋ฌด์ ์ ์๋๋ค.
Cookie๋ ์๋์ผ๋ก ์ ์ก๋๊ธฐ ๋๋ฌธ์ CSRF(Cross-Site Request Forgery) ๊ณต๊ฒฉ์ ๋ ธ์ถ๋ ์ ์๋ค.
๊ทธ๋์ ์ค์ ์๋น์ค์์๋ ๋ณดํต ๋ค์๊ณผ ์๋์ ๊ฐ์ ์ต์ ์ ํจ๊ป ์ฌ์ฉํ๋ค.
res.cookie("token", token, { httpOnly: true, secure: true, sameSite: "Strict" })- httpOnly: JavaScript์์ ์ ๊ทผ ๋ถ๊ฐ
- secure: HTTPS์์๋ง ์ ์ก
- sameSite: ๋ค๋ฅธ ์ฌ์ดํธ์์ ์๋ ์ ์ก ์ ํ(CSRF ์ํ)
๋ธ๋ผ์ฐ์ ๋ ex) localhost:3000 ๋ก ์์ฒญ์ ๋ณด๋ด๊ฒ ๋๋ฉด, Cookie๋ฅผ ์๋์ผ๋ก ๊ฐ์ด ๋ณด๋ด๊ฒ ๋๋ค.
๊ทธ๋์ ์ด์ ์ ์ค๋ช ํ
axios.defaults.withCredentials = true๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
์ด ์ต์ ์ ์ผ๋ฉด Cookie, JWT ๊ฐ ์๋์ผ๋ก ํจ๊ป ์ ์ก๋๋ค.
๊ฒฐ๊ตญ ๋ ์์ฒญ๋๋ง๋ค ๋น๋ฒํ ๋ฃ์๋
headers: { Authorization: ... }๋ฅผ ์ง์ ๋ฃ์ง ์์๋ ๋๋ค.
'๐ Node.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Node.js] NestJS ๊ตฌ์กฐ ์ดํดํ๊ธฐ (0) 2026.08.17 [Node.js] NestJS๋? (0) 2026.08.17 cloudflare R2 ์ฐ๋ (1) 2026.04.07 [Node.js] Express๋? (์ ์ ๋ฐ ์ฌ์ฉ๋ฒ) (0) 2024.11.07 [Node.js] Node.js์ ์ ์์ ํน์ง (4) 2024.10.30