[Web] 인증을 위한 Session-Cookie 방식, 전체적인 그림 이해하기

Session-Cookie 방식

'Session-Cookie 방식'은 특별한 용어가 아니며, 이 글에서는 세션과 쿠키를 함께 사용하는 방식을 나타내는 표현으로 사용할 것이다.

HTTP 통신은

한 번 요청과 응답이 완료되면 연결을 끊는다. (Connectionless)
또한, 통신에 사용된 정보들은 즉시 휘발되기 때문에
처음 요청과 이후 요청은 어떠한 관계도 없다.
따라서 클라이언트의 이전 상태는 보존되지 않는다. (Stateless)
서버 입장에서는 매 요청마다 누가 어떤 요청을 보냈는지 알 수 없으며,
인증 관점에서는 어떤 사용자가 인증을 성공했는지 실패했는지 파악할 수 없다.
이로 인해 사용자는 페이지를 새로고침할 때마다 로그인을 새로 해야 하는 불편함이 발생한다.

이러한 불편함을 해결하기 위해 Session-Cookie 방식을 사용한다.

메커니즘은 간단하다.

Session은 정보를 서버 측에 저장하고,
Cookie는 정보를 클라이언트 측에 저장한다.

이 개념을 기반으로,

민감 정보는 서버에 안전하게 저장하고,
사용자의 식별값만 클라이언트 측에 저장한다.

이 식별값은 클라이언트와 서버간의 통신시 cookie 헤더에 포함되며,
서버는 세션 저장소에서 해당 식별값에 대응하는 값을 찾아 존재하면 인증을 통과시켜주는 방식이다.

여기서 식별값을 Session ID라고 하며, 이는 쿠키 형태로 저장된다.

Session ID의 발급과 사용

Session ID는 서버가 클라이언트에게 발급하는 임의의 값이다.
클라이언트로부터 최초 요청을 받으면 서버에서 Session ID를 생성하여 Response의 Set-Cookie 헤더에 담아 클라이언트에게 전달한다.

Set-Cookie: MY_SESSIONID=d5620830-df1e-4d87-96bf-934807f1bed4
Tomcat의 경우, JSESSIONID=xxxxxxxxx와 같은 형태로 Session ID를 생성해서 담는다.

이후의 모든 요청에서 클라이언트는 발급 받은 Session ID를 Request의 cookie 헤더에 넣어 서버에 전달한다.

Cookie: MY_SESSIONID=d5620830-df1e-4d87-96bf-934807f1bed4

인증을 위해 서버는 쿠키에 담긴 Session ID를 사용하여 세션 저장소에서 일치하는 세션이 있는지 확인하고, 세션이 존재하면 인증을 통과시킨다.

여기서 세션 저장소와 관련된 의문이 발생할 수 있다.
트래픽 증가로 서버를 확장해야 할 경우(scale-out), 세션 저장소를 어떻게 관리해야 할까?

Scale-out 시 세션 공유 문제

세션의 단점 중 하나는 scale-out 상황에서 각 서버들 간의 세션 싱크를 맞추기 위한 처리 비용이 들어간다는 것이다.

분산 시스템에서 세션 관리를 위한 3가지 방법

  1. 클라이언트마다 담당 처리 서버를 지정하는 방법 - Sticky Session
  2. 서버끼리 실시간으로 세션을 동기화하는 방법 - Session Clustering
  3. 외부 세션 저장소를 활용하는 방법 - Session Storage (Ex: Redis)

일반적으로 Redis 기반의 Session Storage 방식을 사용하며, 1개의 Master 서버와  N개의 Slave 서버로 구성한다. 이렇게 하면 세션 데이터를 안정적으로 보관하면서도 서버의 가용성을 향상시킬 수 있다. Master 서버는 Write 작업을 처리하고, Slave 서버는 Master 서버의 데이터를 복제하여 Read 작업을 처리하는 역할을 한다.

이제, 보안 측면에서 생각해보자.

보안 측면에서의 세션과 쿠키

네트워크를 통해 전송되는 모든 정보들은 중간에 '탈취'될 수 있음을 염두에 두어야 한다.

HTTPS를 적용하더라도 데이터 탈취는 가능하다. 다만, 안에 내용을 해독할 수 없을 뿐이다.

해커가 쿠키를 탈취하면 사용자의 민감 정보를 취득할 수 있다.
Session-Cookie의 경우, 해커가 탈취하더라도 Session ID만 취득이 가능하다.
Session ID는 그 자체만으로는 무의미하다.
따라서 Session-Cookie 방식이 쿠키'만' 사용하는 것보다는 '비교적' 안전하다고 볼 수 있다.

그러나, 해커가 Session ID를 탈취하면 사용자의 세션을 획득한 것과 동일한 효과를 낼 수 있다(세션 하이재킹 공격). 따라서 추가적인 보안 조치가 필요하다.

  1. HTTPS를 적용하여 데이터 전송 과정에서 중간자 공격을 방지하고, 탈취되더라도 내용을 해독하기 어렵게 만든다.
  2. 세션에 유효시간을 설정하여 일정 시간이 지나면 세션을 만료시켜 세션 하이재킹 공격을 예방한다.

이러한 조치들은 기본적인 수준이며, XSS(Cross-Site Scripting)나 CSRF(Cross-Site Request Forgery)와 같은 공격에 대비하기 위해서는 더 정교한 조치가 필요하다.

세션 사용이 무조건 더 좋은가?

쿠키가 유리한 경우도 있다.

세션은 서버에 저장되기 때문에,
무분별한 생성이나 큰 사이즈의 정보를 세션에 저장하면 서버에 부하를 일으킬 수 있다.
이때, 쿠키를 적절하게 사용하면 서버 부하를 낮출 수 있다.

예를 들어, 장바구니기능 구현 시 상품 정보를 쿠키에 저장하거나,
자동 로그인 설정과 같이 사용자 로그인 상태를 쿠키에 저장함으로써
서버 호출 횟수를 줄여 서버 부하를 낮출 수 있다.

세션과 쿠키의 속도 비교

상황에 따라 다르다.
어떻게 구현하고 사용하는지에 따라 성능이 크게 달라질 수 있다.

쿠키 사이즈가 얼마나 큰지?

  • 쿠키의 크기가 작을수록 네트워크 전송 및 처리 속도가 향상된다.
  • 쿠키 최대 사이즈는 기본적으로 4KB이다. (브라우저마다 다르다.)

세션 저장 위치가 메모리인지? 파일이나 데이터베이스인지?

  • 메모리에 저장한다면, 빠른 액세스가 가능하다.
    (그러나 메모리 제한 및 서버 재시작 시 세션 정보 소실 등을 고려해야 한다.)
  • 파일이나 데이터베이스에 저장한다면, I/O 작업으로 인해 Overhead가 발생할 수 있다.

사용자 수가 얼마나 많은지?

  • 사용자 수가 많을수록 서버 측에서 세션을 관리하는데 필요한 리소스가 증가한다.

서버 환경이 어떤지?

  • 서버 성능, 웹 서버 종류, 프로그래밍 언어 등에 따라서 성능이 달라진다.

일반적으로 세션은 서버 측에서 데이터를 관리하므로, 세션 관리 방식에 따라 성능이 달라진다.
쿠키는 클라이언트 측에서 저장되고 전송되기 때문에 더 가벼운 데이터를 전송할 때 유리하다.
두 방식의 장단점을 파악하고 사용 목적에 따라 적절히 조합하여 사용하는 것이 중요하다.


REFERENCE

LINKS TO THIS PAGE