[TIL] JWT 저장방식 HttpOnly Cookies VS LocalStorage

2025-02-17 TIL

📝 TIL (Today I Learned)
🔗 원본 이슈: #18
📅 작성일: 2025-02-17
🔄 최종 수정: 2025년 02월 17일


🍀 새롭게 배운 것

  • JWT 저장 방식
    • HttpOnly Cookies VS LocalStorage

🍎 오늘의 문제 상황

1. JWT를 HttpOnly Cookies 방식으로 저장하려고 했지만 CORS 문제로 계속 실패했다.

  • 📌 원인 분석
    • 크롬의 Thrid-party Cookie 제한
      • 백엔드에서 배포한 도메인(banana-flask-app.onrender.com)과 프론트엔드에서 배포한 도메인(banana-project01.github.io)이 달라 쿠키가 전달이 차단되었다.
      • 해결 방법
        • 같은 도메인을 운영하거나, JWT를 localStorage에 저장해 Authorization 헤더에 포함하는 방법이 있다.
  • ✅ 해결 방법
    • 쿠키 대신 JWT를 localStorage에 저장하고, API 요청 시 Authorization 헤더에 추가하는 방식으로 변경했다.
      • JWT 저장 (로그인 성공 시)
        • localStorage.setItem("access_token", jwt_token);
      • API 요청 시 Authorization 헤더 추가

2. 로그인 후 JWT가 포함된 URL로 리디렉션되지만, 토큰이 localStorage에 저장되지 않음

  • 📌 원인 분석
    • storeTokenFromURL() 함수가 실행되지 않음.
    • window.location.href = "?token=..."으로 이동하면 JavaScript 실행 흐름이 초기화됨.
    • DOMContentLoaded 이벤트가 실행되기 전에 storeTokenFromURL()을 호출해야 함.
  • ✅ 해결 방법
    • 페이지 로드 시 storeTokenFromURL() 강제 실행
      •  document.addEventListener("DOMContentLoaded", function () {
                console.log("🔥 페이지 로드 완료, storeTokenFromURL() 실행 대기...");
                storeTokenFromURL();
                fetchUserInfo();
            });
        
    • 토큰을 URL에서 추출하고 localStorage에 저장

3. 로컬 개발 환경에서 로그인 후 토큰이 저장되지 않았다.

  • 📌 원인 분석
    • 로컬 개발 환경 (http://127.0.0.1:5501)에서 로그인 후 localStorage.getItem(“access_token”)이 null로 반환됨.
    • 프론트엔드와 백엔드의 도메인이 다르면 window.location.href를 통한 리디렉션이 정상적으로 작동하지 않을 수 있음.
    • 127.0.0.1에서 개발 중인데, 배포된 banana-project01.github.io 도메인으로 리디렉트되면서 localStorage가 초기화됨.
  • ✅ 해결 방법
    • Postman에서 Bearer 토큰 인증 테스트
      • Authorization 헤더에 Bearer 을 수동으로 입력하여 API 호출.

4. 다른 사용자가 로그인 시 500 에러가 발생하였다.

  • 다른 사용자가 로그인하면 KeyError: ‘id’ 또는 IntegrityError: duplicate key value violates unique constraint “user_email_key” 오류 발생.
  • 📌 원인 분석
    • 카카오 & 구글 OAuth 사용자 정보 구조가 다름 → user_info[“id”]가 없을 가능성 있음.
    • 이메일이 없는 경우 기본값 “No Email”을 사용 → 동일한 이메일이 중복되면서 Unique Constraint 오류 발생.
  • ✅ 해결 방법
    • 소셜 로그인 시 get() 사용하여 안전하게 값 가져오기
    • 이메일이 중복되지 않도록 수정

🦄 느낀 점

  • 소셜 로그인을 다 구현했다고 생각했지만, 배포이후 과정에서 복잡한 부분이 많았다.
  • 아직 더 신경 쓰고, 고려해야할 점이 많지만 이 부분을 배우면서 추후에 서비스를 더욱 디벨롭하면 좋을 것같다.
    • 로그인 후 로그인 버튼이 프로필 아이콘으로 바뀌도록 하였지만, 프로필 아이콘 변경에 딜레이가 있다.
    • 마이페이지 구현을 해봐도 좋을 것같다.
  • 또한 사람들이 한꺼번에 서버를 사용하게 되면 어떻게 될지도 테스트해보고 싶다.
    • 무료 버전의 render를 사용해서 서버 운영에서 약간 불안정한 점이 있었다. (cold start)
    • 다음엔 AWS로 구현해보고 싶다.

🐬 참고 자료

  • [