세션(Session)에 대해 알아보자

2023. 1. 31. 19:51

지난번에 쿠키(Cookie)에 대해서 알아보았다. 이번에는 쿠키와 함께 자주 등장하는 세션에 대해서 알아보자

 

1. 세션(Session)이란?

일정 시간 동안 같은 사용자(브라우저)로부터 들어오는 일련의 요구를 하나의 상태로 보고, 그 상태를 유지시키는 기술이다.

여기서 일정 시간은 방문자가 웹 브라우저를 통해 웹 서버에 접속한 시점부터 웹 브라우저를 종료하여 연결을 끝내는 시점을 말한다.

즉, 방문자가 웹 서버에 접속해 있는 상태를 하나의 단위로 보고 그것을 세션이라고 한다.

 

앞서 살펴본 쿠키는 클라이언트 측의 컴퓨터에 모든 데이터를 저장한다.

하지만 세션은 서비스가 돌아가는 서버 측에 데이터를 저장하고, 세션의 키값만을 클라이언트 측에 남겨둔다.

브라우저는 필요할 때마다 이 키값을 이용하여 서버에 저장된 데이터를 사용하게 된다.

 

이러한 세션은 보안에 취약한 쿠키를 보완해주는 역할을 하고 있다.

1.1 세션 특징

  • 웹 서버에 웹 컨테이너의 상태를 유지하기 위한 정보를 저장한다.
  • 웹 서버의 저장되는 쿠키(=세션 쿠키)
  • 브라우저를 닫거나, 서버에서 세션을 삭제했을 때만 삭제가 되므로, 쿠키보다 비교적 보안이 좋다.
  • 저장 데이터에 제한이 없다. (서버 용량이 허용하는 한에서)
  • 각 클라이언트에 고유 Session ID를 부여한다. Session ID로 클라이언트를 구분해 각 요구에 맞는 서비스를 제공
  • 사용자가 많아질수록 서버 메모리를 많이 차지하게 된다. 즉 동접자 수가 많은 웹 사이트인 경우 서버에 과부하를 주게 되므로 성능 저하의 요인이 된다.

1.2 세션의 동작 순서

  • 클라이언트가 페이지에 요청한다. (사용자가 웹사이트에 접근)
  • 서버는 접근한 클라이언트의 Request-Header 필드인 Cookie를 확인하여, 클라이언트가 해당 session-id를 보냈는지 확인한다.
  • session-id가 존재하지 않는다면 서버는 session-id를 생성해 클라이언트에게 돌려준다.
  • 서버에서 클라이언트로 돌려준 session-id를 쿠키를 사용해 서버에 저장한다.
  • 클라이언트는 재접속 시, 이 쿠키를 이용해 session-id 값을 서버에 전달
  • 사용 예시
    • 화면을 이동해도 로그인이 풀리지 않고 로그아웃하기 전까지 유지

출처: https://dongsik93.github.io/til/2020/01/08/til-authorization(1)/

2. 쿠키와 세션의 차이

  • 저장 위치
    • 쿠키 : 클라이언트
    • 세션 : 서버
  • 보안
    • 쿠키 : 클라이언트에 저장되므로 보안에 취약하다.
    • 세션 : 쿠키를 이용해 Session ID만 저장하고 이 값으로 구분해서 서버에서 처리하므로 비교적 보안성이 좋다.
  • 라이프사이클
    • 쿠키 : 만료시간에 따라 브라우저를 종료해도 계속해서 남아 있을 수 있다.
    • 세션 : 만료시간을 정할 수 있지만 브라우저가 종료되면 만료시간에 상관없이 삭제된다.
  • 속도
    • 쿠키 : 클라이언트에 저장되어서 서버에 요청 시 빠르다.
    • 세션 : 실제 저장된 정보가 서버에 있으므로 서버의 처리가 필요해 쿠키보다 느리다.

보안을 위해서 세션을 사용하면 좋은데 왜 쿠키를 사용할까?

 

세션이 쿠키에 비해 보안이 높은 편이나 쿠키를 사용하는 이유는 세션은 서버에 저장되고, 서버의 자원을 사용하기에 서버 자원에 한계가 있고, 속도가 느려질 수 있기 때문에 자원관리 차원에서 쿠키와 세션을 적절한 요소 및 기능에 병행 사용하여 서버 자원의 낭비를 방지하며 웹사이트의 속도를 높일 수 있다.

