04강
상태 없는 서버
서버가 아무것도 기억하지 않아야 서버를 마음대로 늘릴 수 있다
단계별로 보기
스페이스바로 재생/정지, 좌우 화살표로 단계 이동, R로 처음으로 돌아갑니다.
대기 중1 / 4 단계 — 로그인은 1번 서버로 갔다
사용자가 로그인합니다. 로드밸런서가 이 요청을 1번 서버로 보냈습니다. 1번 서버는 "이 사람은 로그인했다"는 사실을 알게 됩니다. 문제는 그 사실을 어디에 적어두느냐입니다.
이 강의를 마치면
- 서버가 기억을 자기 안에 들고 있을 때 생기는 문제를 설명한다.
- 상태를 밖으로 빼면 서버를 자유롭게 늘리고 줄일 수 있는 이유를 설명한다.
- 세션 고정(스티키 세션)이 왜 임시방편인지 근거를 든다.
- '상태 없음'이 상태가 사라진다는 뜻이 아니라 상태의 위치가 바뀐다는 뜻임을 구분한다.
담당자를 기억하는 창구의 문제
민원실에 창구가 하나뿐이라고 합시다. 어제 왔던 손님이 오늘 다시 오면 담당자가 "아, 그 건이요"라고 알아봅니다. 편합니다.
그런데 손님이 늘어 창구를 세 개로 늘렸습니다. 손님은 그날그날 비어 있는 창구로 갑니다. 어제 1번 창구에서 상담한 손님이 오늘 3번 창구로 가면 어떻게 될까요?
3번 담당자는 이 사람을 처음 봅니다. 어제 무슨 얘기를 했는지 모릅니다. 처음부터 다시 설명해야 합니다.
이것이 서버에서 매일 벌어지는 문제입니다.
웹에서 벌어지는 같은 일
로그인을 하면 서버는 "이 사람은 홍길동이고 로그인했다"는 사실을 기억해야 합니다. 요청을 보낼 때마다 아이디와 비밀번호를 다시 물어볼 수는 없으니까요.
서버가 이 기억을 자기 메모리 안에 넣어두면 이런 일이 벌어집니다.
로그인 요청 → 1번 서버로 감 → 1번 서버가 "홍길동 로그인함"을 기억
장바구니 조회 → 2번 서버로 감 → 2번 서버: "누구세요?" → 로그인 화면사용자에게는 로그인이 랜덤하게 풀리는 이상한 사이트로 보입니다. 그리고 이 버그는 서버가 한 대일 때는 절대 재현되지 않습니다. 그래서 개발자 노트북에서는 멀쩡합니다.
첫 번째 해결책과 그 함정
가장 먼저 떠오르는 해결책은 "그럼 이 손님은 항상 1번 창구로 보내자"입니다. 이걸 세션 고정(스티키 세션) 이라고 합니다. 실제로 동작하기는 합니다.
하지만 대가가 큽니다.
| 상황 | 벌어지는 일 |
|---|---|
| 1번 서버가 죽는다 | 1번에 붙어 있던 사용자 전원이 로그아웃 |
| 1번 서버만 인기 있는 사용자를 맡았다 | 1번만 과부하, 나머지는 놀아도 도와줄 수 없다 |
| 서버를 배포한다(재시작) | 그 서버의 기억이 전부 증발 |
| 서버를 줄이고 싶다 | 사용자를 옮길 방법이 없다 |
즉 세션 고정은 문제를 푼 게 아니라 문제를 미뤄둔 것입니다. 서버 한 대 한 대가 대체 불가능한 존재가 되어버립니다.
진짜 해결책 — 기억을 밖으로 뺀다
발상을 뒤집습니다. 창구 직원이 기억하지 말고, 뒤편에 공동 서류함을 두고 거기에 적어둡니다.
- 손님이 오면 번호표를 보고 서류함에서 그 사람 서류를 꺼내 봅니다.
- 상담이 끝나면 서류함에 다시 넣습니다.
- 어느 창구로 가든 같은 서류함을 보므로 똑같은 응대가 나옵니다.
이제 창구 직원은 서로 완전히 대체 가능해집니다. 한 명이 자리를 비워도, 새로 들어와도, 열 명으로 늘려도 아무 문제가 없습니다. 이것이 상태 없는 서버(stateless) 입니다.
오해 하나만 짚고 갑시다
"상태 없음"은 상태가 사라진다는 뜻이 아닙니다. 로그인 정보는 여전히 어딘가에 있어야 합니다. 달라진 건 위치입니다.
전: 상태가 서버 안에 있다 → 서버가 특별해진다
후: 상태가 서버 밖에 있다 → 서버가 일회용이 된다서버가 일회용이 되는 것이 목표입니다. 일회용이어야 마음대로 늘리고, 줄이고, 죽이고, 새 버전으로 갈아치울 수 있습니다. 앞으로 배울 수평 확장, 무중단 배포, 자동 복구가 전부 이 전제 위에 서 있습니다.
공짜는 아니다
당연히 대가가 있습니다. 서버 안의 메모리를 읽는 데는 사실상 시간이 안 들지만, 옆 기계에 있는 세션 저장소에 물어보려면 네트워크를 한 번 왕복해야 합니다. 요청마다 몇 밀리초가 더 듭니다.
그리고 이제 세션 저장소가 죽으면 전부 죽습니다. 문제를 없앤 게 아니라 한 곳으로 모은 것입니다. 대신 한 곳이니 그 한 곳만 제대로 지키면 됩니다. 여기저기 흩어진 기억을 지키는 것보다 훨씬 쉬운 일입니다.
직접 해보세요
아래 과제에는 서버 두 대가 있고 각자 로그인 정보를 자기 안에 들고 있습니다. 세션 저장소를 두고 두 서버가 모두 그것을 보게 만드세요.
이 강의가 단순화한 것
교육용 모형은 언제나 무언가를 생략합니다. 무엇을 생략했는지 아는 것도 학습의 일부입니다.
전제한 것
- 세션 저장소 조회는 2밀리초가 걸린다고 본다. 실제로는 네트워크 거리와 저장소 종류에 따라 크게 다르다.
- 세션 저장소 자체는 이 강의에서 죽지 않는다고 가정한다. 실제로는 이 저장소를 이중화해야 한다.
- 시뮬레이터는 '로그인이 풀린다'를 직접 재현하지 않는다. 화면에서 확인하는 것은 요청이 어느 경로로 흐르는가이다.
다루지 않은 것
- 토큰 기반 인증(JWT)처럼 세션 저장소 자체를 없애는 접근
- 세션 저장소의 복제와 장애 조치
- 세션 데이터의 만료(TTL)와 정리 정책
- 쿠키·세션 ID의 보안 처리
이제 직접 만들어 보세요
읽어서 아는 것과 만들어서 아는 것은 다릅니다. 컴포넌트를 배치하고 트래픽을 흘려서 실제로 동작하는지 확인해 보세요.
이 강의에 물어보기
하루 5번이 강의 본문만 근거로 답합니다. 강의에 없는 내용은 지어내지 않습니다.