-
[React] 실시간 채팅 기능을 어떻게 구현할까? STOMP, stompjs카테고리 없음 2024. 2. 13. 10:45728x90
[React] 실시간 채팅 기능을 어떻게 구현할까? STOMP
이번에 진행하는 프로젝트에서 실시간 양방향 채팅 기능을 구현하기 위해 STOMP가 채택되었다. 때문에 STOPM가 어떤 것인지, react에서 어떻게 STOMP를 사용할 수 있는지 알아보려 한다.
먼저 STOMP를 이해하기 위해서는 web socket에 대해서 알아야 한다.
Web Socket
web socket은 웹 어플리케이션에서 실시간 양방향 통신을 가능하게 하는 통신 프로토콜이다.
기존 http로 client와 server가 상호작용 하는 것을 생각해 보자.
client에서 server에 요청을 보내면 server는 client에게 요청에 대한 결과를 반환한다. 이렇게 client -> server로만 요청을 보내는 단방향 통신이 이루어진다.
하지만, 채팅 기능을 구현하기 위해서는 단방향 통신으로는 쉽지 않다. 만약 단방향 통신으로 채팅 기능을 구현한다면, 일정 주기마다 server로 요청을 보내서 새로운 채팅이 있는지 확인을 해야 할 것이다. 예를 들어 n초마다 새로운 채팅 목록으로 갱신하려 한다면, n초마다 계속 server에 요청을 보내서 새로운 채팅 목록을 가져와야 한다. 그런데 굳이 계속 server에 요청을 보낸다면 너무 불편하지 않나?
web socket을 사용하면 이 문제를 해결할 수 있다.
web socket은 tcp를 기반으로 client와 server가 양방향 통신을 할 수 있도록 지원한다. web socket을 사용하면 이벤트를 중심으로 응답을 받는 상호작용이 가능하다.
web socket을 연결하기 위해서는 먼저 client에서 server로 web socket을 사용한다는 http 요청을 보내야 한다. 이후 서버에서 http 요청을 web socket으로 업그레이드해준다. 이 시점부터 양방향 통신의 시작이다.
이제 web socket에 대한 개념을 확립했으니 stomp에 대해서도 알아보자.
STOMP
stomp는 Streaming Text Oriented Messaging Protocol로, 텍스트 기반의 메시징 프로토콜이다. 다양한 언어 및 플랫폼 간의 상호 운용성을 지원한다. spring에서 주로 사용된다.
일반적인 web socket에서는 데이터를 전송할 때에 추가 코드 작성이 불가피하다. stomp는 header가 포함되어 보다 다양한 정보들을 수신할 수 있다. 이는 통신 시에 인증 처리가 가능하다는 stomp의 가장 큰 이점인 것이다.
일반적으로 stomp를 사용하여 client와 server 간의 통신을 할 때에 web socket이 양방향 통신을 지원하기 때문에 stomp와의 효율적인 통신이 가능하다. 따라서 stomp는 web socket 위에서 동작한다. 하지만, stomp는 web socket을 위한 것만은 아니다. 보통 web socket 위에서 사용되지만, 반드시 그렇게 사용되는 것은 아니라는 말이다.
React에 적용
react에서 stomp를 사용하기 위해서는 stomp client 라이브러리를 사용해야 한다. 대표적인 라이브러리로 stompjs가 있다.
install
npm install stompjs
//ts
npm install @stomp/stompjs
@stomp/stompjs는 stompjs의 ts용 버전이다.
connect
brokerURL에 server의 endpoint를 지정해 준다.
connectHeaders는 stomp의 최대 장점으로 서버에 데이터를 전송할 수 있다. 이를 통해 사용자 인증이 가능하다.
reconnectDelay는 지정한 (n)ms마다 자동으로 재연결을 시도한다.
import { Client } from '@stomp/stompjs'; const client = new Client({ brokerURL: 'url', connectHeaders: { login: 'user', passcode: 'password', }, debug: function (str) { console.log(str); }, reconnectDelay: (n)ms, }); client.activate(); // 연결 client.deactivate(); // 연결 해제
event
이벤트를 감지하여 이후 동작을 설정할 수 있다.
newClient.onConnect = (frame) => { console.log('Connected!'); }; newClient.onStompError = (frame) => { console.error('error: ' + frame.headers['message']); };
subscribe
onConnect 이벤트가 발생하면 구독 설정을 해준다.
import { Message } from '@stomp/stompjs'; client.onConnect = (frame) => { client.subscribe('/topic/messages', (message: Message) => { console.log('message:', message.body); // 이후 동작 실행 }); };
publish
destination에 end point를 적고, body에 메시지를 구성하여 server단에 전송한다.
client.publish({ destination: '/endpoint', body: JSON.stringify({ type: "", sender: 'user', channelId: "channel", data: 'new message', }), });
// 이후 실제 요구사항을 해결해 가며 글 업데이트 예정입니다.
마치며
개념은 간단하지만 구현하기 위해서는 상당히 복잡해질 것 같다. 확실히 socket io가 사기적인 라이브러리라고 생각한다.
728x90