3. 세션 불일치 문제

세션 불일치 문제는 단일 서버 환경에서는 발생하지 않으므로 따로 걱정하지 않아도 된다.

하지만 서비스가 커짐에 따라 한대의 서버로 운영하는것이 불가능해졌다고 가정해보자. 그래서 서버를 업그레이드 해야되는데 다음과 같이 두가지 방식이 존재한다.

 

첫번째 방법은 scale-up 방식이다.

서버 자체 성능을 늘려 부하를 견딜수 있게 하는 방식이지만, 여전히 서버 한 대에 모든 트래픽이 집중되므로 만일에 서버 장애가 생길시 서버가 복구될 때까지 서비스를 중단해야 하는 상황이 발생할 수 있는 위험이 있다. 사용하려던 서비스가 중단된다면 엄청난 비즈니스 손실(수익 손실)이 생길 수 있다.

 

두번째 방법은 scale-out 방식이다.

서버를 여러대로 늘려서 각 서버에 로드밸런싱으로 트래픽을 분산하게 한다. 그래서 서버 한대에 장애가 생겨도 다른 서버는 살아있으니 서비스 문제가 생기지 않는다.

그러나 이때 서비스 이용에 발생하는 커다란 문제점이 있는데 바로 데이터 정합성, 세션 불일치 문제다. 

왜냐하면 여러 대의 서버가 각각 세션 저장소를 독립적으로 갖기 때문에 데이터 불일치 문제가 발생하기 때문이다.

Scale-Up : 서버의 스펙을 늘리는 방식. (서버의 메모리카드나 cpu 부품을 업그레이드하여 부하를 최소화)
Scale-Out : 서버의 갯수를 늘리는 방식. (여러대의 서버를 두어 부하를 분산)

로드밸런싱 이란?
여러 대의 서버를 두고 트래픽을 분산처리하여 서버의 로드율 증가, 부하량, 속도저하 등을 해결해주는 서비스.
팀의 업무를 팀장이 팀원들에게 배분하는것과 같은 이치이다.

 

예를 들어, 우리가 서버를 수평적으로 확장하기 위해 A, B, C 총 3대의 서버를 설치했다고 가정하자. 이때, 로드 밸런서는 유저의 요청이 들어올 때 마다 A → B → C → A … 순서대로 요청을 분산한다고 가정하자. (이를 라운드로빈 방식이라고 한다.)

가운데 위치한 그림은 로드밸런서이다.

이런 환경에서 위와 같이 특정 유저의 로그인 요청이 A 서버로 전달되었다고 하자. 유저의 세션 정보는 A서버에 생성된다. 그리고 직후에 해당 유저의 글 작성 요청이 B 서버로 전달되었다고 하자. 하지만 B 서버에는 유저의 세션 정보가 존재하지 않는다. 따라서 유저의 요청이 제대로 처리되지 않을 것 이다. 이런 문제를 세션 불일치(정합성) 문제라고 한다.

세션 불일치 문제를 해결하기 위해서는 3가지 해결 방법이 존재한다.

3.1 Sticky Session

첫번째로 Sticky Session 방식이다. 클라이언트의 요청이 항상 해당 클라이언트의 세션이 저장된 서버로 향하는 방식을 말한다. 세션 정보가 없는 유저가 요청을 한 경우 로드밸런서의 기본 알고리즘대로 요청을 전달한다. 이때 이 요청으로 인해 세션이 생성된 경우 해당 유저의 요청은 해당 서버로 고정된다. 요청을 특정 서버로 고정시키는 방법은 쿠키를 통해 판단하거나, 클라이언트의 IP를 확인하여 판단하는 방법이 있다.

 

이 방식은 단순하나 크게 두가지 문제점을 가지고 있다.

 

첫번째는 특정 서버에 트래픽이 집중될 위험성을 가지고 있다.

로드밸런서는 여러 서버에 요청을 적절히 분산해서 부하가 특정 서버에 몰리지 않기 위해 사용한다. 하지만 Sticky Session으로 인해 한 서버에 부하가 몰리면 로드밸런싱의 원래 목적을 달성할 수 없다.

 

두번째는 하나의 서버에 장애가 발생하면, 해당 서버가 들고 있던 세션 정보는 모두 유실되어 해당 서버에 고정된 유저는 다시 로그인해야하는 문제점을 가지고 있다. 즉, 가용성 문제를 가지고 있다.

 

