티스토리 뷰

반응형

필자는 팀 프로젝트에서 채팅서비스를 도입하여 온라인에서 사용자끼리 상품 거래를 할 수 있도록 클라이언트에서 공부해야 할 기술 스택을 찾고 있다가 sockJS를 알게 되었다.

그리고 다음과 같은 이유로 sockJS를 프로젝트에서 사용하기로 하였다.

 

sockJS

websocket과 비슷한 기능을 제공하는 브라우저 javascript 라이브러리다.

그렇다면 그냥 websocket에서 제공하는 기능을 사용하면 되는데 굳이 sockJS를 도입하기로 결심을 한 것일까?

직접 sockJS의 깃헙 주소로 들어간 결과 해당 라이브러리 summary 부분에서 장점을 친절하게 설명하고 있었다.

브라우저와 웹 서버 사이에서 짧은 지연시간, 그리고 크로스 브라우징을 지원하는 API라는 것이다.

이것을 통해 필자가 애용하는 크롬뿐만 아니라 사파리, 파이어 폭스 그리고 websocket 프로토콜을 지원하지 않는 최신 브라우저에서도 해당 라이브러리의 API가 잘 작동되도록 지원하는 라이브러리라는 것을 알 수 있었다.

그리고 해당 라이브러리의 철학 중 연결 장치는 빠르고 가벼워야 한다라는 문구도 봐서 채택하게 되었다.

 

stompJS

한편 팀의 백엔드 측에서 stomp라는 서브 프로토콜을 사용하기로 결정이 되었기 때문에 웹소켓의 서브 프로토콜인 stomp 위에서 sockJS가 정상적으로 작동되고 stomp 프로토콜 환경에서 stompJS에서 제공하는 프로토콜 연결, 메세지 전송, 상대방 구독 기능을 제공하는 stompJS라는 라이브러리도 설치하였다.

해당 게시물은 sockJS와 stompJS를 어떻게 사용했는지에 대한 설명 글이므로 stomp와 서브 프로토콜이 무엇인지는 생략하도록 하겠다.

 

설치 방법

npm run --save-dev sockjs-client@1.0.2 stompjs@2.3.3

필자의 백엔드 프레임워크는 spring boot이며 spring boot 공식 사이트에서 채팅 관련 설명 글을 찾아본 결과 각 라이브러리는 위와 같은 버전을 지원한다고 나와 있어서 해당 버전으로 설치하였다.

 

클라이언트 생성

이제 stompJS와 sockJS의 객체를 사용할 파일을 생성하고 사용할 객체를 다음과 같이 해당 라이브러리에서 import 및 require한다.

// ...
import SockJS from 'sockjs-client'
const Stomp = require('stompjs');
// ...

이제  stomp 프로토콜 위에서 sockJS가 작동되도록 클라이언트를 생성하자!

// ...
let stomp_client;

function connection {
  let socket = new SockJS(연결할 uri);
  stomp_client = Stomp.over(socket);
  // ... 
}

// ...

sockJS의 인자로 연결할 프로토콜의 URI를 입력해주고 임의의 변수에 할당하자!

그리고 stomp 프로토콜 위에 sockJS가 돌아가도록 Stomp.over()의 인자로 방금 만든 socket이라는 변수를 넣어준다.

이제부터는 상황에 따라 stomp_client라는 변수에 서버 연결, 메세지 전송 , 상대방 구독 관련 값을 추가 할당하기에 자주 사용될 것이다.

 

서버 연결

이제 서버에 연결하기 위해 서버에 CONNECT 프레임을 전송해야 한다.

프레임이란 명령어, 선택사항인 헤더 집합, 선택사항인 body로 구성되어 있으며 이 프레임이라는 것을 클라이언트와 주고 받음으로써 통신을 실시간으로 상호작용을 할 수 있다.

// ...
stomp_client.connect({}, function() {
  // ...
})
// ...

위 코드로 서버와 연결하면 서버로부터 연결이 되었다는 CONNECT 응답 프레임이 온다.

