
최근 진행한 프로젝트에서 Spring Security와 JWT를 이용한 로그인을 구현하였습니다. 구현했던 내용을 정리해보고자 글을 작성하게 되었습니다. 이번 포스팅에서는 서버 기반 인증과 토큰 기반 인증 방식에 대해 알아보고 이후 포스팅에서는 대표적인 토큰 기반 인증 방식인 JWT(JSON Web Token)에 대해 다뤄보도록 하겠습니다.
서버(session/cookie) 기반 인증과 토큰 기반 인증
기존 시스템에서는 서버 기반의 인증 방식을 사용하였다. 하지만 시스템의 규모가 커지면서 서버 기반의 인증 방식에 한계점이 보이기 시작하였고, 토큰 기반 인증 방식이 등장하게 되었다. 현재 API를 이용한 웹 서비스를 개발할 때, 토큰을 사용하여 사용자들의 인증 작업을 처리하는 것이 널리 사용되고 있다. 서버 기반 인증과 토큰 기반 인증의 차이점을 알아보고 토큰 기반 인증의 장점을 알아보자.
서버 기반 인증
HTTP 프로토콜은 Stateless 하게 동작한다. 클라이언트의 새 요청은 이전 요청에 대해 아무것도 알지 못하기 때문에 새 요청마다 다시 인증해야 한다. 이를 처리하기 위해 서버 기반 인증 방식을 사용하게 되었다.
서버 기반 인증 방식은 서버 측에서 사용자들의 정보를 기억하고 있어야 한다. 사용자들의 정보를 기억하기 위해서는 세션을 유지해야 하는데, 메모리나 디스크 또는 데이터베이스 등을 통해 관리한다. 서버 기반 인증 시스템은 클라이언트로부터 요청을 받으면, 클라이언트의 상태를 계속 유지하면서 해당 정보를 서비스에 이용하게 된다. 이러한 서버를 Stateful 서버라고 한다. 예를 들어 사용자가 로그인을 하면, 세션에 사용자 정보를 저장해두고 서비스를 제공할 때 사용한다.

이러한 서버 기반 인증 방식은 아래와 같은 문제점이 있다.
세션
유저가 인증을 할 때, 서버는 이 기록을 저장해야 하는데 이를 세션이라고 부른다. 대부분의 경우 메모리에 세션을 저장하는데, 사용자 수가 늘어난다면 서버의 램이 과부하 될 수 있다. 이를 해결하기 위해 데이터베이스에 저장할 수 있지만 이 또한 데이터베이스 성능에 무리를 줄 수 있다.
확장성
사용자가 늘어나게 되면 더 많은 트래픽을 처리하기 위해 여러 프로세스를 돌리거나, 여러 대의 서버 컴퓨터를 추가하는 등 서버를 확장해야 한다. 만약 서버를 여러 대를 사용하여 요청을 분산할 경우, 어떤 유저가 로그인했을 때, 그 유저는 처음 로그인했었던 그 서버에만 요청을 보내도록 설정을 해야 한다.


물론 세션을 사용하면서 분산된 시스템을 설계하는 것은 불가능하지는 않지만 과정이 매우 복잡하다.
CORS (Cross-Origin Resource Sharing)
클라이언트와 서버가 동일한 IP(같은 도메인)에서 동작한다면 리소스를 제약 없이 서로 공유할 수 있지만, 다른 IP주소를 사용한다면(다른 도메인) 원칙적으로는 어떤 데이터도 주고 받을 수 없다.
쿠키는 웹 어플리케이션에서 세션을 관리할 때 자주 사용되는데 단일 도메인 및 서브 도메인에서만 작동하도록 설계되어있다. 따라서 쿠키를 여러 도메인에서 관리하는 것은 번거로운 작업이다.
서버 기반의 인증 방식의 위와 같은 문제점들로 인해 현대에는 토큰 기반의 인증 방식을 사용하게 되었다.
토큰 기반 인증
토큰 기반 인증은 서버 기반 인증과는 다르게 상태를 유지하지 않는다. 즉, Stateless 하다고 할 수 있다. 이런 인증 방식은 더 이상 유저의 인증 정보를 서버나 세션에 저장하지 않음을 의미한다. 세션이 존재하지 않으므로 유저들의 로그인 상태와는 무관하게 서버를 손쉽게 확장할 수 있다. 토큰 기반 인증은 보통 아래와 같은 방식을 따른다.
- 사용자가 로그인을 시도한다.
- 서버 측에서 해당 정보를 검증한다.
- 검증에 성공하면 서버 측에서 사용자에게 Signed 토큰을 발급한다.(Signed는 서버에서 정상적으로 발급된 토큰임을 증명하는 Signature를 가지고 있다는 것을 의미한다.)
- 클라이언트 측에 전달받은 토큰을 저장해 두고, 서버에 요청을 할 때마다 Http 요청 헤더에 토큰을 포함시켜 서버에 전달한다.
- 서버는 토큰을 검증하고, 요청에 응답한다.

