Stateful 과 Stateless 차이점
웹 공부를 하다보면 클라이언트(Client)와 서버(Server)간의 통신을 상태유지(Stateful) 하느냐, 상태유지하지않음(Stateless) 으로 하느냐 라는 말귀를 한번쯤은 들어본 적이 있을 것이다.
상태라는게 어떠한 정보를 말하는 것 같은데, 이번 시간에는 Stateful 과 Stateless의 차이점에 대해 추상적인 개념 이해에서 벗어나 명확히 파악하는 시간을 가져보자.
Stateful (상태유지)
상태 유지라 함은 클라이언트와 서버 관계에서 서버가 클라이언트의 상태를 보존함을 의미한다.
클라이언트와 서버 간에 송수신을 하며 단계별 과정을 진행하는데 있어, 서버에서 클라이언트가 이전 단계에서 제공한 값을 저장하고 다음 단계에서도 저장한 상태이다.
대표적으로 홈페이지에서 한번 로그인을 하면 페이지를 이동해도 로그인이 풀리지않고 계속 유지되는 것이 바로 서버가 클라이언트의 상태를 유지(기억)하고 있으니까 가능한 것이다.
클라이언트의 정보를 기억한다라는 말은 어딘가에 정보를 저장하고 통신할때마다 읽는다는 뜻이다.
이러한 정보들은 일반적으로 브라우저의 쿠키(Cookie)에 저장되거나, 서버의 세션(Session) 메모리에 저장되어 상태를 유지하게 된다.
Stateful한 프로토콜
대표적인 Stateful 구조를 따르는 프로토콜로 TCP의 3-way handshaking 과정을 예를 들수가 있다.
- 클라이언트는 서버에 SYN(접속 요청 메세지)를 전송하고 SYN_SENT 상태가 된다.
- 서버는 SYN 요청을 받고, 클라이언트에 요청을 수락하는 SYN/ACK를 전송하고 SYN_RECEIVED 상태가 된다.
- 클라이언트는 서버에게 수락 확인으로 ACK를 또 보내고, 수신 받은 서버는 ESTABLISHED 상태가 된다.
- 세션 '상태'가 ESTABLISHED 가 됨으로써, 서버와 클라이언트는 서로 데이터를 주고 받을 수 있는 상태가 된다.
이렇게 TCP는 세션 '상태'에 따라 서버의 응답이 달라지게 되는 Stateful 하다고 말할 수 있는 것이다.
Stateful 문제점
위에서 상태를 유지한다는 함은, 서버에서 클라이언트의 상태 정보를 저장하고 있다고 말했었다.
stateful의 문제점은 해당 서버가 멈추거나 여러 이유로 해당 서버가 못쓰게 되어 다른 서버를 사용해야 할때 발생한다.
왜냐하면 새로운 서버에서는 이전 서버에서 가지고 있던 상태값들을 가지고 있지 않기 때문이다.
예를 들어, 유저가 로그인을 하고 게시판 페이지에 들어가서 글을 쓰기 위해 [글쓰기] 를 눌렀더니 다시 로그인 하라는 화면이 뜨는 것이다. 이는 클라이언트의 로그인 정보를 들고 있는 서버가 어떠한 문제로 인해 다운되어 다른 서버가 대신 역할을 이어 받았는데 해당 클라이언트의 로그인 정보가 없기 때문에 일어난 것이다. (만약, 기존서버에서 새로운 서버로 이전 데이터를 모두 전달해준다면 문제가 없을 수 있다)
즉, 서버 1이 내 정보를 갖고 있기 때문에 중간에 서버 1에 장애가 생기면 클라이언트 A는 일을 처음부터 다시 해야된다.
또한 Stateful 방식은 하나의 서버가 1만 명의 클라이언트를 처리할 능력이 있을 때 그보다 많은 수의 클라이언트가 몰리면, 이미 연결된 1만 명의 클라이언트 중 일부가 빠져야 다음 클라이언트가 처리된다는 한계가 있다.
당연히 클라이언트 상태들을 들고 있으니 용량 한계가 존재하기 때문이다.
※ 참고
따라서 현업에서는 이러한 클라이언트의 상태 데이터를 따로 캐시 서버(Redis)에 저장하여 이용한다.
Stateful 통신 예시
다음은 서버와 클라이언트가 다음과 같이 준비되어 있고 클라이언트가 컴퓨터를 사기 위해 서버에게 컴퓨터 부품을 단계별로 커스텀하여 요청을 하는 상황을 비유한 것이다.
- 컴퓨터 판매를 하는 서버 X
- 컴퓨터 사려는 클라이언트 A
대화를 보면 판매하는 서버 X는 사용자의 이전 요청을 모두 기억하며 진행한다는 것을 알 수 있다.
이것이 상태 유지이며 사람 입장에서는 지극히 정상적인 대화 처럼 보인다.
하지만 여기엔 함정이 있다. 바로 판매하는 서버 X가 중간에 바뀔 경우 이다.
만약 대량의 트래픽이 몰려들어서 서버를 긴급하게 늘렸다고 가정해보면, 판매자 서버 X가 아닌 증설된 어떤 서버 Y가 구매과정을 대신 이어받게 될 수도 있다.
다음은 클라이언트 A와 통신하고 있는 서버 X가 중간에 서버 Y와 서버 Z로 바뀌었을 경우의 상황이다.
그야말로 혼돈의 도가니이다. 이게 바로 상태 유지의 문제다.
Stateless (무상태)
무상태는 반대로 클라이언트와 서버 관계에서 서버가 클라이언트의 상태를 보존하지 않음을 의미한다.
Stateless 구조에서 서버는 단순히 요청이 오면 응답을 보내는 역할만 수행하며, 상태 관리는 전적으로 클라이언트에게 책임이 있는 것이다.
즉, 클라이언트와 서버간의 통신에 필요한 모든 상태 정보들은 클라이언트에서 가지고 있다가 서버와 통신할때 데이터를 실어 보내는 것이 무상태 구조이다.
서버는 단순히 받아서 응답만 해주기 때문에 상태 유지에 대한 부하가 현저히 줄어들게 된다.
또한 상태를 보관하지 않아 서버 1에 문제가 생겨 서버 2가 이어 받아도 응답하는데 있어 문제도 없다.
그래서 대량의 트래픽 발생 시에도 서버 확장을 통해 대처를 수월하게 할 수 있다는 장점도 있다. (stateful과 달리 서버가 바뀌어서도 정확한 응답에 문제가 없으니까)
Stateless한 프로토콜
대표적인 Stateless 프로토콜로는 UDP와 HTTP 를 들 수 있다. (HTTP 통신 기본이 무상태)
무상태에선 브라우저는 데이터를 전송할 때마다 연결하고 바로 끊어버리게 된다.
UDP를 예로 들어 보자면, UDP는 TCP와 달리 hand-shaking 과정을 통해 연결 세션을 인증하는 절차를 수행하지 않고, 세션 상태에 관계 없이 그냥 무작정 보내 버린다.
그래서 서버쪽은 클라이언트와의 세션 정보를 저장하는 과정을 거치지 않아, 클라이언트가 송신한 데이터가 수신되었는지 확인하지도 않으며 클라이언트와의 세션 상태에 관계없이 요청에 대한 응답만을 수행하게 된다.
즉, Client와의 세션 정보를 Server가 저장하지 않는다는 점에서 Stateless 하다고 말할 수 있는 것이다.
Stateless 문제점
무상태의 단점으로는 클라이언트의 요청에 상대적으로 Stateful 보다 더 많은 데이터가 소모되게 된다는 점이다.
매번 요청할때마다 자신의 부가정보를 줘야한다.
물론 이벤트 소개 페이지처럼 아무 정보를 담을 필요가 없는 페이지는 무상태로 만들면 좋다.
하지만 로그인처럼 유저가 로그인하고 있다는 상태를 유지해야 하는 서비스는 상태를 유지하지 않으면 로그인이 풀려버린다.
따라서 모든 것을 무상태로 설계할 수 없다. 어쩔 수 없는 경우에만 상태 유지를 최소한으로 사용하는 것이 베스트이다.
Stateless 통신 예시
상태 유지를 이해했다면 무상태는 생각보다 쉽게 이해할 수 있을 것이다.
- 자전거 판매를 하는 서버 X
- 대체 가능한 서버 Y, Z
- 자전거 사려는 클라이언트 A
대화내용으로 짐작하듯이, 서버가 이전의 클라이언트의 요청(상태)을 유지하지 않아도 클라이언트에서 정보를 일일히 처음부터 하나둘 다 보내주기 때문에 서로 통신하는데는 아무 문제 없이 처리가 된다.
따라서 무상태(stateless)는 기존의 서버가 혼잡해져서 새로운 서버를 가져다 놓아도 기존의 비즈니스 로직을 그대로 구현하고 있다면 이전의 사용자 요청이 어떤지에 관계없이 계속 일을 처리할 수 있다.
그러나 단점은 클라이언트가 하고자하는 최종 목적을 위해 지나는 과정마다 점점 전달해야하는 내용이 많아진다는 것이다.
Stateless 와 토큰(Token)
위에서 무상태의 특징으로 클라이언트와 서버간의 통신에 필요한 모든 상태 정보들은 클라이언트에서 가지고 있다가 서버와 통신할때 데이터를 실어 보내는 것이라고 했다.
그래서 서버는 단순히 받아서 응답만 해주기 때문에 서버에 대한 부하가 현저히 줄어든다고도 하였다.
하지만 로그인 유지와 같은 상태는 싫으나 좋으나 stateful한 상태를 사용하여야 하는데, 그러면 서버에 부하가 생긴다.
그래서 stateless 특징을 유지하면서도 로그인 상태 유지를 가능하게 하는 기술이 바로 JWT 토큰 이다.
토큰은 클라이언트가 암호화된 로그인 정보들을 지니고 있다가 서버에 통신할때 넘겨줌으로써 내가 로그인 됬음을 인증하는 방식이다. 토큰에 대한 내용은 위 포스팅 참고.
따라서 특별한 일이 없다면 무상태를 지향해야하며 정말 필요한 경우에만 상태 유지를 해야한다.
Stateless 와 HTTP / REST
보통 구글에 Stateless 서비스를 검색하면 나오는 연관 개념들이 바로 HTTP, REST 정도가 있다.
HTTP는 알다시피 프로토콜이다.
반면 REST는 프로토콜이라기 보단 구조(Architecture)에 가깝다.
즉, REST는 HTTP 프로토콜 상에 구현된 Resource Oriented Architecture (ROA) 설계 구조 이다.
따라서 HTTP와 REST 모두 Stateless한 성격을 가진 녀석들이며,
- HTTP는 Statelss한 성격을 가진 '프로토콜'
- REST는 Stateless한 성격을 가진 '설계 구조'
라고 정리하면 된다.
참고