세션 vs JWT: 언제 어떤 것을 선택해야 할까?

Lord·2024년 10월 24일

Problem Solving Skills

목록 보기
3/17
post-thumbnail

회원 인증과 인가를 구현할 때, 세션(Session)JWT(JSON Web Token) 중 어떤 방식을 선택할지 고민하는 것은 백엔드 개발자라면 한 번쯤 고민해보았을 것이다. 이번 프로젝트에서 나는 JWT 방식을 선택하였으며, 그 이유와 과정을 정리해 보았다. 확장성, 보안성, 그리고 시스템의 유연성 측면에서 어떤 접근이 더 나은 선택이 될지에 대해 깊이 고민한 결과이다.


세션(Session)이란?

세션은 서버에서 클라이언트와의 연결을 관리하기 위한 상태 저장 방식이다. 사용자가 로그인하면 서버는 특정 정보를 저장하고, 이를 고유한 세션 ID로 매핑하여 클라이언트에게 전달한다. 이 세션 ID는 클라이언트의 쿠키에 저장되고, 이후 모든 요청에서 이 세션 ID를 전송해 인증된 사용자임을 증명하게 된다.

장점: 세션의 주요 장점은 서버에서 사용자 상태를 직접 관리하여 보안성을 높일 수 있다는 점이다. 서버는 사용자 세션을 중앙에서 관리하기 때문에, 세션 만료나 로그아웃 같은 관리가 용이하며, 민감한 데이터에 대한 통제도 훨씬 수월하다.

또한, 세션의 유효 기간을 설정하고 사용자 활동에 따라 이를 갱신할 수 있어 불필요한 세션 유지 비용을 줄일 수 있다. 일정 시간이 지나면 세션이 자동으로 만료되므로 보안 관리가 수월하다.

단점: 세션은 서버가 상태 정보를 저장하고 관리하기 때문에 확장성에 한계가 있다. 특히 대규모 트래픽을 처리해야 하는 환경에서는 서버의 메모리나 스토리지에 부담이 될 수 있다. 또한, 서버 간 상태 동기화가 필요해지는 상황에서는 로드 밸런싱을 구현하는 것도 어려워진다. 예를 들어, 서버 장애가 발생했을 때 다른 서버로 사용자의 세션 정보를 복구해야 하는 경우나, 사용자의 권한이나 세션 데이터가 변경될 때 이를 모든 서버에 동기화해야 하는 상황에서 상태 동기화가 필요하다. 이러한 이유로 세션 방식은 단일 서버 환경에서는 적합하지만, 분산 환경에서는 그 한계가 쉽게 드러난다.


JWT(JSON Web Token)란?

JWT는 JSON 형식으로 데이터를 안전하게 전송하기 위해 사용되는 토큰 기반의 무상태(stateless) 인증 방식을 제공한다. JWT는 세 가지 파트로 구성되며, 각각 헤더(Header), 페이로드(Payload), 서명(Signature)으로 나뉜다. 헤더는 토큰의 타입과 해싱 알고리즘 정보를 담고 있고, 페이로드는 사용자 정보나 기타 데이터를 포함한다. 서명은 이 데이터가 변조되지 않았음을 보장한다.

사용자가 로그인하면 서버는 JWT를 생성해 클라이언트에 전달하며, 이후 클라이언트는 각 요청에 이 토큰을 첨부해 서버에 전송한다. 서버는 이 토큰을 검증하여 사용자 정보를 확인하고 인가 절차를 진행한다. 서버는 해당 인증 유저에 대한 정보를 계속 갖고 있지 않고, 단지 자신이 발급해 준 토큰인지만 확인하는 역할을 한다. JWT는 기본적으로 암호화된 정보가 아니며, 대신 서명을 통해 데이터의 무결성을 보장한다. 따라서 민감한 정보를 직접적으로 포함하지 않는 것이 좋다.

