ABOUT

성능과 운영 안정성을 함께 끌어올리는 개발자입니다.

92% Positional Error Reduction
79% p95 Latency Improvement
90%+ Long Tasks Reduction

2022.02 · 한국장학재단

우수 멘티

한국장학재단 사회 리더 대학생 멘토링 IT

2022.10 · 동작구청

우수 인재상

동작구청 우수 SW 인재

2025.05 · (주) 그랩

프로그래밍 우수상

(주) 그랩 우수 프로그램 개발

2025.05 · AWSKRUG

AWS한국사용자모임 발표

AI agent 스크립트 튜닝 관련 발표

ComputerScience

Development

Engineering

Trouble Shooting

GUESTBOOK

첫 마음부터
함께 나누는 온기

방명록 작성하러 가기

SUBSCRIBE

최신소식을
편하게 만나보세요.

세션 (Session)

도입

로그인 상태를 마법처럼 유지하는 기능이 아니라, 무상태인 HTTP 위에서 특정 브라우저와 서버 사이의 연속된 요청을 하나의 사용자 맥락으로 묶어 주는 데 있다

HTTP는 기본적으로 이전 요청을 기억하지 않는 stateless 프로토콜입니다. 따라서 로그인 상태, 장바구니, 다단계 입력, 권한 맥락 같은 정보는 별도의 메커니즘이 없으면 다음 요청으로 이어질 수 없습니다.

세션은 바로 이 문제를 해결하기 위한 구조입니다. 일반적으로 브라우저는 세션 ID를 쿠키로 들고 다니고, 서버는 그 ID에 연결된 상태를 저장소에서 조회해 “이 요청이 누구의 어떤 흐름인지”를 복원합니다. 그래서 세션을 이해한다는 것은 단순히 쿠키를 아는 것이 아니라, HTTP 무상태성 위에 상태를 어떻게 얹는지를 이해하는 일에 가깝습니다.

필요성

세션을 이해하면 로그인 유지, 권한 판별, 장바구니, 멀티스텝 폼, CSRF 방어, 웹 팜 확장 문제를 하나의 상태 관리 관점으로 묶어 볼 수 있다

웹 서비스는 거의 항상 “현재 이 요청을 보내는 사용자가 누구이며, 직전에 무엇을 했는가”를 어느 정도 기억해야 합니다. 로그인 상태를 매 요청마다 비밀번호로 다시 확인할 수는 없고, 장바구니나 권한 정보도 계속 이어져야 하기 때문입니다.

그래서 세션은 단순한 편의 기능이 아니라 인증 이후의 상태 유지 메커니즘입니다. 이 메커니즘을 잘못 설계하면 로그인은 되는데 요청마다 풀리거나, 서버를 두 대로 늘렸더니 상태가 엇갈리거나, 세션 탈취와 고정(session fixation) 같은 보안 문제가 바로 발생합니다.

세션을 꼭 이해해야 하는 대표 상황
  • 로그인 후 여러 요청 동안 사용자 맥락을 유지해야 할 때
  • 장바구니, 폼 입력 상태, 임시 권한 정보를 유지할 때
  • 서버를 여러 대 운영하면서 상태를 어디에 둘지 결정해야 할 때
  • 쿠키 보안 속성과 세션 탈취 방어를 설계해야 할 때
  • 로그아웃, 만료, 재로그인, 권한 변경 시 상태를 어떻게 끊을지 정해야 할 때

정의

웹 세션은 클라이언트가 보내는 여러 HTTP 요청을 하나의 연속된 사용자 상태로 다루기 위해 서버가 유지하는 상태 집합이며, 보통 클라이언트는 그 상태를 직접 들고 있지 않고 세션 ID만 전달한다