위 {} 이것은 CONNECT 프레임을 전송할 때 같이 전송하는 헤더를 설정하는 곳이다.

그리고 연결이 완료되면 콜백 함수가 실행된다.

이 콜백함수를 통해 서버 연결 후에 취할 다양한 액션을 넣어 줄 수 있다.

 

구독

상대방에게 메세지를 보내거나 받아야 할 경우 특정 URI에 대해 구독해야 한다.

쉽게 예를 들자면 우리가 누군가에게 우편을 보낼 때 받는 사람의 주소가 필요 하듯이 stompJS에서도 메세지를 보내거나 받기 위해 특정 URI를 알고 있어야 하며 그것을 구독을 해야 한다.

만약 특정 URI를 구독한다면 이제 상대방이 해당 URL를 구독하고 메세지를 보내면 나는 해당 메세지를 받을 수 있게 된다.

실제 예로 특정 채팅방에 입장하면 해당 채팅방으로부터 전송되는 메세지를 수신할 수 있도록 SUBSCRIBE 프레임을 날리는 경우가 있다.

그리고 이 구독을 하기 위해서는 SUBSCRIBE 프레임을 보낸다.

stomp_client.subscribe(`/join/room/1`, function (frame) {
  // ...
}, {})
// ...

subscribe()의 첫번째 인자는 구독할 URI를 의미한다.

해당 url은 1번 채팅방에 입장한다는 의미이며 필자가 임의로 설정한 URI이다.

두 번째 인자는 구독한 후에 실행될 콜백함수이며 구독 이후 상대방으로부터 메세지를 수신 받을 때마다 해당 콜백함수가 실행된다.

해당 콜백함수의 매개변수를 통해 프레임의 정보를 console.log를 통해 조회할 수 있다.

세 번째 인자는 SUBSCRIBE 프레임을 전송할 때 같이 보내는 헤더를 설정하는 곳이다.

 

구독 끊기

만약 특정 채팅방에서 나가거나 해당 어플리케이션에서 나갔을 경우 상대방이 보낸 메세지를 읽지 않음으로 표시하기 위해 구독을 끊어준다.

이 구독을 끊는다는 것은 서버와의 연결을 끊는 것이 아닌 특정 메세지의 SEND 프레임을수신하지 않겠다는 것을 의미한다.

stomp_client.subscribe(`/join/room/1`, function (frame) {
  // ...
}, {}).unsubscribe()
// ...

위 코드는 채팅방 1번을 나갈 때 구독을 끊는다는 의미이다.

 

메세지 전송

메세지를 전송할 때는 SEND프레임을 전송해야 한다.

// ...
const message = {
  key : value
}
stomp_client.send("/message", {}, JSON.stringify(message))
// ...

send()의 첫 번째인자는 해당 프레임을 전송할 때 필요한 URI를 입력한다.

두 번째 인자는 해당 프레임을 전송할 때 헤더를 설정하는 곳이다.

세 번째 인자는 해당 프레임을 전송할 때 보낼 데이터를 설정하는 body이며 이 부분에 상대방에게 보내고 싶은 메세지가 들어간다.

필자는 보낼 데이터를 JSON 형태로 보내는 것을 예시 코드로 작성했으며 해당 key와 value는 서버 개발자가 지정한 양식에 따라 입력해야 할 데이터를 넣어주면 된다.

 

서버 연결 끊기

// ...
stomp_client.disconnect();
// ...

웹소켓 연결을 끊기 위해서는 Stomp.over()를 할당한 변수에 disconnect()로 체이닝한다.

 

프레임을 개발자 도구에서 숨기기

채팅을 하다보면 프레임이 개발자 도구에 노출됨으로써 프레임에 포함되는 헤더, 데이터, body도 같이 노출된다.이러한 프레임을 개발자 도구에서 숨기기 위해서는 다음과 같이 코드를 추가해주자!

// ...
stomp_client.debug = null
// ...
반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함