[TYPESCRIPT] 운영 기준 클라이언트 토큰 저장 전략: localStorage, cookie, Secure Storage 선택 기준

앞선 글에서는 access token과 refresh token의 수명과 회전 주기를 어떻게 설계해야 하는지를 다뤘습니다. 서버 쪽 설계가 정리되면, 자연스럽게 다음 질문으로 이어집니다.

 

“토큰은 클라이언트에서 어디에 저장해야 할까?” “localStorage에 두면 위험하다고 하는데, cookie는 정말 안전할까?” “웹과 모바일에서 전략을 다르게 가져가야 할까?”

 

토큰 저장 위치는 보안 사고와 직결되는 영역이지만, 실무에서는 종종 “편해서”, “예제 코드가 그래서”라는 이유로 결정됩니다. 이 선택이 잘못되면, 서버를 아무리 잘 설계해도 전체 보안 수준이 무너질 수 있습니다.

 

다음을 실무 기준으로 정리합니다.

  • 클라이언트 토큰 저장의 기본 전제와 위협 모델
  • localStorage, cookie, Secure Storage의 특성과 차이
  • 웹과 모바일에서 권장되는 현실적인 선택지
  • 운영에서 자주 발생하는 실수와 그 이유

 

개념/배경 설명: 토큰 저장은 왜 이렇게 민감한가

토큰은 곧 “로그인 상태 그 자체”입니다. 특히 refresh token은 장기간 유효하기 때문에, 한 번 유출되면 공격자가 지속적으로 access token을 발급받을 수 있습니다.

 

클라이언트 저장 전략을 논의할 때 반드시 고려해야 할 위협은 다음입니다.

  • XSS 공격: 자바스크립트를 통한 토큰 탈취
  • CSRF 공격: 사용자의 의도와 무관한 요청 전송
  • 디바이스 분실 또는 탈취
  • 디버그 빌드, 로그, 스크린샷을 통한 정보 노출

 

중요한 점은 “완벽하게 안전한 저장소는 없다”는 사실입니다. 각 저장 방식은 막을 수 있는 공격과 취약한 공격이 다릅니다. 따라서 선택 기준은 “무조건 안전한가”가 아니라, “어떤 위험을 감수하고, 어떤 위험을 줄일 것인가”가 됩니다.

 

 

설계 1: localStorage 기반 토큰 저장

localStorage는 구현이 단순하고 직관적입니다. 프론트엔드에서 가장 쉽게 접근할 수 있기 때문에, 초기 프로젝트에서 가장 많이 사용됩니다.

 

특징

  • 자바스크립트로 자유롭게 읽고 쓸 수 있음
  • 페이지 새로고침, 브라우저 재시작 후에도 유지
  • 도메인 단위로 저장

 

문제점

  • XSS 공격에 매우 취약
  • 토큰이 노출되면 서버가 이를 구분할 방법이 없음
  • 보안 사고 시 “왜 유출됐는지” 추적이 어려움

 

실무에서 localStorage는 access token조차도 권장되지 않는 경우가 많습니다. 특히 refresh token을 localStorage에 저장하는 구조는, 토큰 탈취 시 장기 악용으로 이어질 가능성이 큽니다.

 

실무 포인트 정리

  • localStorage는 XSS에 취약하다는 전제를 반드시 인지한다
  • refresh token 저장소로는 부적합하다
  • 보안 요구사항이 낮은 내부 도구가 아니라면 신중해야 한다

 

설계 2: HttpOnly Cookie 기반 토큰 저장

보안 관점에서 웹 서비스에서 가장 많이 권장되는 방식은 HttpOnly, Secure 옵션이 적용된 cookie입니다.

 

특징

  • 자바스크립트에서 접근 불가(HttpOnly)
  • HTTPS 환경에서만 전송(Secure)
  • 브라우저가 자동으로 요청에 포함

 

이 방식의 가장 큰 장점은 XSS에 대한 방어입니다. 스크립트로 토큰을 읽을 수 없기 때문에, localStorage 대비 탈취 난이도가 크게 올라갑니다.

 

