프론트엔드 설정
Fetch API
api.js
// 쿠키를 포함해서 요청 보내기
fetch('https://api.example.com/login', {
method: 'POST',
credentials: 'include', // 중요!
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password }),
});Axios
api.js
import axios from 'axios';
// 전역 설정
axios.defaults.withCredentials = true;
// 또는 개별 요청에서
axios.post('https://api.example.com/login', data, {
withCredentials: true // 중요!
});백엔드 설정
Python FastAPI
main.py
from fastapi import FastAPI, Response
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["https://your-frontend.com"], # * 사용 불가!
allow_credentials=True, # 중요!
allow_methods=["*"],
allow_headers=["*"],
)
@app.post("/login")
async def login(response: Response):
# 쿠키 설정
response.set_cookie(
key="session",
value="token-value",
httponly=True,
secure=True, # HTTPS 필수
samesite="none", # 크로스 사이트 허용
max_age=3600 * 24 * 7 # 7일
)
return {"message": "로그인 성공"}Node.js Express
server.js
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({
origin: 'https://your-frontend.com',
credentials: true // 중요!
}));
app.post('/login', (req, res) => {
res.cookie('session', 'token-value', {
httpOnly: true,
secure: true,
sameSite: 'none',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7일
});
res.json({ message: '로그인 성공' });
});HTTPS 필수!
SameSite=None은 Secure=True와 함께 사용해야 합니다.
즉, HTTPS 환경에서만 동작합니다.
개발 중에는 localhost가 예외적으로 허용됩니다.
절대 하지 마세요!
allow_origins=["*"]와allow_credentials=True를 함께 사용- 민감한 토큰을 localStorage에 저장
- httpOnly 없이 세션 쿠키 설정
디버깅 방법
- 브라우저 개발자 도구(F12) → Application → Cookies 확인
- Network 탭에서 요청 헤더에 Cookie가 포함되는지 확인
- 응답 헤더에 Set-Cookie가 있는지 확인
- Console에 CORS 관련 에러가 없는지 확인