인프런 커뮤니티 질문&답변
토큰 관리에 대해 질문을 드리고 싶습니다.
작성
·
26
0
안녕하세요 멘토님, 정말 쉽게 설명해주셔서 수업 잘 듣고 있습니다.
인증 처리하기 부분에 대해서 흐름도를 자세하고 재밌게 설명해주셔서 덕분에 이해하기 수월했습니다. 다만 현재 토큰들을 localStorage에 저장하고 이 값을 zustand로 관리하고 있는 것 같은데 사실 토큰을 storage에 저장하는 방식이 일반적이지는 않은 것 같습니다.
이 부분에 대해서 찾아본 결과 supabase를 이용하기에 쿠키에 저장하는 건 무리인 것 같고,
그렇다면 그나마 토큰을 메모리에 저장하는 방식이 안전할 것 같습니다.
로그인을 진행하면 토큰이 localStorage에 저장되는 형태인데, 이때 만약 storage에 저장하지 않고 메모리에 받게하려면 어떻게 할 수 있을까요 .. ?
또한 사실 토큰 자체를 zustand에서 가지고 있는 것도 괜찮은지 의문입니다.. 전역상태로 들고 있는 것이라서 충분히 탈취위험이 있을 것이라고 생각이 되어서요..
사실 백엔드 서버가 있었다면 쿠키에 저장하는 로직으로 진행했을 거 같은데
만약 이때는 로그인 상태를 어떻게 판별하는지에 대해서도 궁금합니다 !
답변 2
2
안녕하세요 이헨님 이정환입니다.
우선 토큰을 Zustand와 localStorage를 함께 사용해 저장하고 다루는 방식이 일반적이지 않다고 말씀해주셨는데요, 사실 이 방식은 꽤 보편적으로 사용되는 패턴이며, 일반적이지 않다고 보기는 어렵습니다.
대표적으로 Supabase에서도 이러한 방식을 공식 예제에서 소개하고 있으며, 실제로 Supabase의 JavaScript 클라이언트는 기본적으로 localStorage를 사용하도록 설계되어 있습니다. 별도의 설정 없이도 로그인 세션이 localStorage에 자동으로 저장되고 복구되도록 되어 있기 때문에, Supabase 나 Firebase 등의 클라우드 백엔드 서비스를 사용하는 대부분의 프론트엔드 환경에서는 이 구조를 그대로 따릅니다.
또한 메모리에 저장하는 방식이 더 안전하다고 말씀해주셨는데요, 여기서 말하는 "메모리에 저장한다"는 표현은 보통 브라우저의 일시적인 실행 컨텍스트, 즉 런타임 중 유지되는 변수나 상태관리 라이브러리(Zustand, Redux 등)의 상태로 토큰을 관리한다는 의미입니다. 결국 Zustand로 토큰을 저장하는 것도 메모리에 저장하는 방식에 해당됩니다.
추가로 “전역 상태로 보관하는 것은 안전하지 않을 것 같다”라고 말씀해주셨는데요, 혹시 그렇게 생각하신 이유가 있을까요?
Zustand와 같은 상태 관리 라이브러리를 통해 전역 상태로 토큰을 보관하든, 지역 상태나 일반 변수에 보관하든, 모두 런타임 메모리 내에서만 유지되는 정보입니다. 즉, 브라우저가 새로고침되거나 페이지가 종료되면 사라지는 데이터이며, 외부에서 직접 접근하거나 탈취하기는 현실적으로 어렵습니다.
물론 예외적으로, 개발 중에는 Redux DevTools 같은 디버깅 도구나 브라우저 확장 기능 등을 통해 상태가 노출될 가능성도 존재합니다. 하지만 이러한 리스크는 프로덕션 환경에서 디버깅 도구를 비활성화하거나, 민감한 정보를 DevTools에 출력하지 않도록 설정함으로써 충분히 방지할 수 있습니다.
따라서 메모리에만 저장된 전역 상태는 실질적인 보안 취약점으로 보기 어렵습니다. 혹시 걱정하셨던 부분이 이런 개발 환경에서의 노출 가능성일까요? 아니면 다른 관점에서 우려하신 걸까요?
아! 물론 Local Storage에 저장하는 경우, 스크립트 기반 공격(XSS 등)을 통해 토큰이 탈취될 수 있다는 보안상의 우려가 있어서 많은 경우, HTTPOnly 쿠키를 사용하는 방식이 상대적으로 더 안전한 선택이 될 수는 있습니다
다만 React.js는 기본적으로 XSS 공격을 방지하는 설계가 적용되어 있습니다. 예를 들어, JSX로 문자열을 렌더링할 경우 내부적으로 textContent를 사용하기 때문에, 악성 스크립트가 자동으로 실행되지 않습니다. 즉, 개발자가 dangerouslySetInnerHTML을 직접 사용하거나, 외부 입력을 검증 없이 그대로 DOM에 삽입하는 등의 명백한 실수를 하지 않는 한, React 자체만으로도 대부분의 XSS 공격은 방어할 수 있습니다.
또 Supabase처럼 클라이언트 중심의 인증 구조를 사용하는 서비스의 경우, 서버가 존재하지 않기 때문에 HTTPOnly 쿠키를 설정하거나 읽을 수 있는 환경이 아닙니다. 따라서 이 경우에는 로컬 스토리지를 사용하는 방식이 구조적으로 더 적합합니다.
실제로 앞서 말씀드렸듯이 Supabase의 공식 문서나 클라이언트 초기화 예제에서도, 토큰을 localStorage에 저장하고 이를 바탕으로 인증 상태를 유지하는 방식을 사용하고 있습니다.
또한, SPA(Single Page Application) 환경에서는 새로고침 후에도 로그인 상태를 유지하거나 자동 로그인을 구현해야 하는 UX 측면에서, Local Storage가 더 나은 선택지가 되는 경우도 많습니다.
0
안녕하세요, 인프런 AI 인턴입니다. 이헨님.
토큰 관리에 관련하여 질문 주신 점에 감사드립니다. 토큰을 어떻게 저장하고 관리할지가 보안 측면에서 매우 중요한 부분인 만큼, 여러 가지 고려해야 할 사항이 있습니다.
1. 토큰 저장소로서의 메모리와 로컬 스토리지
로컬 스토리지: 클라이언트 쪽에서 가장 쉽게 접근할 수 있는 저장소로, 사용자 세션이 종료되더라도 데이터를 유지할 수 있지만, 보안 취약점이 있습니다. XSS(Cross Site Scripting) 공격에 의해 토큰이 탈취될 위험이 있습니다.
메모리: 메모리에 저장하는 방식은 브라우저가 닫히면 데이터가 사라지기 때문에 보안 측면에서 상대적으로 안전합니다. 하지만 사용자 경험 측면에서는 로그아웃 상태가 될 수 있으므로 지속적인 세션 유지를 위해서는 적절한 로직을 추가로 개발해야 합니다.
2. Zustand와 같은 전역 상태 관리에서의 토큰 저장
Zustand 또는 다른 전역 상태 관리 라이브러리에서 토큰을 보관하는 것은 중요한 정보이기 때문에 매우 주의해야 합니다. 탈취의 위험성을 줄이기 위해서는 필요한 경우에만 상태를 업데이트하고, 민감한 정보를 직접적으로 저장하지 않는 것이 좋습니다.
3. Secure Cookie 사용
대부분의 경우, 인증 정보를 안전하게 보관하기 위해 쿠키를 사용합니다. 쿠키는 서버측에서만 접근 가능한 HttpOnly 속성을 사용하여 XSS 공격에서 보호할 수 있습니다.
특히, 서버가 있다면 인증 쿠키를 사용하여 로그인 상태를 확인하는 것이 유리합니다. 서버는 쿠키에서 정보를 읽어 사용자의 인증 상태를 판별할 수 있습니다.
4. 로그인 상태 판별
JWT: 프론트엔드에서 JWT를 발급받아 인증을 받는 방식도 많이 사용됩니다.
설계에 따라 토큰의 유효성을 인증서버에서 주기적으로 확인하거나, 토큰 자체의 만료 시간을 검증하여 사용자를 인증 상태로 관리할 수 있습니다.서버 기반 세션: 쿠키에 세션 ID를 저장하고, 이 세션 ID를 기반으로 데이터베이스에서 사용자의 로그인 상태를 추적할 수 있습니다.
요약 및 추천
토큰 저장소에 따른 보안 위험을 줄이기 위해 여러 방법론들이 있으니 상황에 맞게 적용하시길 권장합니다. 노출 위험이 있는 프론트엔드보다는, 가능하면 더욱 안전한 서버 측 로직으로 처리를 하는 방향으로 고려해보시면 좋을 것 같습니다.
관련한 더 많은 정보는 다음 게시물들을 참고하실 수 있습니다:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.




