본문으로 건너뛰기
zoe

🔑 인증, 고를 게 많다

백엔드 스터디를 하면서 드디어 인증을 구현하게 되었다. 강의에서는 가볍게 JWT 토큰을 헤더에 저장하는 방식만 설명하고 있어 가볍게 많이 사용하는 방식들에 대해 더 공부해보고자 한다.


인증에는 네 가지 선택지가 있다

인증을 공부하다 보면 "JWT vs 세션", "쿠키 vs 헤더" 같은 비교를 자주 마주친다.

그런데 이것들은 서로 다른 층위의 이야기다.

선택지질문예시
인증 수단뭘로 신원을 증명하나?세션ID, JWT
전달 방식클라이언트와 서버가 어떤 경로로 주고받나?쿠키, 헤더
서버 저장소서버는 어디에 기억해두나?없음, Redis, DB
클라이언트 저장소클라이언트는 어디에 보관하나?쿠키, 로컬스토리지, Secure Store

이 네 선택지는 독립적이다. 그래서 조합이 가능하다.

예를 들어 같은 JWT라도, 웹에서는 쿠키에 담아 보내고 모바일에서는 헤더에 붙여 보낼 수 있다. 인증 수단이 같아도 전달 방식은 다를 수 있다.


인증 수단 — "뭘로 증명하나?"

인증이란 서버에게 "나 이 사람이야"를 증명하는 방식이다.

세션 (Session)

서버가 상태를 기억한다. 세션ID는 열쇠일 뿐이고, 실제 정보는 서버 저장소에 있다.

JWT (JSON Web Token)

세션과 반대로 서버가 아무것도 기억하지 않는다(Stateless)

토큰 자체에 유저 정보(ID, 역할 등)가 들어있고, 서버는 "이 토큰이 내가 서명한 게 맞는지"만 확인한다.

여기에 함정이 있다. 서버가 아무것도 기억하지 않으니, 토큰을 서버에서 무효화할 수 없다. 유저가 로그아웃해도, 토큰이 탈취돼도, 만료 시간이 될 때까지 토큰은 유효하다.

JWT + Refresh Token

순수 JWT의 한계를 보완한 방식이다.

Access Token 수명을 짧게 가져가 탈취 위험을 줄이고, Refresh Token은 서버가 관리해 강제 무효화를 가능하게 한다. Stateless의 장점은 살리되, 필요한 부분만 서버가 관리하는 하이브리드 방식이다.

비교

세션JWTJWT + Refresh
서버 상태StatefulStateless하이브리드
강제 로그아웃쉬움어려움가능
서버 부담매 요청 저장소 조회서명 검증만서명 검증 + 일부 조회
토큰 탈취 시세션 삭제로 차단만료까지 유효짧은 수명으로 완화

전달 방식 — "어떻게 보내나?"

인증 수단을 정했으면, 클라이언트와 서버가 어떤 경로로 주고받을지 정해야 한다.

서버가 응답에 Set-Cookie를 보내면, 브라우저가 이후 매 요청에 쿠키를 자동으로 포함시킨다. 프론트 코드에서 별도로 붙이는 작업이 필요 없다.

가장 큰 장점은 HttpOnly 옵션이다. JavaScript에서 쿠키에 접근할 수 없어, 악성 스크립트가 토큰을 훔치는 XSS 공격을 원천 차단한다.

Secure과 SameSite옵션으로도 중간자 공격이나 csrf공격을 방어할 수 있다.

단점은 브라우저 환경에서만 의미가 있다는 것이다. 모바일 네이티브 앱에는 브라우저가 없으니 자동 전송이나 HttpOnly 보호가 작동하지 않는다.

Authorization 헤더 (Bearer Token)

요청을 보낼 때 코드로 직접 헤더에 토큰을 붙인다.

브라우저 의존이 없어서 모바일 앱, SPA, 서버 간 통신 어디서든 쓸 수 있다. 대신 토큰을 저장하고 꺼내서 붙이는 건 개발자 몫이다. 프론트 입장에서 토큰 관리 방식이 중요해지는 이유다.

비교

쿠키Authorization 헤더
전송브라우저가 자동코드로 직접
XSS 방어HttpOnly로 JS 접근 차단저장소에 따라 다름
CSRF 위험있음 (SameSite로 완화)없음
모바일불편함적합
적합가능

서버 저장소 — "서버는 어디에 기억하나?"

순수 JWT처럼 서버가 아무것도 저장하지 않는 경우도 있지만, 대부분의 서비스에서는 서버 쪽에도 뭔가를 저장한다. 세션 정보일 수도 있고, 토큰 유효 여부일 수도 있다.

없음 (순수 Stateless)

서버가 아무것도 저장하지 않는다. JWT 서명만 검증하면 끝이다.

서버 확장이 쉽다. 서버가 10대든 100대든 같은 비밀키만 공유하면 어느 서버에서든 토큰을 검증할 수 있다. 대신 강제 무효화가 안 된다.