세션을 짧게 말하면, 특정 브라우저와 서버 사이의 연속된 상태입니다. 그러나 여기서 중요한 점은 클라이언트가 세션 내용을 전부 들고 다니는 것이 아니라, 일반적으로는 세션 ID라는 식별자만 쿠키 등에 저장해 요청마다 보내고, 서버가 그 ID를 보고 실제 상태를 꺼낸다는 점입니다.

즉, 세션 ≠ 쿠키입니다. 쿠키는 세션 ID를 운반하는 흔한 수단일 뿐이고, 실제 세션 데이터는 서버 메모리, 분산 캐시, 데이터베이스 같은 저장소에 둘 수 있습니다.

핵심 문장
세션은 서버 쪽 상태이고, 쿠키는 그 상태를 가리키는 ID를 전달하는 가장 흔한 운반 수단입니다. 쿠키 자체가 곧 세션은 아닙니다.

핵심 원리

세션 시스템의 실제 동작은 세션 ID 생성 → 클라이언트 전달 → 요청마다 재전송 → 서버 저장소 조회 → 갱신 또는 만료라는 생명주기 전체로 봐야 이해가 된다

세션은 단순히 로그인 한 번으로 끝나는 구조가 아닙니다. 서버는 세션 ID를 만들고, 이를 클라이언트에 넘기고, 이후 모든 요청에서 다시 받아야 하며, 일정 시간 사용이 없으면 만료시키거나, 로그아웃/권한 변경 시 무효화해야 합니다.

따라서 세션 설계는 “로그인 상태를 유지한다”보다 상태 생성, 유지, 갱신, 재발급, 종료의 전체 생명주기를 다루는 문제입니다. 보안과 확장성 이슈도 대부분 이 생명주기 안에서 발생합니다.

세션 기본 흐름
1) 사용자가 인증한다
2) 서버가 새 세션 ID를 생성한다
3) 서버가 세션 저장소에 상태를 기록한다
4) 서버가 Set-Cookie로 세션 ID를 클라이언트에 보낸다
5) 클라이언트는 이후 요청마다 Cookie 헤더로 세션 ID를 보낸다
6) 서버는 세션 ID로 상태를 조회한다
7) 만료 / 로그아웃 / 재발급 시 세션을 갱신하거나 종료한다

기본 구조

세션을 제대로 설계하려면 HTTP 무상태성, 세션 ID, 쿠키, 서버 저장소, 타임아웃, 재발급 정책을 각각 다른 책임으로 분리해서 봐야 한다
구성 요소 역할 실무 포인트
HTTP 기본적으로 stateless 상태 유지 기능을 직접 제공하지 않음
Session ID 클라이언트와 서버 상태를 연결하는 식별자 충분히 랜덤하고 예측 불가능해야 함
Cookie 세션 ID를 매 요청에 싣는 가장 흔한 수단 Secure / HttpOnly / SameSite 설정이 중요
Session Store 실제 세션 데이터를 저장 로컬 메모리, 분산 캐시, DB 등 선택 가능
Timeout 세션 유효 시간 제어 idle timeout, absolute timeout을 구분해서 설계
Regeneration / Invalidation 재발급과 무효화 로그인, 권한 변경, 로그아웃 시 특히 중요
세션 구현에서 가장 중요한 첫 번째 감각은 세션 상태를 쿠키에 통째로 넣는 것이 아니라, 의미 없는 세션 ID만 쿠키에 넣고 실제 상태는 서버 쪽에 두는 구조를 기본으로 보는 것이다

실무에서 가장 흔한 세션 구현은 세션 ID를 쿠키로 전달하는 방식입니다. 서버는 브라우저에 Set-Cookie 헤더로 세션 ID를 보내고, 브라우저는 이후 같은 사이트 요청마다 그 값을 Cookie 헤더에 실어 다시 보냅니다.

여기서 중요한 보안 원칙이 있습니다. 세션 ID는 의미 없는 식별자여야 하며, 사용자 ID나 권한, 이메일 같은 민감 정보가 직접 들어가면 안 됩니다. OWASP도 세션 ID는 CSPRNG로 생성되어야 하고, 최소 64비트 이상의 엔트로피를 가져야 하며, 그 자체로 의미를 가지지 않아야 한다고 권고합니다.

