무상태

Stateless

개념

서버가 요청 사이에 아무것도 기억하지 않고 필요한 정보를 요청마다 함께 받는 설계로, 서버를 늘리고 줄이기 쉽게 만듭니다.

등장 배경

서버가 한 대였을 때는 사용자를 기억해 두는 것이 가장 편한 방법이었습니다. 누군가 로그인하면 서버가 자기 메모리에 이 접속이 누구인지를 적어 두고, 다음 요청이 오면 그 기록을 꺼내 씁니다. 요청에는 짧은 열쇠 하나만 실려 오고 나머지는 서버가 알고 있으니 주고받는 양도 적습니다.

접속이 늘어 서버를 두 대로 늘리는 순간 이 방식이 깨집니다. 로그인은 1번 서버가 받아 기록을 남겼는데 다음 요청은 2번 서버로 갑니다. 2번은 이 사람이 누구인지 모르니 로그인하라고 답합니다. 사용자 쪽에서 보이는 증상은 로그인은 되는데 새로고침하면 로그아웃되고, 다시 로그인하면 또 되는 상태입니다. 절반의 요청만 실패하니 재현도 잘 안 되고, 담당자는 로그인 코드를 몇 번씩 들여다보게 됩니다.

임시로 막는 방법은 있었습니다. 앞단이 같은 사용자를 늘 같은 서버로 보내도록 고정하는 것입니다. 그러면 그 서버가 죽는 순간 그 사용자들만 전부 로그아웃되고, 서버를 한 대 늘려도 이미 붙어 있는 사용자는 옮겨 가지 않아 부하가 고르게 퍼지지 않습니다. 무상태는 반대 방향으로 풉니다. 서버가 기억하지 않게 만들어, 어느 서버가 받아도 같은 답이 나오게 합니다.

작동 방식

서버가 들고 있던 기억을 밖으로 옮기는 것이 전부입니다. 옮길 곳은 둘이고, 옮긴 뒤 서버는 요청을 처리하고 아무것도 남기지 않습니다.

  1. 요청 안에 담습니다. 서명된 토큰으로 인증 정보를 주고받는 규격인 JWT가 대표적입니다. 누구인지와 언제까지 유효한지를 적은 쪽지에 서명을 붙여 사용자에게 주고, 사용자는 요청마다 그것을 함께 보냅니다. 서버는 서명만 확인하면 되니 어디에도 물어보지 않습니다.
  2. 공용 저장소에 둡니다. 모든 서버가 함께 보는 데이터베이스나 빠른 임시 저장소에 기록을 넣습니다. 서버는 요청을 받을 때마다 그곳을 조회합니다. 기억은 여전히 있지만 서버 바깥에 있어서 어느 서버가 받아도 같은 값을 봅니다.
  3. 파일도 같이 옮깁니다. 업로드받은 파일을 그 서버의 디스크에 저장하면 다음 요청이 다른 서버로 갔을 때 그 파일이 없습니다. 모든 서버가 접근하는 공용 저장소에 올리고 주소만 기록합니다.
  4. 처리 뒤에 흔적을 남기지 않습니다. 계산 중간값을 서버 변수에 담아 두고 다음 요청에서 쓰겠다는 설계가 남아 있으면, 그 한 곳 때문에 전체가 무상태가 아니게 됩니다.

다 됐는지 확인하는 방법은 간단합니다. 서버 한 대를 예고 없이 끄고, 그 순간 요청을 받고 있던 사용자들이 오류를 보는지 확인합니다. 아무도 눈치채지 못하면 무상태입니다.

쓰이는 곳

서버 대수를 자유롭게 바꿀 수 있어야 하는 자리에서 전부 전제로 깔립니다.

첫째는 수평 확장입니다. 서버 대수를 늘려 부하를 감당하는 방식인데, 새로 띄운 서버가 아무 기억 없이도 곧바로 요청을 받을 수 있어야 이 방식이 성립합니다. 부하에 따라 자동으로 대수를 늘리고 줄이는 오토스케일링은 여기서 한 걸음 더 나갑니다. 줄일 때 서버를 그냥 없애 버리기 때문에, 그 서버만 알고 있던 것이 있으면 그것과 함께 사라집니다.

