Stateless Stateful Data Ownership
3줄 요약
- Stateless 설계는 서버가 아무 상태도 쓰지 않는다는 뜻이 아니라, 요청 사이에 유지해야 할 상태를 인스턴스 밖의 명확한 owner로 옮긴다는 뜻이다.
- Stateful 컴포넌트는 장애 때 복구 비용을 가진다. DB, Redis, broker, 검색 색인, session store는 각각 유실 가능성, 재생성 가능성, RTO/RPO가 다르다.
- Data Ownership은 “누가 읽는가”보다 “누가 최종 변경 권한을 갖는가”를 정하는 문제이며, 성능·정합성·장애 격리·운영 복잡도를 동시에 바꾼다.
핵심 정리
- Stateless Spring App은 수평 확장과 배포를 쉽게 하지만, 세션·장바구니·임시 주문·idempotency 상태를 어디에 둘지 결정해야 한다.
- 서버 메모리 상태는 빠르고 단순하지만 scale out, failover, rolling deploy에 약하다.
- session store는 인스턴스 독립성을 높이지만 Redis 장애, TTL, 직렬화, memory pressure를 운영해야 한다.
- sticky session은 빠른 완화책이지만 특정 인스턴스 장애와 배포에 취약하므로 장기 구조인지 임시 완화인지 구분해야 한다.
- Data Ownership은 공유 DB 접근을 줄이고 변경 책임을 명확히 하지만, 서비스 간 조회와 이벤트 동기화 복잡도를 만든다.
- 상태가 유실되어도 되는지, 재생성 가능한지, 사용자가 다시 입력해야 하는지에 따라 저장 위치가 달라진다.
판단 순서
- 상태의 종류를 분류한다.
- 인증 세션, 장바구니, 결제 진행 상태, idempotency key, cache, read model, 이벤트 offset을 구분한다.
- 최종 진실의 원천을 정한다.
- DB, session store, token, external provider, event log 중 어디가 owner인지 적는다.
- 인스턴스 로컬 상태를 제거하거나 의도적으로 제한한다.
- 로컬 cache, static map, ThreadLocal, in-memory lock은 장애와 배포 때 어떻게 사라지는지 검토한다.
- 장애 때 사용자 경험을 정한다.
- 로그아웃, 재시도, pending, 재조회, 기능 축소 중 무엇을 보여줄지 결정한다.
- 복구 비용을 계산한다.
- RTO, RPO, 재처리 가능 여부, session TTL, queue backlog, rebuild 시간을 확인한다.
- 서비스 경계를 고정한다.
- 어떤 서비스가 쓰기 권한을 갖고, 다른 서비스는 API나 event로만 상태를 받는지 정한다.
헷갈리는 지점
- Stateless를 “DB도 Redis도 쓰지 않는 구조”로 오해하기 쉽다.
- 핵심은 상태를 없애는 것이 아니라 인스턴스 로컬 상태를 줄이고 소유자를 명확히 하는 것이다.
- JWT를 쓰면 항상 stateless라고 생각하기 쉽다.
- 토큰 검증은 stateless해도 logout, revoke, 권한 변경 즉시 반영은 별도 상태를 요구할 수 있다.
- sticky session을 수평 확장이라고 착각하기 쉽다.
- 트래픽은 분산되지만 사용자가 특정 인스턴스에 묶여 장애와 배포 비용이 남는다.
- 여러 서비스가 같은 DB 테이블을 읽고 쓰면 빠르다고 느끼기 쉽다.
- 단기 구현은 빠르지만 owner가 흐려져 정합성, 배포, 장애 복구가 어려워진다.
상세본 구성
01. Stateless 서버와 Session 분리 상세.md: Spring 인스턴스에서 세션 상태를 분리하는 기준과 사용자 경험을 다룬다.
02. Stateful Component와 복구 비용 상세.md: 상태 저장 컴포넌트별 유실 가능성과 복구 비용을 계산한다.
03. Data Ownership과 Service Boundary 상세.md: 데이터 변경 권한과 서비스 경계를 설계 판단으로 고정한다.
04. Session Store와 Sticky Session 판단 상세.md: sticky session, session store, token 기반 방식을 비교한다.
05. 상태 관리 설계 실수 상세.md: 숨은 로컬 상태, 중복 owner, TTL 누락, 복구 불가능한 임시 상태를 점검한다.
확인 질문
- 확인 질문: 이 상태는 어느 인스턴스가 죽어도 유지되어야 하는가?
- 답변: 유지되어야 한다면 인스턴스 메모리가 아니라 session store, DB, event log처럼 owner와 복구 절차가 있는 곳에 둬야 한다.
- 확인 질문: 이 상태의 최종 변경 권한은 누가 갖는가?
- 답변: 여러 서비스가 직접 쓰면 충돌과 배포 결합이 생기므로 하나의 owner service나 명확한 transaction boundary가 필요하다.
- 확인 질문: stateful 컴포넌트를 도입하면 무엇이 늘어나는가?
- 답변: 성능이나 확장성은 좋아질 수 있지만 백업, failover, TTL, schema 변경, 관측 지표 같은 운영 복잡도가 늘어난다.