HTTP/1.1 200 OK
Set-Cookie: sid=V7a9xQm2kP4zN8u1; Path=/; HttpOnly; Secure; SameSite=Lax
세션 저장소 예시
sid=V7a9xQm2kP4zN8u1
→ {
     userId: 123,
     role: "USER",
     cartId: "cart-88",
     lastAccessAt: "...",
     expiresAt: "..."
   }

세션 ID를 URL 파라미터로 붙여 전달하는 방식은 로그, 브라우저 히스토리, 리퍼러 등으로 노출될 위험이 커서 일반적으로 바람직하지 않습니다. 세션 ID를 쿠키로 관리하는 쪽이 훨씬 일반적이고 안전한 선택입니다.

패턴 2. 서버 저장소와 분산 세션

단일 서버에서는 메모리 세션이 간단하지만, 서버가 여러 대로 늘어나는 순간 세션은 저장 위치의 문제가 되고, 그때는 sticky session 또는 shared session store 중 하나를 분명히 선택해야 한다

세션 저장소는 크게 두 방향으로 나눌 수 있습니다. 첫째는 애플리케이션 서버 메모리에 직접 두는 방식이고, 둘째는 Redis 같은 분산 캐시나 별도 저장소에 두는 방식입니다.

메모리 세션은 단순하고 빠르지만, 여러 서버 인스턴스를 운영할 때는 문제가 생깁니다. 사용자의 다음 요청이 다른 서버로 가면 세션을 찾지 못할 수 있기 때문입니다. 이 경우에는 sticky session(session affinity)로 같은 사용자를 같은 서버로 붙이거나, 아예 분산 세션 저장소를 두고 모든 앱 서버가 같은 세션 데이터를 보게 해야 합니다.

방식 장점 단점 언제 적합한가
로컬 메모리 세션 단순하고 빠름 멀티 인스턴스에서 일관성 문제가 생김 단일 서버, 개발 환경, 매우 단순한 구조
Sticky Session 기존 코드 변경이 적음 로드밸런서 의존성이 커지고 유연성이 떨어짐 짧은 전환기 또는 특정 제약 환경
Distributed Session Store 여러 앱 서버가 같은 세션을 공유 가능 별도 저장소와 네트워크 홉이 필요함 일반적인 멀티 서버 운영 환경

대표적인 서버 프레임워크 문서도 세션 상태를 cache-backed ephemeral data로 설명합니다. 즉, 세션은 영구 정답 저장소가 아니라 요청 간 상태를 잠시 유지하는 용도에 가깝고, 중요한 비즈니스 데이터는 사용자 DB 같은 영구 저장소를 source of truth로 두는 편이 맞습니다.

패턴 3. 세션 수명 주기와 보안

세션 보안의 핵심은 쿠키 플래그 몇 개를 켜는 데서 끝나지 않고, 세션 ID의 생성·전송·재발급·만료·무효화 전 과정을 공격 모델 기준으로 설계하는 데 있다

세션은 인증이 끝난 뒤의 사용자 상태를 대표하므로, 공격자에게 세션 ID가 노출되면 곧바로 계정 탈취로 이어질 수 있습니다. OWASP는 세션 ID 탈취, 예측, 고정(fixation), 브루트포스가 세션 하이재킹으로 이어질 수 있다고 설명합니다.

그래서 세션 보안은 다음 세 가지 축으로 보는 편이 좋습니다. 첫째, 세션 ID 자체가 충분히 랜덤해야 합니다. 둘째, 전송과 접근 경로가 제한되어야 합니다. 셋째, 중요 이벤트에서 세션 ID를 재발급해야 합니다.