이처럼 Sticky session에서는 사용자와 세션 정보를 갖고 있는 서버를 1:1로 매핑해주어 세션 불일치를 해결해지만, 문제가 발생하면 Scale out의 장점인 트래픽 분산과 가용성을 제대로 활용하지 못하게 되는 경우가 발생할 수 있게 된다.

3.2 Session Clustering

Session Clustering 방식은 특정 서버에서 세션이 생성될 때 다른 서버로 세션을 전파하여 복제하는 방식으로 세션 불일치 이슈를 해결한다. 이런 방식으로 Sticky Session 방식에서 발생한 한 서버에 부하가 몰리는 문제와, 가용성 문제를 해결할 수 있다.

 

하지만, 대규모 클러스터에서는 Session Clustering 방식도 많은 문제점을 가지고 있다.

첫번째로 비효율적인 메모리 관리 문제이다. 세션을 모든 서버가 복제하여 들고있기 때문에 효율적인 메모리 관리를 할 수 없어진다.

 

두번째로 세션을 생성할 때 마다 데이터를 전파하고 복제하는 과정에서 Sticky Session 방식에 비해 많은 네트워크 트래픽을 사용한다는 문제점이다.

 

세번째로 세션을 전파하고 복제하는 과정에서 시간차로 인하여 세션 불일치 이슈가 발생할 위험성이 존재한다. 예를 들어 A서버에서 생성된 세션이 B서버로는 전파가 되었지만, 아직 C서버로 전파가 되지 않았을 찰나에 클라이언트가 C서버로 요청할 수도 있는 것 이다.

 

이처럼 세션 클러스터링은 sticky 세션의 문제점인 특정 서버에만 트래픽이 몰리는 문제를 해결할 수 있었다.

그러나 세션 클러스터링이나 sticky 세션이나 서버가 세션이라는 상태(데이터)를 가진다는 것은 변함이 없다는 특징이 있다

 "서버가 상태(데이터)를 가진다"라는 의미는 Scale out 방식으로 확장을 했을 때 서버가 가지고 있는 데이터를 확장하는 서버에도 똑같이 맞춰줘야 한다는 뜻이다. 이는 곧 오버헤드로 이어진다.

 

정리하면, 세션 클러스터링은 정합성 이슈를 해결할 수 있지만, 성능적인 한계가 존재한다고 말 할 수 있다.

3.3 세션 스토리지 분리

마지막 방식은 세션 스토리지를 외부 서버로 분리하는 방식이다. 이때 외부 세션 스토리지 서버는 일반적인 Disk-Based DB (Mysql, PostgreSQL, MongoDB 등) 를 사용할수도 있지만, 입출력이 잦은 세션 특성 상 I/O 성능이 느린 데이터베이스는 사용하기 적절하지 않다.

따라서 세션을 저장하는 저장소로는 In-Memory DB를 사용하는 것이 일반적이다. Disk-Based DB는 데이터의 영속성을 위해 사용하지만, 세션 정보는 영속성을 보장할 필요가 없다. 세션은 개발자가 설정해놓은 기간이 지나면 소멸된다. 또한 세션은 데이터가 유실된다 하더라도 그 피해가 다른 유형의 데이터에 비해 적다.

그렇다면 In-Memory DB 중 어떤 DBMS를 사용하는 것이 좋을까? 세션 데이터는 Key-Value 로 구성되어 있다. 따라서 세션을 저장할때는 대표적인 Key-Value DB 인 RedisMemcached를 사용한다.

세션 스토리지를 분리하면 Sticky Session 의 문제인 부하 몰림 문제와 가용성 문제를 해결할 수 있다. 또한 Session Clustering 의 비효율적인 메모리 관리 문제, 네트워크 트래픽 증가 문제, 시간차로 인한 세션 불일치 문제도 모두 해결된다.

하지만 이런 세션 스토리지 분리 방식도 단점이 존재한다. 하나뿐인 세션 스토리지에 장애가 발생하면, 모든 서버가 세션 데이터를 정상적으로 사용할 수 없게 된다. 이 문제는 세션 스토리지를 여러개로 구성하는 방식으로 해결한다고 한다.

 

 

 

 

 

 

 

 

출처 : 

반응형