WebSocket의 사용 방법은 Ajax와 비슷하지만, 개념 면에서 Ajax와 차이가 있다. Ajax의 경우는 웹 브라우저에서 데이터를 호출하면 웹 서버에서 호출된 값을 검색, 작성해서 웹 브라우저로 메세지를 보내는 형식의 구조이다. 하지만 WebSocket 의 경우는 웹 브라우저에서 호출해서 데이터를 가져가는 기능을 포함하여 반대로 서버에서 클라이언트를 호출할 수 있는 기능까지 있다. 예를 들어 채팅프로그램을 만든다고 할 때, WebSocket 은 서버에서도 클라이언트를 인지하는 상태이기에 양방향 통신이 가능하다.
스프링에서 웹 소켓을 사용하는 방법
https://inpa.tistory.com/entry/WEB-%F0%9F%8C%90-%EC%9B%B9-%EC%86%8C%EC%BC%93-Socket-%EC%97%AD%EC%82%AC%EB%B6%80%ED%84%B0-%EC%A0%95%EB%A6%AC
🎈소켓 통신
HTTP 통신은 다음과 같은 특징이 있다.
- 비연결성 : 연결을 맺고 요청을 하고 응답을 받으면 연결을 끊어버린다.
- 무상태성 : 서버가 클라이언트의 상태를 가지고 있지 않는다.
- 단방향 통신.
이러한 HTTP 통신의 경우 채팅과 같은 실시간 통신에 적합하지 않다.
실시간 통신이 필요할 때 사용하는 통신을 소켓 통신이라고 한다.
HTTP 통신과 다르게 연결을 맺고 바로 끊어버리는 게 아니라 계속 유지를 하기 때문에 실시간 통신에 적합하다. 먼저 STOMP 프로토콜에 대해서 이해를 해야 한다.
STOMP (Simple Text Oriented Messaging Protocol, 스트리밍 텍스트 지향 메시지 프로토콜)
: 간단한 메시지를 전송하기 위한 프로토콜로 메시지 브로커와 publisher - subscriber 방식을 사용한다. 메시지의 발행자와 구독자가 존재하고 메시지를 보내는 사람과 받는 사람이 구분되어 있다. 메시지 브로커는 발행자가 보낸 메시지를 구독자에게 전달해주는 역할을 한다. STOMP는 HTTP와 비슷하게 frame 기반 프로토콜 command, header, body로 이루어져 있다.
웹 소켓과 STOMP를 함께 사용하면 frame의 구조가 정해져 있기 때문에 통신에 용이하다. 다음은 STOMP를 사용할 때 통신 과정이다.
주요 특징 :
- @Controller → @MessageMapping으로 연결한 후 브로커에다가 보내는데 브로커는 메모리도 가능하고 RabbitMQ, ActiveMq등도 사용이 가능하다.
- spring은 브로커에 대한 tcp 연결을 유지하고 연결된 websocket client에게 메시지를 전달한다.
- client는 메시지를 받고 또 메시지를 수신한다.
- client에서 메시지를 보내면 @MessageMapping에서 받아서 처리한다.
- 메시지를 받을 endpoint는 /endpoint/..., /endpoint/** 등을 지원한다.
- 서버의 모든 메시지는 특정 클라이언트 구독에 대한 응답이어야 하며 서버 메시지의 subscription-id 헤더는 클라이언트 구독의 id 헤더와 동일해야 한다.
장점 :
- raw websocket 보다 더 많은 프로그래밍 모델을 지원
- 여러 브로커(카프카 등)을 사용 가능
- spring framework를 사용하면 사용 가능
- 메시지 포맷을 정할 필요가 없다.
- 애플리케이션 로직은 여러 @Controller 인스턴스로 구성될 수 있으며 주어진 연결에 대해 단일 WebSocketHandler를 사용하여 원시 WebSocket 메시지를 처리하는 대신 STOMP 대상 헤더를 기반으로 메시지를 라우팅할 수 있다.
수신자는 /topic 경로를 구독하고 있고 발행자는 /app 혹은 /topic으로 메시지를 보내는 모습을 확인할 수 있다. 만약 발행자가 /topic 경로로 메시지를 보내면 바로 수신자에게 도착하고 /app 경로로 메시지를 보내면 가공을 한 다음 보내게 된다.
Websocket은 기존의 단방향 HTTP 프로토콜과 호환되어 양방향 통신을 제공하기 위해 개발된 프로토콜. 접속까지는 HTTP프로토콜을 이용하고 그 이후의 통신은 자체적인 Websocket 프로토콜로 통신하게 된다. socket 통신은 서버와 클라이언트가 1:N으로 관계를 맺는다. 따라서 한 서버에 여러 클라이언트가 접속할 수 있으며, 서버에는 여러 클라이언트가 발송한 메시지를 받아 처리해 줄 Handler의 작성이 필요하다. 핸들러는 TextWebSocketHandler를 상속받아서 작성하고, Client로부터 받은 메시지를 Console log에 출력하고 Client로 환영 메시지를 보내는 역할을 한다.
(❁´◡`❁) Spring WebSocket은 실시간 애플리케이션을 구현하는 데 유용하며, Spring과 통합하여 보안, 메시지 브로커, 연결 관리 등을 쉽게 처리할 수 있다.
1. 실시간 채팅 애플리케이션
2. 실시간 알림 시스템
3. 실시간 데이터 스트리밍
- 금융 시장 데이터 실시간으로 클라이언트에게 전송.
- 스포츠 경기 실시간 점수 업데이트후 전송
4. 협업 애플리케이션
- 여러 사용자가 동시에 같은 문서를 편집하고, 편집 내용이 실시간으로 모든 사용자에게 반영.
- 여러 사용자가 동시에 같은 화면에서 그림을 그리거나 아이디어를 공유.
5. 실시간 위치 추적
- 차량의 실시간 위치 정보를 사용자에게 전송.
- 사용자가 자신의 위치를 친구와 실시간으로 공유.
6. 게임 애플리케이션
- 멀티플레이어 게임을 진행할 수 있으며, 게임 상태나 움직임을 실시간으로 동기화.
- 순위 점수를 실시간으로 업데이트하고 사용자에게 전송.
7. 인터넷 of Things(IoT)
- 스마트 홈 디바이스나 IoT 기기에서 발생하는 데이터를 실시간으로 모니터링하고 제어.
- 다양한 센서로부터 실시간 데이터를 수집 후 클라이언트 애플리케이션에 전송.
8. 라이브 투표 시스템
9. 기타
사용자가 투표를 진행하면서 실시간으로 투표 결과를 집계하고 화면에 반영 , 페이스북 같은 SNS 어플리케이션, 구글 Doc 같이 여러 명이 동시 접속해서 수정할 수 있는 Tool, 클릭 동향 분석 데이터 어플 (특정 시간동안 어느 사이트에 주로 접속했는지 등의 정보를 파악하는 어플), 증권 거래 정보 사이트 및 어플, 스포츠 업데이트 정보 사이트 및 어플, 화상 채팅 어플, 위치 기반 어플, 온라인 교육 사이트 및 어플 ...
참고 : 웹소켓(WebSocket) 엔드포인트는 클라이언트와 서버 간에 웹소켓 연결을 시작하는 URL이다. 이 엔드포인트를 통해 클라이언트는 서버에 연결 요청을 보내고, 서버가 요청을 승인하면 두 개의 통신 채널이 열리게 된다. 즉, 엔드포인트를 통해 클라이언트는 서버와 지속적으로 데이터를 주고받을 수 있는 상태를 유지하게 된다. 이를 통해 양방향 통신이 실시간으로 이루어질 수 있다.
웹소켓 엔드포인트는 일반적으로 다음과 같은 형식을 따른다.
- ws:// 또는 wss://로 시작 (HTTP와 HTTPS와 유사하게, ws는 일반 웹소켓, wss는 보안 웹소켓을 의미)
- 도메인 이름 또는 IP 주소
- 포트 번호 (필요한 경우)
- 특정 경로 : 예를 들어, ws://example.com/socket 또는 wss://example.com/socket/updates 같은 형식이다.
ws://example.com/socket이 웹소켓 엔드포인트라면, 이 URL을 통해 클라이언트는 서버와 연결하여 실시간으로
메시지를 송수신할 수 있다.
웹소켓 엔드포인트는 전통적인 HTTP 요청과는 다르게, 초기 Handshake 이후에 클라이언트와 서버가 지속적인 연결 상태를 유지하면서 데이터를 주고받게 되는 특징이 있다.
웹소켓은 HTTP 프로토콜 위에서 작동하며, 처음에는 일반 HTTP 요청을 통해 연결이 시작되지만, 서버와의 Handshake 과정 이후에는 HTTP 연결이 웹소켓 연결로 업그레이드 된다. 이때 사용되는 특정 URL이 바로 웹소켓 엔드포인트이다.
웹 소켓 설정 : Websocket을 활성화하기 위한 Config 파일을 작성한다.
@EnableWebSocket을 선언하여 WebSocket을 활성화 하고, WebSocket을 접속하기 위한 endpoint 주소를 작성한다. 도메인이 다른 서버에서도 접속 가능 하도록 CORS : setAllowedOrigins("*") 설정을 추가.
* 실습용 CDN *
<!-- SockJS와 STOMP 라이브러리 읽기용 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.5.1/sockjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
* 실습용 css *
chat.html 관련
<body>
<div>
<h2 style="color: #004d40">🏡 채팅</h2>
<ul id="messageArea">
</ul>
<!-- 입력창과 버튼을 감싸는 컨테이너 추가 -->
<div id="inputContainer">
<input type="text" id="name" placeholder="이름 입력"> <input
type="text" id="message" size="100" placeholder="메세지 입력"
xxxxonkeydown="if (event.keyCode == 13) sendMessage()">
<button xxxxonclick="sendMessage()">전송</button>
<button xxxxonclick="leaveChat()">퇴장</button>
</div>
</div>
</body>