토큰 기반 인증 시스템을 사용하게 되었을 때의 장점은 아래와 같다.
무상태성(stateless), 확장성(scalability)
토큰을 서버에 저장하지 않고 클라이언트에 저장하기 때문에 완전히 stateless 하며, 이것은 서버를 확장하기에 매우 유리한 환경을 제공한다. 만약 세션을 서버 측에서 저장하고 있고, 서버를 여러 대를 사용하여 요청을 분산할 경우, 어떤 유저가 로그인했을 때, 그 유저는 처음 로그인했었던 그 서버에만 요청을 보내도록 설정을 해야 한다. 하지만 토큰을 사용한다면 어떤 서버로 요청이 들어가도 상관이 없게 된다.
보안성
클라이언트가 서버에 요청을 보낼 때, 더 이상 쿠키를 전달하지 않으므로 쿠키를 사용함으로써 발생하는 보안 취약점이 사라진다. 하지만 토큰을 사용하더라도 취약점이 존재할 수 있으니 언제나 보안 취약점에 대비해야 한다.
확장성(Extensibility)
시스템의 확장성을 의미하는 Scalability와 달리 Extensibility는 로그인 정보가 사용되는 분야의 확장을 의미한다. 토큰을 사용하여 다른 서비스에서도 권한을 공유할 수 있다.(구인 구직 웹 서비스인 로켓펀치에서는 Facebook, LinkedIn, GitHub, Google 계정으로 로그인을 할 수 있다) 또한 토큰 기반 인증에서는 토큰에 선택적인 권한만 부여하여 발급을 할 수 있다.(로켓펀치에서 페이스북 계정으로 로그인을 했을 때, 프로필 정보를 가져오는 권한은 있어도, 포스트를 작성할 수 있는 권한은 없다.)
여러 플랫폼 및 도메인
위에서 언급한 서버 기반 인증 방식의 문제점 중 하나인 CORS를 해결할 수 있는데, 애플리케이션과 서비스의 규모가 커지면 여러 디바이스를 호환시키고 더 많은 종류의 서비스를 제공하게 된다. 토큰을 사용한다면, 디바이스나 도메인에 상관없이 토큰만 유효하다면 요청이 정상적으로 처리된다. 이러한 구조를 통해 assets 파일(image, css, js, html 파일 등)은 모두 CDN에서 제공을 하고, 서버 측에서는 API만 다루도록 설계할 수 있다.
마무리
이번 포스팅에서는 서버 기반 인증과 토큰 기반 인증을 서로 비교해보면서 토큰 기반 인증 방식의 이점에 대해 알아보았습니다. 다음 포스팅에서는 대표적인 토큰 기반 인증 방식인 JWT(JSON Web Token)에 대해 알아보겠습니다.
참고
https://hackernoon.com/why-do-we-need-the-json-web-token-jwt-in-the-modern-web-k29l3sfd
https://brunch.co.kr/@jinyoungchoi95/1
'Web' 카테고리의 다른 글
캐시(로컬 캐시 & 글로벌 캐시)에 대해 알아보자! (0) | 2023.05.21 |
---|---|
JWT의 다양한 보안 전략에 대해 알아보자! (0) | 2022.09.04 |
JWT(Json Web Token)에 대해 알아보자! (0) | 2022.09.04 |