장점: JWT의 가장 큰 장점은 서버에 별도의 세션 저장소를 두지 않아도 된다는 점이다. 모든 정보는 JWT 자체에 포함되어 있어 서버는 토큰의 유효성만 검증하면 된다. 이러한 구조 덕분에 분산 서버 환경에서 확장성이 높아지며, 여러 서버에서 독립적으로 인증을 수행할 수 있다. 특히 MSA 구성으로 여러 서비스가 나누어져 있을 경우 이러한 장점이 더욱 돋보인다.

또한, JWT는 표준화된 구조를 가지고 있어 다양한 플랫폼 간의 통합이 용이하다. 클라이언트와 서버 간에 JWT를 사용해 인증 정보를 교환하면, 시스템의 복잡성을 줄이고 성능을 개선할 수 있다.

단점: JWT는 발급된 토큰을 만료 전까지는 무효화할 수 없다는 한계가 있다. 이로 인해 보안 취약점이 생길 수 있으며, 이를 보완하기 위해 주로 Refresh Token을 사용한다. 또한, JWT는 클라이언트에 모든 정보를 포함하고 있기 때문에 대량의 데이터를 저장할 경우 네트워크 부하가 증가하고 클라이언트 스토리지에도 영향을 줄 수 있다.


JWT 선택의 이유

이번 프로젝트에서 나는 확장성과 무상태성을 고려하여 JWT를 선택하였다. 서버에 세션 상태를 저장하지 않음으로써 서버의 부하를 줄일 수 있었고, 대규모 트래픽 테스트를 염두에 둔 확장성의 확보가 큰 장점으로 작용하였다. RESTful API와 같이 무상태성을 요구하는 시스템 구조에서 JWT는 특히 효과적이었다. 서버가 요청마다 클라이언트 상태를 참조할 필요가 없어지므로 성능 향상과 확장성에서 큰 이점을 제공하였다.


Refresh Token의 필요성과 도입 이유

JWT의 단점 중 하나는 발급된 토큰을 만료 전까지 무효화할 수 없다는 점이다. 이를 해결하기 위해 Refresh Token을 도입하였다.

Refresh Token은 Access Token보다 더 긴 유효 기간을 가지며, Access Token이 만료되었을 때 이를 갱신하기 위해 사용된다. Access Token은 짧은 유효 기간을 가지므로 유출 시 피해를 최소화할 수 있으며, Refresh Token을 통해 새로운 Access Token을 발급하는 방식으로 보안성을 유지하였다.

Refresh Token은 HttpOnly 쿠키에 저장하여 클라이언트 측 스크립트로부터의 접근을 차단함으로써 보안성을 강화하였다. 이러한 구조는 JWT의 무효화를 할 수 없는 문제를 어느 정도 해결하고, 사용자가 로그아웃하거나 보안상의 이유로 토큰을 무효화해야 하는 상황에서도 인증 상태를 안전하게 통제할 수 있도록 한다.


Authorization Code의 도입과 보안 강화

JWT와 Refresh Token을 사용하는 과정에서 Authorization Code 방식을 도입하여 보안성을 강화하였다. Authorization Code 방식은 OAuth 2.0 표준의 일환으로, 클라이언트가 인증 서버로부터 인증 코드를 받고 이를 사용해 토큰을 요청하는 방식이다. 이번 프로젝트에서는 OAuth 인증을 통해 서버가 토큰을 발급하여 클라이언트에 전달할 때, Access Token과 Refresh Token을 URL 쿼리 파라미터로 전달할 수밖에 없었다. 이러한 이유로 Authorization Code를 서버 전용으로 발급하여 보안을 강화하였다.

Authorization Code 도입 이유

  1. 토큰 유출 방지: 민감한 토큰 정보가 직접 클라이언트와 서버 간에 노출되지 않도록 하여 보안을 강화한다.
  2. 토큰 발급의 추가 인증: Refresh Token을 통한 토큰 갱신 시 추가적인 인증 과정을 요구함으로써 악의적인 사용자가 토큰을 탈취하더라도 이를 악용하지 못하게 한다.
  3. 클라이언트의 신뢰성 확보: 인증 코드를 통해 토큰을 요청함으로써 클라이언트의 신뢰성을 확인하고, 민감한 데이터를 다루는 애플리케이션에서 보안성을 높일 수 있다.

