세션(Session)과 토큰(Token)은 사용자 인증(Authentication)과 인가(Authorization) 및 상태 관리(State Management)를 위한 주요 기술이다.
세션 기반 인증은 서버에서 유저의 상태를 관리한다. 그래서 개발자들은 서버의 부담을 줄이기 위해서, 서버에 사용자의 인증 상태를 저장하는 것이 아닌 클라이언트에 저장하는 방법을 고안하였고, 이게 바로 토큰이다.
쿠키(Cookie)
브라우저에 데이터를 저장하는 것을 말한다. 모든 브라우저는 '요청'을 보내고 '응답'을 받는데, 이때 브라우저가 요청을 보낼 때 보내야할 데이터가 있다면, 쿠키와 같은 데이터를 요청에 포함시켜 보낼 수 있다.
쿠키에 저장된 값 덕분에 인증 정보는 물론 다양한 데이터를 저장할 수 있어, 페이지 이동이나 브라우저를 닫아도 데이터를 유지할 수 있다. 일반적으로 쿠키는 유효기간을 설정할 수 있으며, 이 기간은 개발 환경에 따라 다를 수 있다.
쿠키는 브라우저에 데이터를 저장하므로 클라이언트 측에서 데이터를 수정할 수 있다는 특징이 있다. 따라서 보안에 민감한 정보는 쿠키에 저장하지 않는 것이 좋다.
HTTP의 비상태성(Stateless)
HTTP는 stateless한 특성을 가지기 때문에 각 통신의 상태는 저장되지 않는다. 따라서 HTTP만으로는 요청한 클라이언트가 이전에 인증을 받았는지 확인할 방법이 없다. 그렇다고 매번 새 페이지를 요청할 때마다 로그인하라고 요구하는 것은 사용자의 편의를 전혀 고려하지 않는 방식이다.
사용자의 아이디와 패스워드를 브라우저에 그대로 저장해놓고, 매 요청마다 함께 이 정보를 보내는 방법은 어떨까? 이런 방식은 전송 데이터가 커져 비효율적이고, 클라이언트 측에 민감한 데이터가 저장되어 보안상 매우 취약하다. 또한 서버 측에서는 매번 데이터베이스를 조회하고 인증 과정을 거쳐야 하므로 비효율적이다.
이 문제를 해결하기 위한 대표적인 도구 두 가지가 바로 세션과 토큰이다.
유저가 로그인을 시도하면, 서버는 일치하는 유저 정보를 찾은 후 인증 확인의 표시로 세션이나 토큰을 발급하여 클라이언트에게 전달한다.
브라우저는 받은 세션이나 토큰 정보를 저장하고 있다가, 이후 요청 시 인가를 위해 이를 함께 낸다.
세션과 토큰의 목적은 유사하지만, 가장 큰 차이점은 세션은 서버의 데이터베이스에 저장되고, 토큰은 클라이언트 측에 저장된다는 점이다.
세션(Session)
서버에서 사용자 정보를 유지하는 방식으로, 사용자가 로그인하면 서버에 세션을 생성하고 이를 통해서 사용자를 식별한다.
세션은 각 요청마다 정보를 전송하는 방법 중 하나로, 서버에서 세션 DB를 구축하고 세션 ID를 통해 사용자의 정보를 파악한다.
세션은 위해서 말한 브라우저의 저장 방식인 쿠키 속에 세션 ID를 저장시킨다. 이후 클라이언트가 서버에 요청을 보낼 때, 쿠키에 담긴 세션 ID 정보를 통해 서버가 해당 사용자의 정보를 확인하고 응답을 보낸다.
동작 과정
- 사용자가 로그인하면 DB나 서버 메모리에서 세션 ID를 생성
- 아이디, 로그인 날짜, 유효기간, session id 등을 저장하고 유저에게는 session id만 보내준다.
- 생성된 세션 ID를 클라이언트에 쿠키(cookie)로 전달
- 이후 클라이언트는 요청 시 세션 ID를 쿠키로 보내며, 서버는 이를 확인하고 사용자를 식별
- session id를 가진 doc을 DB에서 찾아본 후 아무런 이상이 없고 유효기간도 지나지 않으면 통과시켜준다.
세션은 서버에 저장되므로 한꺼번에 다수의 접속자가 발생하면 과부하가 걸릴 수 있다. 이를 해결하려면 서버를 여러 대 두는 방법이 있지만, 유저의 세션 데이터는 하나의 서버에 저장되기 때문에, 이 경우 세션 공유가 복잡해지는 문제도 발생한다. 또한, 유효기간, HttpOnly, Secure 옵션 등을 설정하여 쿠키에 저장된 세션 ID의 보안을 강화해야 한다. 혹은 Sticky Server 방식을 사용하여 특정 유저가 항상 동일한 서버에 연결되도록 할 수 있다.
토큰(Token)
클라이언트에서 인증 정보를 관리하는 방식으로, 사용자 로그인 시 서버에서 발급한 토큰을 이용해 인증을 수행하는 방식이 있다. 대표적인 예가 JWT(JSON Web Token)입니다.
쿠키는 브라우저에 데이터를 저장하는 방식인데, 만약 네이티브 환경처럼 브라우저가 없는 경우에는 쿠키 대신 토큰을 사용할 수 있다.
쿠키와 차이점이라면, 관심사를 들 수 있는데 쿠키는 세션 ID 혹은 보안과 관련되지 않은 단순한 데이터 정보를 가지는데 반해, 토큰은 인증과 관련된 정보를 담고 있다.
그렇다면 클라이언트 측에 저장되는 정보가 민감할 수 있는데, 어떻게 인증과 관련된 정보를 안전하게 담을 수 있을까?
바로 JWT는 서명이 되어 있어서이다. JWT는 JSON 형식으로 정보를 저장하며, 서명을 통해 '무결성'을 검증할 수 있습니다. 즉, 토큰이 변조되지 않았음을 확인할 수 있어 인증과 권한 관리와 관련된 정보를 저장하는 데 안전하게 사용할 수 있다.
토큰은 사용자가 어떤 리소스를 이용할 수 있는 권한을 나타내는 증표이다. 웹 보안에서의 토큰은 인증과 권한 정보를 포함한 암호화된 문자열로, 이를 통해 특정 애플리케이션이나 서비스에 대한 유저의 접근 권한을 제어할 수 있다.
동작 과정
- 사용자가 로그인하면 서버는 사용자에 대한 권한 정보를 서버의 비밀키와 함께 토큰(JWT)를 생성
- Authorization 헤더에 토큰을 담아 클라이언트에게 전달(보통 로컬 스토리지나 쿠키에 저장)
- 이후 요청 시 토큰을 Authorization 헤더에 포함해 서버로 전달
- 서버는 전달받은 토큰을 서버의 비밀키로 검증하여, 토큰이 위조되었는지, 유효 기간이 지났는지 등을 확인
- 토큰이 유효하다면, 서버는 사용자의 요청에 대한 응답 데이터를 전송
JWT 토큰 기반 인증은 확장성 면에서 유리하고, 분산 환경인 마이크로서비스에 적합하다. 또한, 무상태(stateless) 방식이기 때문에 서버 부하가 적고 성능이 향상된다. 그러나 보안 관리 측면에서는 토큰이 탈취될 위험이 있으며, 토큰 변경 시 로그아웃 처리가 복잡하고, 토큰의 크기가 커지면 네트워크 부담을 초래할 수 있다.
웹 브라우저 측(local storage나 쿠키)에 저장되는 토큰은 공격에 노출될 가능성이 있으므로, 토큰에 민감한 정보를 담지 않고 유효 기간을 짧게 설정해 공격에 노출될 시간을 최소화해야 한다. 다만, 너무 짧은 유효 기간은 사용자가 반복적으로 로그인해야 하는 번거로움을 만들 수 있다. 이를 해결하기 위해 refresh token을 발급하여 토큰이 만료되거나 변질될 경우 새 토큰을 재발급받을 수 있도록 한다. refresh token은 긴 유효 기간을 가지고 있으며, 최대한 안전한 위치에 저장되어 기존 토큰을 재발급하는 역할을 한다.
JWT 토큰은 유저가 로그인에 성공하면 발급되며, 토큰에는 아이디, 로그인 날짜, 유효 기간 등이 포함되어 암호화된다. 이후 유저는 GET 또는 POST 요청 시 해당 토큰을 제출해 인증을 받는다. 이 방식은 매 요청마다 DB 조회를 할 필요가 없기 때문에 성능에 유리하지만, 토큰이 탈취되면 다른 컴퓨터에서 인증을 우회할 수 있는 문제가 발생할 수 있다. 이 문제를 해결하려면 악성 토큰을 모아서 DB와 비교하는 방법이 있지만, 이는 세션 기반 방식과 유사해지므로 단점이 될 수 있다.
세션 vs 토큰
구분 | 세션(Session) | 토큰(Token) |
저장 위치 | 서버 | 클라이언트 (로컬 스토리지, 쿠키) |
사이즈 | 작다 | 크다 |
확장성 | 낮음 (서버 부하 증가) | 높음 (서버 부하 감소) |
보안 | 서버에서 정보 관리로 안전 | 탈취 시 위험 (유효기간 설정 필수) |
속도 | 느림 (서버 접근 필요) | 빠름 (서버 접근 불필요) |
상태 | 상태 유지 (Stateful) | 무상태 (Stateless) |
적합한 경우 | 민감한 데이터 (결제, 내부 서비스) | 대규모 서비스, API (마이크로 서비스) |
- 세션 사용 시점
- 보안이 중요한 경우 (e.g., 은행, 결제 시스템)
- 사용자 정보를 자주 변경하거나 즉시 무효화해야 하는 경우
- 단일 서버 환경에서 운영하는 경우
- 토큰 사용 시점
- 확장성이 중요한 경우 (e.g., 대규모 서비스, REST API)
- 마이크로서비스 아키텍처 환경
- 모바일, SPA(Single Page Application)와 같은 클라이언트 중심 환경
참조
https://codingapple.com/course/node-express-mongodb-server/
https://hudi.blog/session-based-auth-vs-token-based-auth/
https://fierycoding.tistory.com/69
https://kindjjee.tistory.com/139
카카오 테크 캠퍼스를 진행할 때, 멘토님이 추천해주신 영상을 보고 정리한 글(인증과 인가)이 있다. 그냥 비슷한 영역이라고 생각해서 한 번 읽어보았는데 session과 token에 대한 내용이 그대로 있었다. 그때는 무작정 정리했는데 지금 보니 좀 더 이해가 잘 되고 색다르다.
인증과 인가
인증과 인가란인증 : (식별가능한 정보로) 서비스에 등록된 유저의 신원을 입증하는 과정인가 : 인증된 사용자에 대한 자원 접근 권한 확인 자원을 적절한/유효한 사용자에게 전달/공개하기 위
best11gh.tistory.com
공부하면서 직접 만들어보면 이해하는 JWT라는 포스팅을 보았는데 다음에 해봐야겠다.
'백엔드' 카테고리의 다른 글
애플 로그인 테스트 (1) | 2025.04.21 |
---|---|
인증과 인가 (0) | 2024.07.15 |