티스토리 뷰

SockJs란?

SockJS는 WebSocket 프로토콜의 대안으로 사용되는 브라우저 클라이언트와 웹 서버 간의 양방향 통신을 지원하는 자바스크립트 라이브러리입니다.

WebSocket은 브라우저 클라이언트와 웹 서버 간의 양방향 통신을 지원하지만, 모든 브라우저에서 지원되지는 않습니다. SockJS는 WebSocket이 지원되지 않는 브라우저에서도 양방향 통신을 가능하게 하기 위해 개발되었습니다.

SockJS는 다양한 전송 프로토콜을 지원합니다. 이를 통해, 브라우저와 웹 서버 간에 최적의 프로토콜을 선택하여 통신할 수 있습니다. SockJS는 다음과 같은 전송 프로토콜을 지원합니다.

  • WebSocket
  • HTTP streaming
  • HTTP long-polling
  • Iframe-based transport

SockJS는 브라우저 클라이언트와 웹 서버 간의 양방향 통신을 지원하기 위한 간단하고 효과적인 방법을 제공합니다. 이를 통해, 브라우저와 웹 서버 간의 실시간 통신을 구현할 수 있으며, 다양한 웹 애플리케이션에서 사용됩니다.

STOMP란?

STOMP(Streaming Text Oriented Messaging Protocol)는 텍스트 기반의 메시징 프로토콜로, 다양한 언어와 프레임워크에서 사용됩니다.

STOMP는 JMS(Java Messaging Service)와 유사한 메시징 시스템을 구축할 수 있도록 지원합니다. 메시지 브로커와 메시지 송수신 클라이언트 간의 상호작용을 정의하는 규약으로, 메시지 전송, 구독, 메시지 핸들링, 트랜잭션 처리 등을 지원합니다.

STOMP는 텍스트 기반으로 이루어져 있어서, HTTP와 같은 프로토콜 위에서 동작하는 웹 애플리케이션에서 쉽게 사용할 수 있습니다. 또한, STOMP는 매우 간단하고 유연한 구조로 이루어져 있어서, 다양한 언어와 프레임워크에서 사용할 수 있습니다.

STOMP는 일반적으로 웹 소켓을 기반으로 동작합니다. 웹 소켓은 서버와 클라이언트 간의 양방향 통신을 지원하는 프로토콜로, STOMP와 함께 사용될 경우 실시간 메시징 시스템을 구현할 수 있습니다. STOMP는 다양한 프레임워크에서 지원되고 있으며, ActiveMQ, RabbitMQ, Apache Kafka 등 다양한 메시징 브로커에서 사용됩니다.

 

관련 코드

부모 컴포넌트 GameRoomRTC

 

client 객체 관련 함수들

  // stomp client section
  const subscribe = async () => {
    client.current.subscribe(`/sub/gameRoom/${param.roomId}`, ({ body }) => {
      const data = JSON.parse(body);
      switch (data.type) {
        case 'ENTER': {
          break;
        }
        case 'CHAT': {
          setChatMessages((chatMessages) => [...chatMessages, data]);
          break;
        }
        
        (생략)
        
        default: {
          // console.log('default');
          break;
        }
      }
    });
  };
  
  const connect = () => {
    client.current = new StompJs.Client({
      webSocketFactory: () => SockJs,
      connectHeaders,
      debug() {},
      onConnect: () => {
        subscribe();
      },
      onStompError: (frame) => {
        // console.log(`Broker reported error: ${frame.headers.message}`);
        // console.log(`Additional details: ${frame.body}`);
      },
    });
    client.current.activate();
  };

  // end stomp client section
  
  // stomp client method
  function sendChat({ message, sender }) {
    if (message.trim() === '') {
      return;
    }
    client.current.publish({
      destination: `/sub/gameRoom/${param.roomId}`,
      body: JSON.stringify({
        type: 'CHAT',
        roomId: param.roomId,
        sender,
        message,
      }),
    });
  }

return문

        <ChatBox
          notice={
            notice || (
              <p>
                게임 진행 시 <span>공지사항</span> 을 안내해 드립니다.
              </p>
            )
          }
          sendChat={sendChat}
          client={client}
          chatMessages={chatMessages}
        />

자식 컴포넌트 ChatBox

function ChatBox({ notice, sendChat, chatMessages }) {
  const nickname = getNicknameCookie('nickname');
  const [message, setMessage] = useState('');
  const input = useRef(null);
  const scrollRef = useRef();

  const scrollToBottom = () => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
  };

  useEffect(() => {
    scrollToBottom();
  }, [chatMessages]);

  function publish(value) {
    sendChat(value);
    setMessage('');
  }

  function onKeyUpEnter(event) {
    if (event.key === 'Enter') {
      publish({ message, sender: nickname });
    }
  }

  return (
    <StChatBox>
      <StChatBoxCon>
        <StNoticeBack>
          <StNoticeText>{notice}</StNoticeText>
        </StNoticeBack>
        <StUserChatBox ref={scrollRef}>
          <div>
            {chatMessages?.map((message) => {
              return (
                <Chat
                  key={nanoid()}
                  className={
                    message.sender === nickname
                      ? 'my'
                      : message.sender === '양계장 주인'
                      ? 'chickenLord'
                      : 'other'
                  }
                >
                  <div>{`${message.sender}`}</div>
                  <StChatBubble
                    className={
                      message.sender === nickname
                        ? 'my'
                        : message.sender === '양계장 주인'
                        ? 'chickenLord'
                        : 'other'
                    }
                  >{`${message.message}`}</StChatBubble>
                </Chat>
              );
            })}
          </div>
        </StUserChatBox>
        <StSendChat>
          <Input
            ref={input}
            type="text"
            placeholder="채팅을 입력해주세요."
            value={message}
            onChange={(e) => setMessage(e.target.value)}
            onKeyUp={onKeyUpEnter}
          />
          <StChatEnter onClick={() => publish({ message, sender: nickname })}>
            <img src={chatEnterBtn} alt="입력" />
          </StChatEnter>
        </StSendChat>
      </StChatBoxCon>
    </StChatBox>
  );
}

 

깃허브

https://github.com/namoldak/Frontend/blob/main/src/components/GameRoom/GameRoomRTC.jsx

 

GitHub - namoldak/Frontend

Contribute to namoldak/Frontend development by creating an account on GitHub.

github.com

https://github.com/namoldak/Frontend/blob/main/src/components/GameRoom/UserCardsAndChatBox/ChatBox.jsx

 

GitHub - namoldak/Frontend

Contribute to namoldak/Frontend development by creating an account on GitHub.

github.com