꼭 챙겨야 할 쿠키 속성
  • Secure : HTTPS 연결에서만 전송되도록 제한
  • HttpOnly : JavaScript에서 접근하지 못하게 제한
  • SameSite : cross-site 요청에서의 전송을 제한해 CSRF를 부분적으로 완화
  • Path / Domain : 가능한 한 가장 좁은 범위로 제한
  1. 로그인 성공 시 새 세션 ID를 발급한다.
  2. 권한 상승, 비밀번호 변경 같은 민감한 이벤트 후에도 세션을 재발급한다.
  3. 로그아웃 시 세션 저장소의 상태를 무효화하고, 클라이언트 쿠키도 제거한다.
  4. idle timeout과 absolute timeout을 함께 설계한다.
  5. 세션 ID는 절대 URL에 실어 나르지 않는다.

특히 session fixation 방어는 실무에서 자주 놓칩니다. 로그인 전에 이미 존재하던 세션 ID를 로그인 후에도 그대로 쓰면, 공격자가 미리 고정한 ID를 통해 피해자 세션을 탈취할 수 있기 때문입니다. 그래서 MDN과 OWASP 모두 로그인 시점의 새 세션 ID 재발급을 중요한 방어책으로 설명합니다.

세션 관리에서 자주 헷갈리는 포인트는 세션이라는 개념과 세션 쿠키라는 쿠키 수명 정책이 정확히 같은 말이 아니라는 점이다

RFC 6265 기준으로 쿠키에 Max-AgeExpires가 없으면, 사용자 에이전트는 그 쿠키를 보통 “현재 세션이 끝날 때까지” 유지합니다. 이것이 흔히 말하는 세션 쿠키입니다.

반대로 Max-AgeExpires를 주면 영속 쿠키가 됩니다. 따라서 “세션을 구현한다”와 “세션 쿠키를 쓴다”는 겹치지만 완전히 같은 말은 아닙니다. 서버 쪽 세션 상태를 유지하면서도, 그 식별자를 영속 쿠키로 둘지 세션 쿠키로 둘지는 별도의 정책 문제입니다.

# 세션 쿠키 예시
Set-Cookie: sid=abc123; Path=/; HttpOnly; Secure; SameSite=Lax

# 영속 쿠키 예시
Set-Cookie: sid=abc123; Max-Age=1800; Path=/; HttpOnly; Secure; SameSite=Lax

한계와 주의점

세션은 구현이 직관적이라는 장점이 있지만, 상태가 서버 쪽에 남기 때문에 무상태 아키텍처보다 수평 확장과 장애 복구, 운영 비용 측면에서 더 많은 고려가 필요하다

세션은 이해하기 쉽고 구현도 편한 편이지만, 서버가 상태를 기억해야 하므로 완전한 stateless 구조보다 운영 부담이 커집니다. 세션 저장소가 장애를 일으키면 인증 이후의 사용자 흐름 전체가 흔들릴 수 있고, 멀티 서버 환경에서는 affinity나 distributed store가 필수가 되기도 합니다.

또한 세션에 너무 많은 데이터를 넣으면 저장소 부하와 직렬화 비용이 커지고, 세션을 영구 저장소처럼 쓰기 시작하면 만료와 무효화 정책이 어색해집니다. 결국 세션은 “편리한 상태 유지 메커니즘”이지 “모든 사용자 데이터를 넣는 곳”은 아닙니다.

실무에서 특히 주의할 지점
  • 세션 저장소 장애가 곧 로그인 상태 장애로 이어질 수 있음
  • 웹 팜 환경에서는 local memory session만으로는 부족할 수 있음
  • 세션에 영구 비즈니스 데이터를 넣으면 경계가 흐려짐
  • 세션 보안을 쿠키 플래그만으로 해결했다고 오해하기 쉬움

자주 하는 실수

