
Vibe Guardian
React 앱에서 JWT를 localStorage에 저장하면 안 되는 이유
ARTICLE CONTENT
1. React 앱에서 인증 정보를 저장할 때 자주 생기는 고민
1) React인증에서 가장 많이 나오는 질문
React로 로그인 기능을 만들다 보면 React인증 정보를 어디에 저장할지 가장 먼저 고민하게 됩니다. 특히 JWT localStorage 방식은 구현이 간단해서 많이 선택되지만, 동시에 토큰보안 관점에서 계속 논의가 되는 방식이기도 합니다. 개발 초기에는 편리해 보여도, 서비스가 커질수록 예상하지 못한 보안 이슈가 드러나는 경우가 많습니다. 그래서 많은 개발자들이 “이 방식이 정말 괜찮을까?”를 검색하게 됩니다. 이 글에서는 JWT를 localStorage에 저장할 때 왜 주의해야 하는지, 그리고 어떤 상황에서 대체 방식을 고려해야 하는지 정리해보겠습니다.
2) 왜 localStorage가 먼저 떠오르는가
JWT localStorage 방식은 브라우저에서 값을 읽고 쓰기 쉬워서 빠르게 적용할 수 있습니다. 새로고침 후에도 토큰이 남아 있어 사용자 경험도 나쁘지 않다는 장점이 있습니다. 하지만 편리함이 곧 안전함을 의미하지는 않습니다. 특히 XSS취약점이 존재할 경우, localStorage에 저장된 값은 비교적 쉽게 노출될 수 있어 주의가 필요합니다.
3) 이 글에서 확인할 내용
이 글에서는 React 앱에서 JWT를 localStorage에 저장하면 어떤 위험이 있는지, 토큰보안을 위해 어떤 점을 살펴야 하는지, 그리고 기본적인 점검 과정에서 무엇을 확인하면 좋은지 설명합니다. 단순히 “쓰면 안 된다”로 끝내기보다 실제 서비스에서 어떤 상황이 문제가 되는지 중심으로 살펴보겠습니다.
2. JWT localStorage 방식이 많이 쓰이는 이유
1) 구현이 쉽고 직관적이다
JWT localStorage는 로그인 성공 후 토큰을 저장하고, 이후 요청에서 꺼내 쓰는 구조라 이해가 쉽습니다. React인증 로직을 빠르게 만들 때 자주 사용되는 이유도 여기에 있습니다. 상태 관리 라이브러리와 연결하기도 쉬워 초반 개발 속도는 확실히 빠른 편입니다.
2) 새로고침 이후에도 상태를 유지할 수 있다
메모리 기반 저장 방식과 비교하면, localStorage는 브라우저를 닫지 않는 한 값이 유지됩니다. 사용자는 다시 로그인하지 않아도 되는 것처럼 느낄 수 있어 편리합니다. 다만 이 점은 동시에 공격자가 접근할 수 있는 시간도 길어진다는 뜻이 될 수 있습니다.
3) 서버와의 구조가 단순해진다
쿠키 기반 세션보다 JWT localStorage는 클라이언트가 토큰을 직접 관리하는 구조라 서버 로직이 단순해지는 경우가 많습니다. 하지만 토큰보안이 서버 밖으로 일부 이동하는 셈이므로, 프런트엔드의 보안 관리 책임이 더 커집니다. 이 점을 간과하면 나중에 문제가 생길 수 있습니다.
3. localStorage가 위험하다고 말하는 핵심 이유
1) XSS취약점에 비교적 취약하다
localStorage는 JavaScript로 쉽게 읽을 수 있습니다. 이 말은 반대로 말하면, XSS취약점이 발생했을 때 악성 스크립트가 저장된 토큰에 접근할 가능성이 있다는 뜻입니다. 한 번 스크립트가 실행되면 사용자의 JWT를 탈취해 다른 기기에서 재사용하는 시나리오가 가능해집니다. 그래서 토큰보안 측면에서 가장 자주 지적되는 지점이 바로 이 부분입니다.
2) 브라우저에서 자동 보호가 되지 않는다
쿠키는 HttpOnly, Secure, SameSite 같은 옵션으로 어느 정도 통제를 할 수 있지만, localStorage는 이런 보호 장치가 기본적으로 없습니다. React인증에서 편리함 때문에 선택하는 경우가 많지만, 보안 통제가 약하다는 점은 분명한 단점입니다. 즉, “브라우저에 저장한다”는 사실 자체보다 “어떤 방식으로 보호되는가”가 중요합니다.
3) 탈취되면 사용자가 알아채기 어렵다
JWT localStorage에 저장된 토큰이 외부로 유출되어도 사용자는 바로 인지하지 못하는 경우가 많습니다. 보통은 로그아웃이 되거나, 이상한 접근이 발생한 뒤에야 문제가 드러납니다. 특히 짧은 기간에 여러 API 요청이 오가는 서비스라면 피해 범위가 더 커질 수 있습니다.
4. XSS취약점이 실제로 문제되는 이유
1) 단순 입력창도 공격 지점이 될 수 있다
XSS취약점은 특별히 복잡한 화면에서만 생기는 것이 아닙니다. 댓글, 검색어, 프로필 소개, 관리자 메모처럼 사용자가 입력하는 값이 화면에 다시 노출되는 곳이면 언제든 위험 요소가 될 수 있습니다. React라고 해서 무조건 안전한 것도 아니며, dangerouslySetInnerHTML 같은 기능을 사용할 때는 특히 주의가 필요합니다.
2) 외부 스크립트가 들어오는 환경도 점검해야 한다
광고 스크립트, 분석 도구, 위젯, 서드파티 라이브러리 등이 많아질수록 XSS취약점 가능성은 커질 수 있습니다. 직접 작성한 코드만 보는 것이 아니라 외부에서 불러오는 스크립트까지 함께 살펴야 토큰보안을 더 현실적으로 관리할 수 있습니다.
3) 보안 점검은 기능 구현 뒤에 따로 하면 늦을 수 있다
많은 팀이 로그인 기능을 먼저 만들고, 이후에 문제가 생기면 점검하는 방식으로 진행합니다. 하지만 React인증 구조와 저장 방식은 초기에 결정되는 경우가 많아, 나중에 바꾸기가 쉽지 않습니다. 그래서 처음부터 localStorage 사용 범위와 위험 요소를 확인하는 습관이 중요합니다.
5. 토큰보안을 위해 함께 살펴봐야 할 항목들
1) HTTPS와 보안 헤더 확인
JWT localStorage 자체의 위험만 보는 것보다, 사이트 전반의 기본 보안 상태를 함께 확인하는 것이 좋습니다. HTTPS 적용 여부, 보안 헤더 설정, 인증서 상태는 기본 중의 기본입니다. 이런 요소가 정리되어 있어야 React인증 과정에서 데이터가 불필요하게 노출되는 위험을 줄일 수 있습니다.
2) 쿠키와 CORS 설정도 함께 검토
API를 분리해서 운영하는 경우 CORS 설정이 느슨하면 예상치 못한 접근 문제가 생길 수 있습니다. 또한 쿠키를 사용하는 방식으로 전환할 가능성이 있다면, SameSite나 Secure 설정도 고려해야 합니다. 토큰보안은 하나의 저장소만 보아서는 완성되지 않는 경우가 많습니다.
3) 민감 정보 노출 여부 점검
.env 파일, 소스코드, API 키 같은 정보가 실수로 노출되면 JWT localStorage보다 더 큰 문제가 될 수 있습니다. 브라우저에서 실제로 어떤 정보가 열람 가능한지 함께 보는 것이 중요합니다. 보안 점검 도구를 활용하면 이런 기본 항목을 빠르게 확인하는 데 도움이 됩니다.
6. React 앱에서 더 현실적인 저장 방식은 무엇인가
1) 무조건 localStorage를 쓰지 않는 쪽을 검토
모든 서비스에서 localStorage가 절대 금지인 것은 아닙니다. 다만 민감도가 높은 서비스나 계정 보호가 중요한 서비스라면 다른 방식을 우선 검토하는 편이 좋습니다. 예를 들어 짧은 수명의 액세스 토큰과 별도 갱신 전략을 함께 설계하는 경우가 많습니다.
2) 쿠키 기반 인증이 적합한 경우
HttpOnly 쿠키를 활용하면 JavaScript에서 토큰을 직접 읽지 못하므로 XSS취약점에 의한 탈취 위험을 줄이는 데 도움이 됩니다. 대신 CSRF와 같은 다른 보안 요소를 함께 고려해야 합니다. 즉, 한쪽 위험을 줄이면 다른 쪽을 관리해야 하는 구조라고 이해하면 됩니다.
3) 서비스 성격에 따라 기준이 달라진다
사내 도구, 개인 프로젝트, 공개 서비스, 금융/결제 성격의 서비스는 요구 수준이 다릅니다. React인증을 단순히 구현하는 것과 토큰보안을 운영 수준에서 관리하는 것은 다른 문제입니다. 그래서 저장 방식은 “무엇이 더 편한가”보다 “내 서비스에 어떤 리스크가 더 큰가”를 기준으로 정하는 것이 좋습니다.
7. 정리: 어떤 상황에서 이 문제를 꼭 고려해야 할까
1) 로그인 상태 유지보다 보안이 더 중요한 경우
사용자 정보, 결제 정보, 관리자 기능처럼 민감한 데이터를 다루는 서비스라면 JWT localStorage 저장은 더 신중하게 봐야 합니다. 특히 XSS취약점 가능성이 있는 화면이 많거나 외부 스크립트가 자주 추가되는 환경이라면 토큰보안을 우선해 구조를 다시 살펴볼 필요가 있습니다.
2) 직접 전화로 확인하는 방식과의 차이
보안 이슈가 생겼을 때 직접 전화로 문의하면 현재 증상이나 운영 상황을 빠르게 공유할 수 있습니다. 반면 보안 점검 도구를 활용하면 URL만 입력해도 HTTPS, 헤더, 노출 위험, 브라우저 기반 취약점 같은 기본 상태를 먼저 확인할 수 있습니다. 즉, 전화 상담은 구체적인 상황 설명에 강하고, 자동 점검은 초기 확인과 반복 점검에 강한 편입니다.
3) 결론적으로 필요한 판단
React인증을 설계할 때 JWT localStorage는 편리하지만, XSS취약점과 토큰보안 측면에서 분명한 한계가 있습니다. 따라서 단순히 “많이 쓰인다”는 이유만으로 선택하기보다, 서비스의 민감도와 구조를 함께 고려해야 합니다. 기본 보안 상태를 먼저 점검하고 싶거나, 현재 방식이 안전한지 빠르게 확인하고 싶다면 이런 도구를 활용해보는 것도 도움이 됩니다.
다른 콘텐츠도 함께 보세요
같은 주제에서 이어서 읽기 좋은 글들을 랜덤으로 추천합니다.
혼자 서비스 운영하면서 보안 사고 나면 감당이 되나요
혼자 서비스 운영할 때 보안이 더 부담스러운 이유 1) 작은 서비스일수록 보안 점검이 뒤로 밀리기 쉽습니다 혼자 서비스를 운영하다 보면 기능 개발, 배포, 고객 문의 대응, 운영 관리까지 한 사람이 모두 챙겨야 합니다. 이 과정에서 보안은 중요하다고…
개인정보 유출 사고 나면 과징금이 얼마나 나오나 — 규모별 기준
개인정보 유출 사고와 과징금이 함께 검색되는 이유 1) 사고가 나면 가장 먼저 떠오르는 질문 개인정보 유출 사고가 발생하면 가장 먼저 걱정되는 것은 피해 규모와 대응 절차입니다. 그런데 실제로는 “얼마나 벌금을 내게 되는지”, “어떤 기준으로 제재가…
CORS 제대로 설정하기 — 와일드카드(*) 대신 허용 도메인 명시하는 방법
CORS가 왜 자주 문제로 보일까 1) 브라우저가 요청을 막는 이유 웹 개발을 하다 보면 화면은 정상인데 API 호출만 실패하는 상황을 자주 만나게 됩니다. 이때 가장 먼저 떠올리는 개념이 바로 CORS설정입니다. CORS는 서로 다른 출처에서 보내는…
DNS 스푸핑이란 — 내 도메인으로 접속했는데 가짜 사이트가 뜨는 이유
DNS 스푸핑이란 무엇인가 DNS 스푸핑은 사용자가 입력한 도메인 주소를 공격자가 조작해, 원래 가려던 사이트가 아닌 가짜 사이트로 연결되게 만드는 방식입니다. 흔히 DNS스푸핑이라고도 부르며, 겉으로는 평소처럼 주소를 입력했는데 전혀 다른 화면이 뜨…