네트워크 프로토콜을 이해하는 데 있어 Stateful, 그리고 Stateless 구조의 개념과 이 둘의 차이를 짚어보는 것은 큰 도움이 됩니다.
1. State가 의미하는 것
네트워킹은 두 화자(peer) 간의 메시지 교환을 중개합니다. 메시지를 주고 받는 한 쪽은 클라이언트(Client), 다른 하나는 서버(Server) 역할을 수행하는 게 인터넷 상에서 발견할 수 있는 전형적인 모습이죠. 서버에 해당하는 대상은 대게 하나 이상, 많게는 수천/수만 개의 클라이언트를 상대하게 됩니다. 서버는 자신과 메시지를 나눴던 클라이언트와 그 메시지 내용 하나하나를 일일이 기억할수도, 또는 곧바로 잊어버릴 수도 있습니다.
Stateful과 Stateless 구조를 설명할때, 이 'state'라 함은 서버와 클라이언트가 주고 받은 일련의 대화 기록이며, 이를 좀 더 네트워크 관점에서 풀어보면 클라이언트/서버가 교환한 요청(Request)과 응답(Response) 메시지 내용으로도 볼 수 있습니다.
서버/클라이언트 통신 방식은 이전 대화 기록(state)를 서버가 저장 또는 참조하느냐에 따라서 Stateful, 아니면 Stateless 구조로 분류할 수 있습니다.
2. Stateful 구조
Stateful 구조의 특징
클라이언트는 수시로 서버에 요청(Request) 메시지를 보냅니다. 서버는 그에 대응하여 응답(Response) 메시지로 답변하고요. 요청과 응답이 한번씩 오고가는 과정을 '세션'으로 부르기도 하는데, Stateful 아키텍쳐에서는 세션 간의 정보와 상태가 지속적으로 추적된다고 생각하시면 좋습니다.
서버는 각 세션별로 어떤 state 정보들을 취득할 지 사전에 어느정도 정의해 둘 수 있습니다. 그리고 state 정보에 따라 어떤 액션을 취할 지에 대한 전체적인 프로세스도 설계할 수 있구요. 더 나아가, 세션이 중단되어도 이전의 컨텍스트와 내역은 서버가 그대로 유지하고 있으므로 중단된 시점부터 다시 재개가 가능합니다. 이런 여러가지 이유들로 인해 Stateful 구조는 클라이언트 요청 처리 성능면에서는 우수하다고 할 수 있습니다.
Stateful 통신 방식을 영화관에서 티켓을 예매하는 상황에 빗대보면 다음과 같습니다.
고객 A: [스파이더 맨] 티켓 2장 예매 가능할까요?
영화관 직원 A: 네 가능합니다. 2장 가격은 24,000원입니다.
고객 A: 멤버쉽 할인도 추가로 받고 싶습니다.
영화관 직원 A: 네, 할인 적용하면 20,000원 되겠습니다.
--------------------------------------------------------------------------
5분 뒤
---------------------------------------------------------------------------
고객 A: 방금 전에 2장 샀었는데, 1장만 추가로 더 예매할게요.
영화관 직원 A: [스파이더 맨] 관람권 1장 추가 예매 말씀하시죠? 멤버쉽 할인 동일하게 적용하시면 10,000원 추가로 지불하시면 되겠습니다.
영화관 직원은 마지막 대화가 이뤄지기 전, 고객 A가 [스파이더 맨] 티켓 2장을 멤버쉽 할인 적용받아 구매했다는 사실을 기억하고 있습니다. 그래서 고객 A가 '어떤 티켓'을 추가 구매하겠다는 건지 이야기하지 않아도 자연스럽게 대화가 이어질 수 있습니다.
Stateful 구조의 문제점
다만, Stateful 서비스는 서버가 많은 양의 클라이언트 데이터를 짊어져야하는 부담을 안겨줍니다. 고객센터를 운영하는데 상담원 한 명이 모든 고객들의 상담 내역을 모조리 기억할 수는 없겠죠. 서버도 마찬가지입니다. 보통 이런 경우에는 서버 노드를 분산시키고 중계 서버를 통해 클라이언트 요청을 서버 노드 하나와 매칭시켜주는 전략을 사용합니다. 서버 하나가 평균적으로 감당해야하는 클라이언트 규모를 획기적으로 줄일 수 있죠. 그럼 다시 고객센터 이야기로 돌아와서, 이제 고객(클라이언트) 수에 못지 않게 상담원 수도 늘렸으니 이제 서비스가 제대로 운영될까요?
그렇지 않습니다. Stateful 아키텍처의 가장 큰 단점은 서버와 클라이언트 간의 종속성 문제인데요. 한 서버에 갑작스럽게 장애가 발생한다면, 해당 서버가 담당하던 클라이언트들은 다른 대체 서버들로부터 원활한 서비스를 제공받기 어렵습니다. 그들의 state 정보를 장애가 발생한 서버만 갖고 있으니까요. 각 서버가 전담하는 클라이언트가 명확하게 구분지어져 있는 구조는 결국 서버 운영의 유연성을 떨어트리는 부작용을 낳게됩니다.
이러한 면에서, Stateful 서버 구조는 가급적 사용을 지양하는 것이 옳을 수도 있겠지만, state 정보가 반드시 필요한(주로 로그인이 요구되는) 서비스들은 Stateful 아키텍처가 어울리긴 합니다.
3. Stateless 구조
Stateless 구조의 특징
Stateless 아키텍처에서의 서버는 클라이언트와 나눈 이전 요청/응답 기록을 따로 남겨두지 않습니다. 같은 클라이언트를 상대하더라도 서버는 매번 처음 본 클라이언트처럼 행동할 뿐더러, 클라이언트의 요청이 이전과는 다른 서버에게로 전달될 수 있습니다. 굳이 세션 정보를 기록해야 한다면야, 서버보다는 클라이언트 쪽에다가 캐시 형태로 정보를 보관하도록 합니다. 이러한 특징 때문에 클라이언트가 무언가를 요청하고자 한다면, 하나의 요청 메시지에 가급적이면 필요한 모든 내용을 담아야만 합니다.
앞에서 Stateful 서비스를 설명할 때의 영화 예매 사례를 떠올려봅시다.
고객 A: [스파이더 맨] 티켓 2장 멤버쉽 할인 받아서 예매 가능할까요?
영화관 직원 A: 네 가능합니다. 2장 가격은 20,000원입니다.
--------------------------------------------------------------------------
5분 뒤
---------------------------------------------------------------------------
고객 A: [스파이더 맨] 티켓 1장 멤버쉽 할인 받아서 (추가로) 예매하려고 합니다.
영화관 직원 B: 네 가능합니다. 1장 가격은 10,000원입니다.
고객 A가 티켓 추가 구매를 위해 창구로 돌아왔을 때는 영화관 직원 A가 잠깐 자리를 비워, 직원 B가 대신 서 있는 상태였습니다. 직원 B는 그날 고객 A를 처음 본 상황이라, 고객 A가 어떤 티켓을 구매했었는지 모릅니다. 따라서 고객 A는 직원 B에게 요청할 때, 필요한 모든 정보(티켓 종류, 티켓 장 수, 멤버쉽 유무)를 이야기해야만 하지요.
설령 직원 A가 그대로 자리를 지키더라도, Stateless 구조에서는 고객 A은 FM대로 모든 정보를 담아 후속 요청을 해야만 합니다. 어찌보면 비효율적인 통신 방식으로 보일 수 있습니다.
그럼에도 Stateless 아키텍처가 필요한 이유
Stateless 구조는 컨택스트 유지를 포기하는 대신, 장애 대응이 쉽고 확장성이 좋다는 장점들이 있습니다. 클라이언트의 요청을 분산 배치된 서버 중 누가 받는지는 전혀 중요하지 않습니다. 모든 서버가 같은 요청을 동등하게 처리해줄 수 있기 때문입니다.
어떤 서버 노드 하나가 마비되더라도 Stateful 서비스와는 다르게 다른 서버가 들어오는 요청들을 대신 맡을 수 있습니다. 응답을 받지 못한 클라이언트들은 동일한 요청을 또 보내기만 하면 되니까요. 서버-클라이언트의 비종속적인 특징은 서버 자원의 스케일을 늘리거나 줄일 때도 다른 처리 작업(transaction)에 크게 영향을 미치지 않는다는 장점도 뒤따릅니다.
무엇보다 서버측에서 세션 데이터 저장을 위한 스토리지 공간을 마련할 필요가 없다는 점도 Stateless 아키텍처가 널리 이용되는데에 한몫하는 요인입니다.
4. 종합적인 비교
앞에서 살펴본 Stateful/Stateless 구조의 장단점을 종합하자면 아래와 같습니다.
5. 각각의 구조를 채택하는 프로토콜/서비스
Stateful의 예시
Stateful 형태로 동작하는 프로토콜에는 파일 전송 프로토콜(File Transfer Protocol, FTP)와 Telnet 등이 있습니다. 서비스의 경우, 대체로 로그인이 필요한 서비스들 (ex., 온라인 뱅킹, 이메일) 등이 Stateful 아키텍처에 기반합니다.
Stateless의 예시
Stateless 형태의 연결을 지원하는 대표적인 프로토콜은 HTTP와 DNS입니다. 홈페이지와 같이 불특정 다수에게 단순한 Html, 이미지 리소스 등을 제공해야하는 경우에 Stateless 아키텍처가 쓰입니다.