주의할 점

  • CSRF 공격에 대한 추가 방어가 필요
  • SameSite 정책을 명확히 설정해야 함
  • 클라이언트에서 토큰을 직접 다루기 어렵다

 

실무에서는 refresh token을 HttpOnly cookie에 저장하고, access token은 메모리 변수에만 보관하는 구조가 자주 사용됩니다. 이렇게 하면 XSS와 CSRF를 모두 고려한 균형 잡힌 설계가 됩니다.

 

실무 포인트 정리

  • 웹 서비스에서는 refresh token을 HttpOnly cookie에 저장하는 것이 기본 선택지다
  • SameSite, Secure 설정은 환경별로 명확히 관리한다
  • CSRF 토큰 또는 Double Submit 전략을 함께 고려한다

 

설계 3: 모바일 환경의 Secure Storage

모바일 앱에서는 브라우저 cookie를 그대로 사용할 수 없습니다. 대신 OS가 제공하는 Secure Storage(Keychain, Keystore 등)를 사용합니다.

 

특징

  • OS 수준에서 암호화 및 접근 제어
  • 디바이스 잠금과 연계 가능
  • 앱 외부 접근이 사실상 불가능

 

모바일에서는 refresh token을 Secure Storage에 저장하는 것이 사실상 표준에 가깝습니다. 다만 루팅, 탈옥 기기에서는 보안 수준이 떨어질 수 있으므로, 서버 쪽에서 기기 신뢰도 판단 로직을 함께 두는 경우도 많습니다.

 

실무 포인트 정리

  • 모바일에서는 Secure Storage 사용을 기본 전제로 한다
  • 토큰 유출보다 “디바이스 탈취” 시나리오를 고려한다
  • 의심 기기 탐지를 서버 정책과 함께 설계한다

 

웹/모바일 권장 조합 정리

  • 웹: refresh token → HttpOnly cookie, access token → 메모리
  • 모바일: refresh token → Secure Storage, access token → 메모리
  • 공통: access token은 가능한 한 저장하지 않고, 필요 시 재발급

 

운영/실무에서 자주 겪는 문제

1. 편의성 때문에 localStorage를 선택한 경우

초기 개발 속도는 빠르지만, 보안 점검이나 사고 이후 구조를 바꾸는 비용은 훨씬 큽니다. 특히 refresh token을 localStorage에 저장한 경우, 개선 시 전체 로그인 구조를 수정해야 하는 상황이 발생합니다.

 

2. cookie를 쓰면서 CSRF를 고려하지 않은 경우

HttpOnly cookie만 설정하면 안전하다고 오해하는 경우가 많습니다. CSRF 방어 없이 cookie 인증을 사용하면, 다른 형태의 공격에 그대로 노출될 수 있습니다.

 

3. 환경별 설정 불일치

개발/스테이징/운영 환경에서 Secure, SameSite 설정이 달라 운영에서만 로그인 문제가 발생하는 경우도 흔합니다. 환경별 설정은 반드시 문서화하고 점검해야 합니다.

 

 

실무 권장 체크리스트

  • refresh token과 access token의 저장 위치가 명확히 분리되어 있는가
  • 웹 환경에서 HttpOnly cookie를 기본 선택지로 고려했는가
  • CSRF 방어 전략이 함께 설계되어 있는가
  • 모바일 앱에서 Secure Storage를 사용하고 있는가
  • 환경별(cookie 옵션, HTTPS 여부) 설정이 일관적인가

 


 

 

클라이언트 토큰 저장 전략의 핵심은 “어디가 가장 안전한가”가 아니라 “어떤 위험을 통제하고 싶은가”입니다.

 

웹과 모바일의 특성을 구분하고, refresh token과 access token의 책임을 분리하면 보안과 사용자 경험을 동시에 만족시키는 구조를 만들 수 있습니다. 결국 좋은 인증 설계는 서버와 클라이언트가 함께 완성합니다.