어떤 서비스를 만들던, 로그인은 빠질 수 없는 필수 기능이 아닐까 싶다. 그리고 개발 초기에 구현하는 기능이기 때문에 웹/앱 관계없이 개발자라면 꼭 알아두어야 하는 기능이 아닐까 싶다. JWT(Json Web Token) 기반의 로그인 인증 방식에 대해 나름 공부하며 얻은 지식들을 정리해본다.

JWT 기반의 로그인 인증 방식이 널리 사용되는 이유 중 하나는 Stateless(무상태성 이라고도 하는 듯)라는 특성 때문이다. 그럼 Stateless는 뭐고, 왜 좋은걸까? 그걸 알기 위해선 Stateful한 방식(세션 기반 인증)과 먼저 비교하여 이해할 필요가 있다.

 

Stateful한 세션 기반 인증 방식과 장단점

Stateful한 세션 기반 인증 방식은 전통적인 웹 애플리케이션에서 많이 사용되는 인증 방식이다. Stateful이란, 서버가 클라이언트와의 상호작용에서 상태(state)를 유지한다는 의미이다. 서버는 클라이언트와의 각 요청을 처리하면서 이전 요청에서 생성된 정보를 저장하고 관리한다. 이 정보는 보통 세션(Session)이라고 불리며, 서버는 클라이언트의 세션을 유지함으로써, 사용자가 로그인한 후에 사용자를 인식할 수 있게 된다. 세션 기반 인증은 대략 다음과 같은 절차로 작동한다.

  1. 로그인 요청 : 클라이언트가 서버에 로그인 요청을 보냄. 이 요청에는 사용자의 아이디와 패스워드와 같은 자격 증명이 포함된다.
  2. 서버에서 인증 : 서버는 이 자격 증명을 받아서 DB를 조회해 유효성을 확인한다. 유효하면 클라이언트에 대해 세션을 생성한다. 이 세션은 서버 메모리나 데이터베이스에 저장된다. 세션에는 고유한 식별자(Session ID)가 부여된다. 내가 처음 세션 개념을 알게 되었을 때에는 그냥 뭉뚱그려 개별 유저에게 부여되는 딕셔너리 형식의 자료구조라고 이해하고 사용했다.
  3. 세션ID 전달 : 서버는 이 세션 ID를 클라이언트에게 쿠키에 담아 전달한다. 이 쿠키는 클라이언트가 서버에 요청을 보낼 때마다 자동으로 포함된다.
  4. 요청 처리 : 클라이언트가 서버에 요청을 보낼 때마다, 클라이언트의 브라우저는 쿠키에 포함된 세션 ID를 서버에 보낸다. 서버는 이 세션 ID를 확인하여, 해당 사용자가 이미 인증된 상태인지, 어떤 사용자인지 등을 파악한다.
  5. 세션 유지 : 서버는 사용자가 로그아웃하거나 세션이 만료되기 전까지, 해당 세션 ID를 유지하며 클라이언트의 상태를 관리한다.

세션 기반 인증 방식을 쇼핑몰 웹사이트를 예로 들어 생각해보면, 사용자가 쇼핑몰 웹사이트에 로그인하면 서버는 사용자의 정보를 인증하고, 이 사용자에게 고유한 세션을 생성한다. 세션 ID를 'ABCD1234'라고 가정해보겠다. 서버는 이 'ABCD1234'라는 세션 ID를 서버 메모리나 DB에 저장하고, 이 세션에 사용자의 정보와 상태(ex: 장바구니에 담긴 상품 리스트)를 저장한다. 서버는 'ABCD1234'라고 하는 세션 ID를 사용자의 브라우저로 쿠키에 담아 보낸다. 사용자가 상품을 장바구니에 추가하면, 서버는 이 요청을 받아 'ABCD1234'라는 세션에 해당 상품 정보를 추가한다. 사용자가 로그아웃하면, 서버는 'ABCD1234' 세션을 삭제하고 더 이상 해당 세션을 유지하지 않는다. 이후의 요청에서는 더이상 해당 사용자를 인증된 상태로 인식하지 않게 된다.

Stateful한 세션 기반 인증의 장점은 사용자별 상태를 별도로 계속 유지하기 때문에 사용자의 특정 상태(ex: 장바구니 리스트, 사용자 설정 등)를 쉽게 관리할 수 있다. 또한, 세션 타임아웃, 세션 무효화 등의 관리 기능을 통해 사용자의 인증 상태를 관리할 수 있다.

Stateful한 세션 기반 인증의 단점으로는 서버가 각 클라이언트마다 세션을 유지해야 하므로, 사용자가 많아질수록 서버 메모리나 DB의 부하가 증가한다. 특히, 여러 서버로 확장(scale-out)할 때, 세션을 공유하는 것이 복잡해질 수 있다. 그리고 사용자의 세션이 특정 서버에 종속되기 때문에, 서버 간의 부하 분산이나 장애 처리에 어려움이 생길 수 있다.

 

Stateless한 JWT 기반 인증 방식과 장단점

그럼 이 글의 핵심인 Stateless한 방식에 대해 알아보겠다. 단어 의미대로, 서버가 클라이언트와의 각 요청 사이에 어떠한 상태도 유지하지 않는다는 의미이다. 서버는 각 요청을 독립적으로 처리하며, 이전 요청이나 이후 요청과의 연관성을 고려하지 않는다. 조금 더 자세히 들어가면, 클라이언트가 로그인하면, 서버는 JWT를 생성하여 클라이언트에게 전달한다. 이 JWT는 클라이언트가 이후 요청을 할 때마다 포함시켜 보내며, 서버는 이 토큰을 검증하여 클라이언트를 인증한다. 모든 필요한 정보는 JWT 자체에 포함되어 있기 때문에 세션이나 상태 정보를 유지할 필요가 없다.

Stateless의 장점으로는 서버를 수평적으로 쉽게 확장할 수 있다는 점이다. 서버 부하가 증가할 때 새로운 서버 인스턴스를 추가하여 트래픽을 분산시키는 것이 쉽고, 서버 코드와 인프라가 단순해질 수 있다. 또한, 클라이언트의 상태를 신경 쓰지 않고 요청을 처리할 수 있어 서비스 가동 중단 없이 쉽게 서버를 재시작하거나 배포할 수 있다는 것을 의미한다.

Stateless의 단점으로는 JWT를 클라이언트가 보관하고, 요청마다 전송하기 때문에, 만료된 토큰을 강제로 무효화하기 어렵다. 이를 해결하기 위해서 짧은 만료주기의 access token과 상대적으로 긴 만료주기의 refresh token을 같이 사용하는 방식 등으로 많이 운영된다. 또한, JWT에는 사용자에 대한 정보를 인코딩하여 저장하기 때문에, 세션 ID만 저장하는 방식보다 더 큰 크기의 데이터를 전송해야 한다. 이로 인해 네트워크 대역폭이 더 많이 사용될 수 있다.

728x90

+ Recent posts