세션 설계에서 가장 흔한 오답은 세션과 쿠키를 같은 것으로 보거나, 세션 ID를 안전한 랜덤 식별자가 아니라 정보가 담긴 토큰처럼 다루는 데서 시작된다
  • 세션 = 쿠키라고 생각함
  • 세션 ID 안에 사용자 정보나 권한 정보를 직접 넣음
  • Secure, HttpOnly, SameSite를 설정하지 않음
  • 로그인 후 세션 ID를 재발급하지 않아 fixation에 취약해짐
  • 세션 ID를 URL 파라미터로 노출함
  • 멀티 서버 환경에서 local memory session만 사용하고 분산 구조를 무시함
  • 중요한 영구 데이터를 세션에만 저장함
  • idle timeout과 absolute timeout을 구분하지 않음

실무 루틴

세션을 설계할 때는 로그인 유지부터 생각하기보다, 어떤 데이터를 세션에 넣을지·어디에 저장할지·언제 끊을지·어떤 이벤트에서 재발급할지를 먼저 정하는 순서가 맞다
  1. 세션에 정말 필요한 최소 상태만 넣는다.
  2. 클라이언트에는 가능하면 세션 ID만 전달한다.
  3. 세션 저장소가 local memory인지 distributed store인지 먼저 정한다.
  4. 로그인 성공 시 세션 ID를 새로 발급한다.
  5. Secure, HttpOnly, SameSite, Path, Domain을 함께 설계한다.
  6. idle timeout, absolute timeout, logout invalidation을 별도로 정한다.
  7. 멀티 서버라면 sticky session 또는 shared session store 전략을 명확히 고른다.

디버깅

세션 문제를 디버깅할 때는 “로그인이 풀린다”라고 뭉뚱그리지 말고, 쿠키가 안 오는지·세션 저장소를 못 찾는지·만료됐는지·다른 서버로 갔는지를 먼저 분리해야 한다
1
응답에 Set-Cookie가 제대로 내려갔는지 먼저 확인한다.
2
다음 요청에 Cookie 헤더로 세션 ID가 실제로 돌아오는지 본다.
3
세션 저장소에서 해당 ID를 찾을 수 있는지, 이미 만료되었는지, 명시적으로 무효화되었는지 확인한다.
4
멀티 서버 환경이면 요청이 같은 서버로만 가는지, 아니면 shared session store를 제대로 보는지 점검한다.
5
Secure, SameSite, Domain, Path 때문에 브라우저가 쿠키를 안 보내는 것은 아닌지도 함께 본다.
세션 장애를 볼 때 가장 먼저 나눌 것
- 쿠키 발급 실패인가?
- 쿠키 재전송 실패인가?
- 세션 저장소 조회 실패인가?
- 세션 만료인가?
- 세션 재발급/무효화 로직 문제인가?
- 멀티 서버 라우팅 문제인가?

요약

세션의 본질은 HTTP 무상태성 위에서 특정 브라우저와 서버 사이의 연속된 상태를 유지하는 것이며, 이를 안전하게 운영하려면 세션 ID·쿠키·저장소·만료·재발급·분산 환경 설계를 하나의 생명주기로 함께 봐야 한다
  • ✅ 세션은 서버가 유지하는 사용자별 상태 집합이다.
  • ✅ HTTP는 stateless이므로 세션 같은 별도 메커니즘이 필요하다.
  • ✅ 보통 클라이언트는 세션 상태 전체가 아니라 세션 ID만 쿠키로 전달한다.
  • ✅ 세션 ID는 의미 없는 랜덤 식별자여야 하며 충분한 엔트로피가 필요하다.
  • Secure, HttpOnly, SameSite는 세션 쿠키 보안의 기본이다.
  • ✅ 로그인이나 권한 변경 후에는 세션 ID를 재발급해야 fixation 공격을 줄일 수 있다.
  • ✅ 멀티 서버 환경에서는 sticky session 또는 distributed session store 전략을 명확히 골라야 한다.
  • ✅ 세션은 영구 정답 저장소가 아니라 ephemeral state에 더 가깝다.
728x90