메모리 (서버 변수)

서버 프로세스 메모리에 세션을 저장한다. 가장 빠르지만, 서버가 여러 대면 문제가 된다. 유저가 A 서버에서 로그인했는데 다음 요청이 B 서버로 가면 세션을 찾을 수 없다.

Redis

인메모리 저장소로, DB보다 빠르고 서버 간 공유가 가능하다.

서버가 여러 대여도 모두 같은 Redis를 바라보니 세션 공유 문제가 해결된다. 활용 예시도 다양하다.

용도저장하는 것예시
세션 저장소세션ID → 유저 정보전통 세션 방식
토큰 블랙리스트로그아웃된 토큰 ID(jti)JWT 강제 무효화
세션 유효성세션ID → 유효 여부 (Y/N)JWT + 세션 하이브리드
Refresh TokenRefresh Token 해시토큰 갱신 관리

DB (PostgreSQL, MySQL 등)

영구 저장이 필요할 때 사용한다. Redis보다 느리지만 데이터가 날아가지 않는다. 실시간 조회는 Redis에, 보안 로그나 세션 이력은 DB에 두는 식으로 함께 쓰는 경우가 많다.

비교

없음메모리RedisDB
속도가장 빠름빠름상대적으로 느림
서버 확장자유로움불가가능가능
영구성서버 재시작 시 소멸설정에 따라영구
강제 무효화불가가능가능가능
주 용도순수 JWT단일 서버 개발세션/토큰 관리이력/영구 저장

클라이언트 저장소 — "클라이언트는 어디에 보관하나?"

서버에서 받은 토큰이나 세션ID를 클라이언트 어디에 저장할지의 문제다. 이 선택이 보안에 직접적인 영향을 미친다.

쿠키

서버가 Set-Cookie로 설정하면 브라우저가 관리한다. HttpOnly를 켜면 JavaScript에서 접근할 수 없다.

로컬스토리지 (localStorage)

브라우저를 닫아도 유지된다. 편하지만 JavaScript로 자유롭게 접근 가능해, XSS 공격에 취약하다.

세션스토리지 (sessionStorage)

로컬스토리지와 비슷하지만 탭을 닫으면 사라진다. XSS 취약점은 동일하다.

Secure Store (모바일)

모바일 OS가 제공하는 암호화된 저장소다. iOS의 Keychain, Android의 Keystore가 이에 해당한다. React Native에서는 expo-secure-store 같은 라이브러리를 통해 접근한다. 앱 외부에서는 접근이 불가능하다.

메모리 (변수)

새로고침하면 사라진다. 가장 안전하지만 가장 불편하다. 수명이 짧고 Refresh Token으로 재발급 가능한 Access Token에 쓰기도 한다.

비교

쿠키 (HttpOnly)로컬스토리지세션스토리지Secure Store메모리
JS 접근불가가능가능불가 (앱 외부)가능 (앱 내부만)
XSS 위험안전취약취약해당 없음안전
지속성만료까지영구탭 닫으면 소멸영구새로고침 시 소멸
환경모바일어디든

보안 위협이 선택을 결정한다

환경마다 다른 저장소를 쓰는 이유는 위협의 종류가 다르기 때문이다.

웹의 주요 위협은 XSS다. 악성 스크립트가 페이지에 삽입되면 JavaScript로 접근 가능한 모든 저장소의 토큰을 탈취할 수 있다. JS가 접근할 수 없는 HttpOnly 쿠키가 안전한 이유다.

모바일의 주요 위협은 기기 탈취와 리버스 엔지니어링이다. 브라우저가 없으니 XSS는 해당이 없고, OS 레벨에서 암호화해주는 Secure Store가 가장 안전하다. HttpOnly가 JS 접근을 막는 보호라면, Secure Store는 앱 외부의 접근을 막는 보호인 셈이다.

환경주요 위협추천 저장소추천 전달 방식
XSSHttpOnly 쿠키쿠키 (자동 전송)
모바일 앱기기 탈취Secure Store헤더 (직접 전송)
웹 + 모바일둘 다환경별 분기쿠키 + 헤더 둘 다 지원

마치며

그동안 서버가 이 토큰을 어떻게 검증하는지, 세션을 어디에 저장하는지, 왜 Redis를 쓰는지 같은 건 생각해본 적이 없었다.

백엔드 스터디를 하면서 서버는 단순히 토큰을 발급하고 검증하는 것에서 끝이 아니라는 걸 알게 되었고, 글을 쓴 것 이외에도 이미 폐기된 Refresh Token이 재사용되면 탈취로 판단해 전체 세션을 강제 로그아웃시키는 재사용 감지(Reuse Detection), 세션 유효성을 Redis에서 빠르게 확인하는 캐싱 전략 등 보안을 위해 다양한 방식으로 토큰을 관리하는 방식등 다양한 것을 공부해보면 좋을 것 같다는 생각이 든다 !...