Refresh Token vs 세션 쿠키, 어느 것이 더 보안성이 높은가?

Refresh Token과 세션 쿠키 모두 쿠키로 전송되며 서버와의 통신에서 인증에 사용된다. 하지만 Refresh Token을 사용한 JWT 방식이 보안성 측면에서 더 우수한 몇 가지 이유가 있다.

  1. 무효화와 만료 관리: Access Token의 유효 기간을 짧게 설정하고, Refresh Token을 통해 새로운 Access Token을 발급받는 방식은 세션보다 보안 관리가 효율적이다.
  2. 세션의 중앙 관리 문제 해결: 세션은 서버에서 상태를 중앙 관리해야 하므로 서버 간 동기화가 필요하다. 반면 Refresh Token은 상태 저장 부담을 덜어주어 서버 확장이 용이하다.
  3. 로그아웃 및 세션 강제 종료: Refresh Token을 서버에서 관리하여 개별 사용자의 인증 상태를 효율적으로 갱신하고 통제할 수 있으며, 로그아웃 시 해당 Token을 삭제함으로써 Access Token의 갱신을 방지할 수 있다. 이는 세션 기반 인증에서처럼 중앙에서 모든 세션을 일괄적으로 관리하는 것은 아니지만, 개별 사용자의 인증 상태를 안전하게 제어할 수 있도록 한다.

세션과 JWT를 혼합하여 사용하는 경우

세션과 JWT를 혼합하여 사용하는 방식은 각 인증 방식의 장점을 결합하는 것이다. 예를 들어, Refresh Token을 서버의 세션에 저장하고, Access Token은 클라이언트에 전달하는 방식이 있다. 이 방식은 세션의 보안성과 JWT의 확장성을 결합한 절충안으로, 여러 시나리오에서 효과적인 접근 방법이 될 수 있다.

예를 들어, 높은 보안 수준이 요구되는 금융 시스템이나 의료 시스템에서는 사용자의 민감한 데이터와 관련된 보안성을 유지하면서도, 분산 환경에서 확장 가능한 구조가 필요하다. 이때, 다음과 같은 방식으로 두 인증 방법을 혼합하여 사용할 수 있다.

  1. 세션에서 Refresh Token 관리: Refresh Token을 서버에서 관리함으로써 각 사용자의 인증 상태를 중앙에서 관리할 수 있다. 이는 세션 방식과 비슷한 접근을 가능하게 한다. 즉, 여러 사용자의 인증 상태를 서버에서 중앙 집중적으로 제어할 수 있어 특정 시점에서 전체 사용자의 상태를 업데이트하거나 무효화하는 것이 수월해진다. 예를 들어, 시스템의 보안 문제로 모든 사용자의 인증을 무효화해야 할 경우, 서버에서 관리하고 있는 Refresh Token을 일괄 삭제함으로써 전체 사용자에 대한 제어가 가능하다.

  2. JWT의 Access Token으로 확장성 확보: Access Token은 클라이언트에 전달되어 클라이언트 측에서 관리되므로 각 요청에서 서버는 클라이언트가 전송한 JWT의 유효성을 검증하는 데 집중할 수 있다. 이 과정에서 서버의 부하가 감소하고, 분산 서버 환경에서 중앙 저장소 없이 독립적으로 인증을 처리할 수 있어 확장성이 높아진다.

  3. 보안성 향상과 실시간 제어의 결합: Refresh Token을 세션에서 관리함으로써 민감한 데이터에 대한 보안성을 높일 수 있으며, JWT로 각 요청을 처리하는 방식은 시스템 성능과 확장성에 이점을 준다. 예를 들어, 로그아웃 요청이 발생했을 때, 서버에서 해당 사용자의 Refresh Token을 무효화함으로써 Access Token이 갱신되지 않도록 할 수 있다. 이는 세션 방식의 실시간 제어와 유사한 효과를 제공하면서도 무상태성의 장점을 유지한다.

