-
[Vue.js] axios.defaults.withCredentials = true๋ ์ ์ฌ์ฉํ๋ ๊ฑธ๊น?๐ Vue.js 2026. 7. 11. 04:52
JWT ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค ๋ณด๋ฉด ์์ฃผ ๋ณด๊ฒ ๋๋ ์ฝ๋๊ฐ ์๋ค.
axios.defaults.withCredentials = true;์ฒ์์๋ "์ฟ ํค๋ฅผ ๋ณด๋ด๊ธฐ ์ํ ์ค์ ์ธ๊ฐ?" ์ ๋๋ก๋ง ์ดํดํ์ง๋ง, ์ค์ ๋ก ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ฉด์ ์ด ์ต์ ์ด ์ ํ์ํ์ง ์ ํํ ์๊ฒ ๋์๋ค.
๐ ๋จผ์ ์์์ผ ํ๋ ๊ฒ
๋์ ํ๋ก์ ํธ์ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- Vue3 : http://localhost:5173
- Node.js(Express) : http://localhost:3000
ํ๋ก ํธ์๋์ ๋ฐฑ์๋์ ํฌํธ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ธ๋ผ์ฐ์ ์ ์ฅ์์๋ ๋ค๋ฅธ Origin(์ถ์ฒ) ์ผ๋ก ์ธ์ํ๋ค.
Origin์ ๋ค์ 3๊ฐ์ง๊ฐ ๋ชจ๋ ๊ฐ์์ผ ํ๋ค.
- ํ๋กํ ์ฝ(http/https)
- ๋๋ฉ์ธ(localhost)
- ํฌํธ(5173, 3000)
์ฆ
http://localhost:5173์์
http://localhost:3000์ผ๋ก ์์ฒญํ๋ ๊ฒ์ Cross Origin ์์ฒญ์ด๋ค.
๐ก ๋ก๊ทธ์ธ์ ์ด๋ป๊ฒ ์ด๋ฃจ์ด์ง๊น?
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ๋ฒํผ์ ๋๋ฅธ๋ค.
Vue โ โผ POST /api/login/auth โ โผ Node ์๋ฒ๋ก๊ทธ์ธ์ด ์ฑ๊ณตํ๋ฉด ์๋ฒ๋ JWT๋ฅผ ์์ฑํ๋ค.
const token = jwt.sign(payload, "my_secret_key", { expiresIn: "1h" });๊ทธ๋ฆฌ๊ณ ๋ธ๋ผ์ฐ์ ์๊ฒ ์ฟ ํค๋ฅผ ์ ์ฅํ๋ผ๊ณ ์๋ตํ๋ค.
res.cookie("token", token, { httpOnly: true });๋ธ๋ผ์ฐ์ ๋ ์๋ต์ ๋ฐ์ ๋ค ์ฟ ํค๋ฅผ ์ ์ฅํ๋ค.
Browser token = eyJhbGciOiJIUzI1Ni...์ฌ๊ธฐ๊น์ง๋ ์ ์์ด๋ค.
๐งจ ๊ทธ๋ฐ๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
๋ก๊ทธ์ธ ํ ๋ฌธ์ ๋ชฉ๋ก์ ๊ฐ์ ธ์จ๋ค๊ณ ๊ฐ์ ํด๋ณด์.
axios.get("http://localhost:3000/api/documents/list")๋๋ถ๋ถ์ ๋น์ฐํ
GET /api/documents/list Cookie: token=eyJ...์ด๋ ๊ฒ ์์ฒญ์ด ๊ฐ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ค.
ํ์ง๋ง ์ค์ ๋ก๋
GET /api/documents/list (์ฟ ํค ์์)์์ ๊ฐ์ด ์ ์ก๋๋ค.
๋ธ๋ผ์ฐ์ ๊ฐ ์ฟ ํค๋ฅผ ์ผ๋ถ๋ฌ ๋นผ๋ฒ๋ฆฌ๋ ๊ฒ์ด๋ค.
๐โ๏ธ ์ ์ฟ ํค๋ฅผ ์ ๋ณด๋ด๋ ๊ฑธ๊น?
๊ฒฐ๊ตญ์ ๋ณด์ ๋๋ฌธ์ด๋ค.
๋ธ๋ผ์ฐ์ ๋ ๋ค๋ฅธ Origin์ผ๋ก ์์ฒญํ ๋ ์ฟ ํค๋ฅผ ์๋์ผ๋ก ๋ณด๋ด์ง ์๋๋ค.
๋ง์ฝ ์๋ฌด ์ฌ์ดํธ๋ ๋ค๋ฅธ ์๋ฒ์ ์ฟ ํค๋ฅผ ๋ง์๋๋ก ๋ณด๋ผ ์ ์๋ค๋ฉด ๋ณด์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋์ ๋ธ๋ผ์ฐ์ ๋
"์ด ์์ฒญ์ ๋ค๋ฅธ Origin์ธ๋ฐ ์ ๋ง ์ฟ ํค๋ฅผ ๊ฐ์ด ๋ณด๋ผ ๊ฑฐ์ผ?"
๋ผ๊ณ ํ ๋ฒ ๋ ํ์ธํ๋ค.
์ด๋ ์ฌ์ฉํ๋ ์ต์ ์ด ๋ฐ๋ก
withCredentials์ด๋ค.
withCredentials๋ฅผ ์ฌ์ฉํ๋ฉด
axios.get( "http://localhost:3000/api/documents/list", { withCredentials: true } )๋ธ๋ผ์ฐ์ ๋ ์ด์
GET /api/documents/list Cookie: token=eyJ...๋ฅผ ํจ๊ป ์ ์กํ๋ค.
Node์์๋
req.cookies.token์ผ๋ก JWT๋ฅผ ์ฝ์ ์ ์๋ค.
axios.defaults.withCredentials = true
ํ์ง๋ง ๋งค๋ฒ
withCredentials: true๋ฅผ ์ ๋ ๊ฒ์ ๋ฒ๊ฑฐ๋กญ๋ค.
๊ทธ๋์ axios์์๋ ๊ธฐ๋ณธ ์ค์ ์ ์ ๊ณตํ๋ค.
axios.defaults.withCredentials = true;์ด ํ ์ค์ ์์ฑํ๋ฉด
axios.get(...) axios.post(...) axios.put(...) axios.patch(...) axios.delete(...)๋ชจ๋ ์์ฒญ์ ์๋์ผ๋ก
withCredentials: true๊ฐ ์ ์ฉ๋๋ค.
์ฆ
axios.get("/api/list");๋ฅผ ์คํํด๋ ๋ด๋ถ์ ์ผ๋ก๋
axios.get("/api/list", { withCredentials: true });์์ ๊ฐ์ด ๋์ผํ๊ฒ ๋์ํ๋ค.
๋ฌผ๋ก ! ์๋ฒ๋ ์ค์ ํด์ผ ํ๋ค.
ํด๋ผ์ด์ธํธ์์ ์ฟ ํค๋ฅผ ๋ณด๋ด๊ฒ ๋ค๊ณ ํด๋ ์๋ฒ๊ฐ ํ์ฉํ์ง ์์ผ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ์ฟ ํค๋ฅผ ๋ณด๋ด์ง ์๋๋ค.
๊ทธ๋ฌ๊ธฐ์ Express์์๋ CORS ์ค์ ์
app.use(cors({ origin: "http://localhost:5173", credentials: true }));๋ฅผ ๋ฐ๋์ ์ถ๊ฐํด์ผ ํ๋ค.
์ฌ๊ธฐ์
credentials: true๋
"์ด Origin์์ ์ฟ ํค๋ฅผ ํฌํจํ ์์ฒญ์ ํ์ฉํ๋ค."
๋ผ๋ ์๋ฏธ์ด๋ค.
๐ ์ ์ฒด ๋ก๊ทธ์ธ ํ๋ฆ
์ฌ์ฉ์ ๋ก๊ทธ์ธ โ โผ Vue (axios.post) โ โผ Node ๋ก๊ทธ์ธ ์ฒ๋ฆฌ โ โผ JWT ์์ฑ โ โผ res.cookie("token", token) โ โผ ๋ธ๋ผ์ฐ์ ์ ์ฟ ํค ์ ์ฅ โ โผ axios ์์ฒญ ๋ฐ์ โ โผ axios.defaults.withCredentials = true โ โผ ๋ธ๋ผ์ฐ์ ๊ฐ Cookie๋ฅผ ํจ๊ป ์ ์ก โ โผ Node req.cookies.token โ โผ jwt.verify() โ โผ ๋ก๊ทธ์ธ ์ฌ์ฉ์ ํ์ธ โ โผ API ์คํ์ต์ข ์ ๋ฆฌ
axios.defaults.withCredentials = true๋ JWT๋ฅผ ์์ฑํ๋ ์ฝ๋๋ ์๋๊ณ , ์ฟ ํค๋ฅผ ์ ์ฅํ๋ ์ฝ๋๋ ์๋๋ค.
์ด ์ต์ ์ ์ญํ ์ ๊ทธ์ ๋ธ๋ผ์ฐ์ ์ ์ ์ฅ๋์ด ์๋ ์ฟ ํค๋ฅผ ์ดํ์ ๋ชจ๋ Axios ์์ฒญ์ ํจ๊ป ์ ์กํ๋๋ก ๋ธ๋ผ์ฐ์ ์ ์๋ ค์ฃผ๋ ๊ฒ์ด๋ค.
JWT๋ฅผ HttpOnly ์ฟ ํค ๋ฐฉ์์ผ๋ก ๊ด๋ฆฌํ๋ ํ๋ก์ ํธ์์๋ ๊ฑฐ์ ํ์์ ์ผ๋ก ์ฌ์ฉํ๋ ์ค์ ์ด๋ฉฐ, ์๋ฒ์ cors({ credentials: true }) ์ค์ ๊ณผ ํจ๊ป ์ฌ์ฉํด์ผ ์ ์์ ์ผ๋ก ์ธ์ฆ์ด ๋์ํ๋ค.
์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ๊ตฌํํ๋ฉด์ ์ง์ ๋ก๊ทธ์ธ, ์๋ก๊ณ ์นจ, ์ธ์ฆ ํ์ธ ๊ณผ์ ์ ๋๋ฒ๊น ํด ๋ณด๋ ๋จ์ํ "์ธ์์ ์ฐ๋ ์ต์ "์ด ์๋๋ผ ๋ธ๋ผ์ฐ์ ์ ๋ณด์ ์ ์ฑ ๊ณผ ์ฟ ํค ์ ์ก ๋ฐฉ์์ ์ดํดํ๋ ๋ฐ ์ค์ํ ์ค์ ์ด๋ผ๋ ๊ฒ์ ์๊ฒ ๋์๋ค.
'๐ Vue.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Vue.js] ๋ผ์ดํ์ฌ์ดํด ํ (Lifecycle Hooks) (0) 2025.04.16 [Vue.js] Props์ Emits (1) 2024.12.05 [Vue.js] ๋ฐ์์ฑ(Reactivity) ์์คํ (0) 2024.12.04 [Vue.js] ํ ํ๋ฆฟ ๋ฌธ๋ฒ ๋ฐ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ (4) 2024.12.02 [Vue.js] ์ปดํฌ๋ํธ ๊ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ (2) 2024.10.16