WebSocket과 STOMP

KDG: First things first!·2024년 11월 7일

네트워크

목록 보기
2/2

웹소켓이란

웹소켓(WebSocket): 웹소켓은 클라이언트와 서버 간에 양방향 통신을 실시간으로 가능하게 하는 전송(transport) 계층의 TCP 기반의 프로토콜이다. HTTP와 달리 웹소켓은 연결이 지속적으로 유지되어, 클라이언트와 서버가 실시간으로 데이터를 주고받을 수 있다.


웹소켓의 특징

  • 양방향 통신: 웹소켓은 클라이언트와 서버 간의 양방향 통신을 지원한다. HTTP 요청과 응답의 일방적인 통신 방식과 달리, 웹소켓은 클라이언트와 서버가 상호 간에 데이터를 자유롭게 주고받을 수 있도록 합니다.

  • 지속적인 연결: 웹소켓은 연결 유지 방식을 사용한다. 한번 연결이 수립되면, 지속적인 연결을 유지하면서 서버는 클라이언트가 요청할 때마다 새로운 연결을 만들지 않고, 클라이언트와 서버 간에 단일 연결을 통해 데이터를 주고받는다.

  • 저지연성: 웹소켓은 지속적인 연결을 통해 데이터를 전송하기 때문에, 새로운 연결을 생성하는 오버헤드가 없고, 빠른 응답을 제공하여 저지연성을 유지한다. 이로 인해 실시간 애플리케이션에서 유리하다.

  • 상태 유지: HTTP는 상태 비저장(stateless) 프로토콜로 요청마다 새로운 연결을 만들고, 그 이후에 상태를 저장하지 않지만, 웹소켓은 연결이 유지되는 동안 연결 상태를 계속 유지하면서 클라이언트와 서버가 데이터를 주고받을 수 있다.


웹소켓의 작동 방식

  • 핸드쉐이크(Handshake):웹소켓은 HTTP 프로토콜을 사용하여 연결을 초기화한다. 클라이언트가 서버에 웹소켓 핸드쉐이크 요청을 보내면, 서버는 이를 승인하고 웹소켓 연결을 수립한다. 이 핸드쉐이크 과정이 끝나면, HTTP 프로토콜은 더 이상 사용되지 않고 웹소켓 프로토콜이 사용된다.

  • 데이터 전송: 연결이 수립된 후, 클라이언트와 서버는 실시간으로 양방향 데이터를 주고받을 수 있다. 서버는 클라이언트에게 데이터를 푸시할 수 있고, 클라이언트도 서버에 데이터를 보낼 수 있다.

  • 연결 종료: 클라이언트 또는 서버 중 어느 한 쪽이 연결 종료 메시지를 보내고 다른 한 쪽이 이를 확인하면 연결이 종료된다.(어느 한 쪽이 close 프레임을 받지 못 하는 상황이면 비정상적인 종료를 감지하는 몇 가지 방법도 존재한다.)


웹소켓과 HTTP의 차이점

HTTP는 요청-응답 방식으로, 서버가 클라이언트의 요청에 대해 응답을 보내면 연결이 종료되는 방식이다.
하지만 웹소켓은 지속적인 연결을 유지하고, 클라이언트만 서버에게 요청을 보낼 수 있는 단방향 통신인 HTTP와는 다르게 클라이언트와 서버 간에 양방향 통신이 가능하여 실시간으로 데이터를 주고받을 수 있다는 차이점이 있다.

웹소켓은 무상태(stateless) 프로토콜인 HTTP와 다르게 상태를 유지(stateful)하는 연결 방식이다.


HTTPWebSocker
비연결형(Connectionless)연결 지향형(Connection-oriented)
단방향 통신 (Unidirectional Communication)양방향 통신 (Bidirectional Communication)


그렇다면 어떤 경우에 HTTP가 아니라 웹소켓을 사용하는 것이 좋을까?

예를 들어 HTTP 응답 요청 방식을 이용하여 채팅 서비스를 구현한다고 가정해보자.

클라이언트에서 서버에 HTTP 방식으로 '안녕'이라는 메시지를 전송한다.

그럼 이에 대한 답장이 왔는지 확인하기 위해서는 클라이언트에서 일일이 주기적으로 서버에 새로운 메시지가 들어왔는지 요청을 날려야 한다.

당연히 이 방식은 답장 존재 여부에 상관없이 계속 주기적으로 요청을 보내야 하기 때문에 서비스가 커지면 커질수록, 사용자만 많으면 많아질수록 불필요한 요청과 커넥션 생성, 연결, 연결 해제 등의 비용이 크게 발생하는 매우 비효율적인 방식이다.


이러한 경우에 해당 문제를 해결하기 위해서는 웹소켓을 사용해야 한다.

클라이언트와 서버가 웹소켓을 통해 연결되면 서버와 클라이언트 클라이언트에서 주기적인 요청을 통해 답장 메시지를 확인할 필요 없이 양쪽에 메시지가 들어올 때마다 새로 커넥션을 맺지 않고도 실시간으로 서로에게 메시지를 전송할 수 있다.



웹소켓의 장단점

장점

  • 실시간 통신: 웹소켓은 실시간으로 데이터를 주고받을 수 있어서 빠른 응답이 필요한 애플리케이션에 유용다.

  • 낮은 대기 시간: 연결이 지속되기 때문에 새로운 연결을 설정할 필요 없이 빠르게 데이터를 주고받을 수 있다.

  • 효율성: HTTP보다 오버헤드가 적고, 여러 요청을 하나의 연결로 처리할 수 있어 서버 자원을 효율적으로 사용할 수 있다.