이러한 혼합 방식은 특히 여러 서버가 분산되어 작동하는 환경에서 효과적이다. 예를 들어, 금융 서비스나 사용자 인증이 필요한 대규모 웹 애플리케이션에서 이러한 방식이 유용할 수 있다. 금융 서비스의 경우, 많은 사용자들이 동시에 접근하기 때문에 서버의 확장성이 매우 중요하다. 이때 JWT의 무상태성과 Refresh Token의 중앙 집중적인 관리 방식은 각 사용자의 인증 상태를 효과적으로 처리하면서도 서버 부하를 줄이는 데 도움을 줄 수 있다. 또한, 의료 시스템과 같은 민감한 정보를 다루는 서비스에서도 세션과 JWT를 혼합하여 보안성과 확장성을 모두 만족시킬 수 있다. 이러한 시스템에서는 실시간 데이터의 안전한 관리와 다중 서버 간의 인증 상태 동기화가 필수적이기 때문에, 이러한 혼합 방식을 통해 안정성을 높이는 것이 가능하다.

세션 기반 인증이 중앙 집중적이고 보안 관리가 용이하다는 장점을 지니지만 확장성에서 제약을 받는 반면, JWT는 무상태성 덕분에 확장성이 뛰어나지만 보안적인 제어가 어렵다. 이를 보완하기 위해, 세션에서 Refresh Token을 관리함으로써 보안성을 강화하고, 클라이언트에서 JWT를 관리하여 확장성을 극대화하는 방식이 각자의 장점을 균형 있게 유지하는 것이다.


최근 많은 기업들이 JWT를 사용하는 이유

최근 많은 기업과 서비스가 세션 대신 JWT를 사용하는 이유는 확장성과 편리성 때문이라고 생각한다.

  • 확장성: JWT는 서버에 별도의 상태 저장소를 두지 않아도 되기 때문에 서버와 클라이언트 간의 상태 동기화 문제가 줄어든다. 이는 서비스의 관리와 유지보수를 더욱 간편하게 만들어준다.
  • 무상태성: 분산 서버 환경에서 JWT는 상태를 서버에 저장하지 않고 토큰을 통해 인증 정보를 전달하므로, 중앙에서 상태를 유지할 필요가 없어 서비스 확장이 용이하다.
  • 표준화된 통합: JWT는 다양한 클라이언트와 서버 간에 표준화된 인증 방식을 제공하므로, 여러 플랫폼 간의 상호 운영성이 뛰어나다. 특히 모바일 애플리케이션과 웹 애플리케이션 간의 인증 통합이 필요할 때 JWT의 유연성과 표준화된 형식은 매우 큰 장점이 된다.

이러한 이유로 JWT는 현대적인 웹 애플리케이션에서 많이 채택되고 있다. 특히, 마이크로서비스 아키텍처에서 개별 서비스가 독립적으로 인증을 수행해야 할 때 JWT의 무상태성과 유연성은 매우 유용하다. OAuth 2.0과 같은 표준 인증 방식과의 호환성도 높아 여러 인증 방식을 통합적으로 운영할 수 있는 장점이 있다.


어떤 방식을 선택해야 할까?

이번 프로젝트에서 JWT를 선택한 이유에 대해 정리해 보았다. 세션과 JWT 모두 장단점이 명확하며, 프로젝트의 특성과 요구 사항에 맞는 방식을 선택하는 것이 중요하다.

세션은 서버가 상태를 명확히 제어하고 관리하는 데 적합하지만, 확장성에 있어서는 제한적이라는 단점이 있다. 반면, JWT는 확장성 면에서 강력하지만, 보안성에서 추가적인 주의가 필요하다. 이를 해결하기 위해 Refresh Token과 Authorization Code를 도입하여 보안을 강화하였다.

이러한 경험을 통해 각 인증 방식의 장점을 잘 활용하고, 프로젝트의 상황에 맞는 최적의 솔루션을 찾는 것이 중요함을 깨달았다. 앞으로도 다양한 문제에서 어떤 방식이 올바른 선택인지 끊임없이 고민하고 그 결과를 공유하면서, 문제 해결 능력을 키움과 동시에 프로젝트의 완성도 또한 높여서 더욱 발전하는 개발자가 되고자 한다.

profile
다재다능한 Backend 개발자에 도전하는 개발자

0개의 댓글