오늘은 웹 개발의 심장이자 면접 단골 질문인 인증(Authentication) 시스템 구축에 대해 이야기해볼게. 내가 15년 동안 풀스택 개발자로 구르면서 정말 수많은 인증 방식을 구현해봤는데, 의외로 많은 주니어들이 세션과 JWT의 차이를 제대로 모르고 단순히 "남들이 쓰니까" JWT를 선택하더라고. 실무에서 바로 써먹을 수 있는 인증 시스템 설계 노하우를 몇 가지 짚어줄게.
1. 세션과 JWT, 트렌드가 아니라 서비스 규모로 결정해라
많은 신입 개발자들이 무조건 JWT가 좋은 줄 알고 쓰지만, 절대 그렇지 않아. 두 방식은 명확한 트레이드오프가 있거든.
- 세션 기반 인증: 서버 메모리나
Redis에 세션 상태를 저장하는 방식이야. 사용자를 강제 로그아웃시키거나 중복 로그인을 막는 제어가 아주 쉽지. 하지만 서버가 늘어날 때 세션 동기화를 신경 써야 해서 확장이 까다로워. - JWT 기반 인증: 토큰 자체에 사용자 정보를 담아 클라이언트에 저장하는 Stateless(무상태) 방식이야. 서버는 토큰 검증만 하면 되니 확장에 매우 유리하지만, 한 번 발급된 토큰은 만료 전까지 강제로 회수하기가 어렵다는 치명적인 단점이 있어. 따라서 단일 서버로 시작하는 초기 서비스라면 오히려 든든한 세션 방식이 훨씬 유리할 수 있어.
2. JWT를 로컬 스토리지에 저장하는 실수를 멈춰라
포트폴리오를 보면 많은 친구들이 JWT를 브라우저의 localStorage나 sessionStorage에 저장하더라고. 이건 "제 보안 키를 가져가세요"라고 광고하는 것과 같아. XSS(Cross-Site Scripting) 공격에 노출되면 자바스크립트 코드 한 줄로 토큰을 탈취당할 수 있거든.
가장 안전한 방법은 AccessToken은 메모리(변수)에 두고, RefreshToken은 보안 옵션(httpOnly, Secure, SameSite=Strict)이 적용된 **쿠키(Cookie)**에 저장하는 거야. 이렇게 하면 자바스크립트로 쿠키에 접근할 수 없어서 XSS 공격을 원천 차단할 수 있지.
3. 실무형 인증의 치트키, 토큰 로테이션과 인터셉터
보안을 한 단계 더 높이려면 Refresh Token Rotation (RTR) 기법을 도입해야 해. 사용자가 새로운 AccessToken을 요청할 때마다 RefreshToken도 새것으로 재발급해주는 방식이지. 이렇게 하면 혹시 모를 토큰 탈취 상황에서도 피해를 최소화할 수 있어.
프론트엔드에서는 axios의 interceptor를 활용해서 토큰 만료 에러(401)가 났을 때 자동으로 토큰 재발급 API를 호출하고 기존 요청을 재시도하는 로직을 짜야 해. 이 흐름을 매끄럽게 처리할 줄 알아야 진짜 실무를 아는 개발자 대접을 받거든. 요즘은 NextAuth.js 같은 라이브러리를 쓰면 이런 복잡한 세션 관리와 OAuth2 연동을 아주 편하게 구현할 수 있으니 꼭 공부해봐.
💡 핵심 정리
- 세션은 제어가 쉽지만 확장이 어렵고, JWT는 확장이 쉽지만 제어가 어렵다.
- 보안을 위해 JWT는 절대
localStorage에 저장하지 말고, 보안 쿠키(httpOnly)를 활용하자.- 실무 수준의 시스템을 원한다면 **RTR(Refresh Token Rotation)**과 프론트엔드 Interceptor 패턴을 반드시 구현해보자. 인증 시스템은 한 번 뚫리면 서비스 전체가 무너지는 아주 민감한 영역이야. 단순히 라이브러리 가져다 쓰는 데 그치지 말고, 데이터가 어떻게 오가는지 그 흐름을 머릿속으로 완벽하게 그려가며 코드를 짜봐. 이 정도 깊이로 고민하고 면접에서 털어놓는다면, 분명 남들과 다른 눈에 띄는 지원자가 될 수 있을 거야.