단점

  • 연결 유지: 클라이언트와 서버 간에 연결이 지속적으로 유지되어야 하므로, 많은 클라이언트를 지원하려면 서버가 높은 부하를 처리해야 할 수 있다. 또한 오랫동안 데이터 전송이 없어도 연결을 유지해야 하기 때문에 필요 이상의 연결 유지 비용이 소모될 수도 있다.

  • 보안: 웹소켓은 HTTP 기반으로 연결을 시작하므로, 보안에 대한 고려가 필요하다.


웹소켓 사용 예시

  • 실시간 채팅 애플리케이션

  • 온라인 게임의 실시간 데이터 교환

  • 주식 가격 실시간 업데이트

  • 알림 시스템


웹소켓은 주로 실시간 데이터 통신이 필요한 애플리케이션에서 많이 사용된다.



웹소켓 세션(Session)

웹소켓 세션(WebSocket Session): 웹소켓 세션이란 클라이언트와 서버 간에 유지되는 장기적이고 양방향 통신 채널을 의미한다. 웹소켓은 HTTP와 달리 한 번 연결이 수립되면 통신이 끊기지 않고 지속되며, 이 상태를 '세션'이라고 부른다. 웹소켓 세션을 통해 실시간 채팅, 게임, 증권 거래 정보 등 지연 없이 즉각적인 데이터 전송이 가능하다.

즉, 웹소켓 세션이란 웹소켓 연결이 연결된 상태이자 서버와 브라우저가 데이터를 주고받는 각각의 통로라고 생각하면 된다.

실제로 사용자가 웹 사이트에 들어와 웹소켓 연결을 맺을 때마다 서버는 해당 유저와 연결된 세션을 만들어 관리하고 서버는 특정 세션에만 메시지를 전달할 수도, 전체 세션에 동시에 데이터를 전달할 수도 있다.

일반적으로 사용자가 웹소켓에 접속하면 세션이 생겨나고, 사용자가 창을 닫거나 서버와의 연결이 끊어지면 세션이 없어진다.




STOMP(Simple Text Oriented Messaging Protocol)란?

STOMP: STOMP란 WebSocket 위에서 메시지를 구조적으로 주고받기 위한 프로토콜(규약)이다. STOMP는 복잡한 웹소켓 통신을 추상화하여, 개발자가 메시지 교환을 보다 쉽게 구현할 수 있도록 돕는다.


앞서 설명했듯이 서버와 클라이언트가 웹소켓으로 연결되면 서로 메시지를 전달할 수 있게 되지만 웹소켓은 단지 바이너리와 텍스트 데이터만 전송이 가능할 뿐 메시지 형식은 제공되지 않는다는 문제점이 존재한다.

이 때문에 바이너리와 텍스트 데이터처럼 단순한 메시지가 아니라 다른 복잡한 형식의 메시지가 전송되면 클라이언트와 서버의 입장에서는 전달받은 메시지를 어떻게 해석해야 하는지, 어떻게 처리해야 되는지 알 수 없다.

따라서 이 문제를 해결하기 위해서는 클라이언트와 서버가 전달받은 메시지를 이해하고 처리할 수 있는 구조화된 형식이 필요하고 이 구조화된 메시지 형식이 STOMP이다.


STOMP의 형식은 크게 3가지로 나눌 수 있다.

우선 가장 상단에 있는 COMMAND 부분은 무엇을 할 것인지를 지시하는 명령어로 연결, 메시지 전송, 연결 해제 등의 명령어들이 존재한다.

그 다음 중간 부분에는 header가 존재하는데 header는 메시지 경로, 내용 형식 등의 COMMAND에 대한 등의 추가 정보나 옵션을 나타낸다.

마지막으로 Body 부분에는 실제 전송할 메시지의 내용이 포함된다.



STOMP의 Pub/Sub

STOMP의 특징으로는 STOMP는 Pub/Sub 구조를 지원한다는 특징이 존재한다. Pub/Sub 구조를 이용하면 하나의 메시지를 다른 여러 사용자들에게 동시에 전달할 수 있다.



메시지를 발행하는 주체인 Publisher가 메시지를 발행하면 메시지를 수신하는 주체인 Subscriber들이 메시지를 분류하는 경로인 특정 topic을 구독하여 메시지를 전달받는다.



Spring에서는 STOMP가 이미 구현되어 있고 내부에서 어떻게 처리하는지 알아보자.

특정 클라이언트나 서버가 웹소켓을 통해 텍스트 형태의 메시지를 전송하면 inBoundChannel로 메시지가 전송된다. 그럼 inBoundChannel에서 텍스트 형태로 받은 메시지를 STOMP 형식으로 파싱한다.

파싱된 메시지의 header에서 경로를 확인하고 해당 경로의 메시지를 처리할 수 있는 해당 경로의 컨트롤러인 MessageHandler로 전달한다. MessageHandler를 통해 작성한 비즈니스 로직이 실행되고 그 결과로 새로운 메시지를 반환하게 된다.

이렇게 반환된 메시지는brokerChannel로 이동하게 되는데 brokerChannel은 메시지를 수신하면 모든 채널들의 구독 경로를 확인하고 해당 메시지의 경로에 매칭되는 채널들에 해당 메시지를 전달한다.

그 중에서 클라이언트의 응답 전용 채널인 outBoundChannel에서 해당 메시지를 전달받아 구독된 클라이언트들에게 응답 메세지를 전달한다.



업로드중..

자료 출처: https://www.youtube.com/watch?v=ckxmMbwmn98&t=310s

profile
알고리즘, 자료구조 블로그: https://gyun97.github.io/

0개의 댓글