반응형

1. 증상
- 발생 시점: 외부 장비 조회 API를 호출한 뒤 페이지 새로고침 시
- 증상: 로그인 정보(
loginInfo)가 사라지고 로그인 페이지로 리다이렉트됨 - 특이사항: 장비 조회 직후에는 화면상
loginInfo가 유지되어 보이고, 새로고침 후에만 세션이 없는 것처럼 동작
2. 원인
2.1 요약
외부 API(프록시 경유) 응답에 포함된 Set-Cookie 헤더가 우리 도메인으로 전달되면서, 기존 세션 쿠키가 덮어쓰이거나 제거됨.
2.2 상세
- 프론트에서 장비 조회 시 같은 오리진으로 요청을 보냄
- 예:
https://our-domain.com/api/external/... - 이 요청은 Nginx(Vite 프록시 등)를 통해 외부 API로 프록시됨
- 예:
https://api.example-external.go.kr/...
- 예:
- 외부 API가 응답 시
Set-Cookie헤더를 포함할 수 있음- 해당 API가 세션/추적용 쿠키를 설정하는 경우
- 프록시가 응답을 그대로 클라이언트에 전달하면, 브라우저 입장에서는
- 응답이 우리 도메인(our-domain.com)에서 온 것으로 인식하고
Set-Cookie를 우리 도메인에 적용함
- 그 결과
- 우리 앱의 세션 쿠키(예:
ADMIN_SESSION_ID)가 - 외부 API에서 내려준 쿠키로 덮어쓰이거나 영향받아
- 이후 요청에서 세션이 유효하지 않게 됨
- 우리 앱의 세션 쿠키(예:
- 새로고침 시
- 앱이
/auth/.../loginInfo등 세션 기반 API를 다시 호출하고 - 이미 세션 쿠키가 바뀐 상태이므로 서버가 세션을 찾지 못해
loginInfo가 비어 있는 것처럼 보이고 로그인 페이지로 보내짐
- 앱이
2.3 왜 장비 조회 직후에는 괜찮아 보였나?
- 직후에는 메모리 상의 Redux 상태에 이전에 불러온
loginInfo가 남아 있어서 화면에는 그대로 보임 - 실제로는 쿠키는 이미 변경된 상태이고, 새로고침으로 앱이 다시 로드되면서 서버에 세션 요청을 보낼 때 문제가 드러남
3. 해결 방법
3.1 프록시에서 외부 API 응답의 Set-Cookie 제거 (권장)
외부 API 응답을 클라이언트로 넘기기 전에 Set-Cookie 헤더를 제거합니다.
우리 앱은 해당 외부 API의 쿠키가 필요하지 않으며, 제거해도 장비 조회 기능에는 영향이 없습니다.
(1) Vite 개발/프리뷰 환경
vite.config.ts의 해당 프록시에 configure를 추가합니다.
// 예시: /api/external/ 로 들어오는 요청을 외부 API로 프록시하는 경우
"/api/external/": {
target: "https://api.example-external.go.kr/",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/external/, ""),
secure: true,
ws: true,
configure: (proxy) => {
proxy.on("proxyRes", (proxyRes) => {
delete proxyRes.headers["set-cookie"];
delete proxyRes.headers["set-cookie2"];
});
},
},
- 의미: 외부 API 응답의
Set-Cookie를 제거한 뒤 클라이언트에 전달 - 적용 범위:
npm run dev,npm run preview등 Vite가 프록시를 처리하는 환경
(2) Nginx (운영/스테이징)
해당 location 블록 안에 다음 한 줄을 추가합니다.
location /api/external/ {
proxy_ssl_server_name on;
proxy_pass https://api.example-external.go.kr/;
proxy_set_header Host api.example-external.go.kr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# 외부 API 응답의 Set-Cookie를 클라이언트에 전달하지 않음
proxy_hide_header Set-Cookie;
}
- 의미: upstream(외부 API) 응답의
Set-Cookie를 숨겨서 클라이언트로 내려보내지 않음 - 적용 후:
nginx -t로 문법 확인 후nginx -s reload로 반영
3.2 프론트엔드: 외부 API 요청에 쿠키 미전송 (보조)
해당 외부 API 호출 시 쿠키를 보내지 않도록 설정하면,
우리 세션 쿠키가 외부로 나가지 않고, 응답으로 받는 쿠키에 의한 덮어쓰기 가능성도 줄일 수 있습니다.
// 예: axios 사용 시
const response = await axios.get(requestUrl, {
params: requestParams,
withCredentials: false, // 쿠키 미전송
});
- 주의:
withCredentials: false만으로는 응답의 Set-Cookie가 브라우저에 적용되는 것을 막지 못할 수 있음.
따라서 3.1(프록시에서 Set-Cookie 제거) 를 함께 적용하는 것이 안전합니다.
4. 확인 방법
- 로그인 후 장비 조회(외부 API 호출) 실행
- 새로고침(F5 또는 페이지 리로드)
- 기대 결과: 로그인 상태 유지,
loginInfo정상 노출 - (선택) 브라우저 개발자 도구 → Application → Cookies 에서
우리 도메인의 세션 쿠키(예:ADMIN_SESSION_ID)가
장비 조회·새로고침 후에도 그대로 있는지 확인
5. 참고 사항
- 외부 API 쿠키: 장비 조회용 공개 API는 인증이 필요 없으므로, 응답의
Set-Cookie는 해당 서비스의 세션/추적용일 가능성이 큼. 우리 쪽에서 제거해도 기능상 문제 없음. - 운영 반영: Nginx 등 실제 서비스 프록시에서도 동일하게
proxy_hide_header Set-Cookie적용 필요. - 다른 외부 API: 비슷하게 같은 오리진으로 프록시하는 외부 API가 있다면, 동일한 방식으로
Set-Cookie제거를 검토하는 것이 좋음.
반응형
'TroubleShooting' 카테고리의 다른 글
| 음성인식 모바일 호환성 트러블슈팅 (0) | 2026.03.06 |
|---|---|
| 사용자 이탈 방지 로직(뒤로가기/새로고침 차단) 최적화 (0) | 2026.01.14 |
| 리액트 API 호출 구조 리팩토링: useEffect에서 React Query로의 전환 (0) | 2026.01.07 |
| Jenkins-SonarQube 연동 에러: "The ‘report’ parameter is missing" (HTTP 400) (0) | 2026.01.06 |