둘째는 앞단의 분배입니다. 요청을 여러 서버에 나눠 보내는 로드 밸런서가 아무 제약 없이 고르게 뿌릴 수 있습니다. 같은 사용자를 같은 서버로 묶어 두는 설정이 필요 없어집니다.

셋째는 배포입니다. 서버를 몇 대씩 빼서 새 판으로 바꾸는 방식이 가능해집니다. 빼도 되는 서버라는 전제가 무상태에서 나옵니다.

넷째는 서버리스입니다. 서버를 직접 관리하지 않고 함수 단위로 실행하는 방식인데, 호출마다 새 실행 환경이 뜰 수 있어서 애초에 무상태 말고는 선택지가 없습니다.

실무 용례

"이 기능은 서버 메모리에 담고 있어서 무상태가 아닙니다. 대수를 늘리면 깨집니다."

지금 구조로는 서버를 늘릴 수 없다는 지적입니다.

"세션을 공용 저장소로 빼면 무상태가 됩니다."

기억을 서버 밖으로 옮겨 문제를 풀자는 제안입니다.

"무상태라서 서버를 아무 때나 껐다 켜도 됩니다."

배포와 축소를 자유롭게 할 수 있다는 뜻입니다.

페이지덱에서는 서버를 두 대로 늘린 날 이 문제를 만났습니다. 문의가 오전에만 60건 들어왔고 내용은 전부 로그아웃 관련이었습니다. 태오가 앞단 설정에서 같은 사용자를 같은 서버로 묶어 급하게 막았고, 그 주에 로그인 기록을 공용 저장소로 옮겼습니다.

옮긴 뒤에는 고정 설정을 풀었습니다. 그다음 달에 서버 한 대가 갑자기 멈췄을 때, 그 서버가 받고 있던 요청만 실패하고 사용자는 다시 누르면 다른 서버에서 정상으로 처리됐습니다. 고정이 남아 있었다면 그 서버에 묶여 있던 사용자 전부가 로그아웃됐을 상황이었습니다.

흔한 오해

무상태를 상태가 없다는 뜻으로 읽는 경우가 가장 많습니다. 이름이 그렇게 읽히니 자연스러운 오해입니다. 그런데 사용자가 누구인지, 장바구니에 무엇이 들었는지는 여전히 어딘가에 있어야 합니다. 무상태가 뜻하는 것은 그 기억을 서버가 들고 있지 않다는 것뿐이고, 상태는 요청 안이나 공용 저장소로 옮겨진 것입니다. 이걸 없앴다고 이해하면 공용 저장소가 멈췄을 때 전부 멈추는 구조를 만들어 놓고도 왜 그런지 설명하지 못하게 됩니다.

무상태면 항상 나은 선택이라고 보는 것도 흔합니다. 확장과 배포가 편해지니 그렇게 굳습니다. 대가가 둘 있습니다. 요청마다 인증 정보를 실어 보내거나 공용 저장소를 조회해야 하니 요청 하나의 값이 조금 올라갑니다. 그리고 요청에 담아 보내는 방식에서는 발급한 쪽지를 중간에 무르기가 어렵습니다. 서버가 기억하지 않으니 이미 나간 쪽지가 유효 기간까지 계속 통하고, 로그아웃이나 권한 회수가 즉시 반영되지 않습니다. 그래서 실무에서는 유효 기간을 짧게 두고 짧은 주기로 다시 발급하거나, 취소 목록만 따로 공용 저장소에 두는 방식을 섞습니다.

자주 헷갈리는 용어

용어기억을 어디에 두는가무상태와의 차이
세션서버가 사용자별로 유지서버가 기억하는 쪽입니다. 다만 세션 기록을 서버 메모리가 아니라 모든 서버가 보는 공용 저장소에 두면 세션을 쓰면서도 무상태 조건을 지킬 수 있습니다

같이 보면 좋은 페이지

  • 백엔드

    이 설계가 어느 영역의 판단인지 먼저 봅니다

  • 세션

    기억을 서버가 들고 있는 반대쪽 방식입니다

마지막 업데이트 2026-09-16