- Back-end : Spring Boot, WebSocket, SockJS, Gradle

- Front-end : ReactJS, react-stomp

 

1. Spring Boot 서버 구현 

1) Spring Boot -> Message -> WebSocket 로 Spring boot 프로젝트를 생성한다. 
   생성 후 프로젝트 내 spring-boot-starter-websocket 이 추가되었는지 확인해야 한다. 

 

'org.springframework.boot:spring-boot-starter-websocket'

 

2) WebSocketConfig 클래스 생성

- enableSimpleBroker : 메시지 브로커를 등록한 

- addEndpoint : 클라이언트가 접속할 웹 소켓의 주소, setAllowedOrigins("*")로 전체 CORS 를 허용하며 SockJS을 사용하도록 설정했다. 

 

@Controller
@Configurable
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/test").setAllowedOrigins("*").withSockJS();
    }

}

 

3) 웹소켓을 컨트롤할 TestController 클래스 생성 

- 웹소켓을 주고 받을 시 이벤트를 Trigger 하는 방법은 2가지가 있다. 

   먼저 client 소켓에서 sendMessage 함수로 메시지를 보낼 경우에는 @MessageMapping 어노테이션으로 받을 수 있다.
   두 번째로 @RequestMapping을 사용할 경우에는 웹 소켓이 연동된 Client와 무관하게 외부의 GET 질의로 이벤트를 Trigger 할 수 있다. 

 

- 메시지를 응답하는 방식도 2가지다. 

   첫 번째는 @SendTo 어노테이션을 사용하여 해당 topics를 수신하는 Client Websocket에 메시지를 전달할 수 있다.  
   이 경우 해당 함수는 리턴할 타입을 정의해야하며 반환값 리턴을 통해 Client에 메시지를 전달한다. 

   두 번째는 SimpMessagingTemplate를 사용하는 방식이다.  @SendTo 어노테이션을 사용하지 않고SimpMessagingTemplate로 응답값을 보낼 수 있으며, 이 경우 해당 함수의 리턴값은 void로 처리해야 한다.  SimpMessagingTemplate의 convertAndSend 함수를 사용하면 특정 유저에게만 메시지를 보낼 수 있다. 

 

@RestController
public class TestController {

    @Autowired
    private SimpMessagingTemplate webSocket;

    @MessageMapping("/sendTo")
    @SendTo("/topics/sendTo")
    public String SendToMessage() throws Exception {

        return "SendTo";
    }

    @MessageMapping("/Template")
    public void SendTemplateMessage() {
        webSocket.convertAndSend("/topics/template" , "Template");
    }

    @RequestMapping(value="/api")
    public void SendAPI() {
        webSocket.convertAndSend("/topics/api" , "API");
    }
}

 

2. React 코드 구현

1) 프로젝트 생성

 

npx create-react-app websocket_react

 

2) 관련 라이브러리 추가 

- sockjs-client, react-stomp 라이브러리 추가

 

yarn add sockjs-client react-stomp

 

3) 테스트 App 코드 작성

- react-stomp 라이브러리를 사용하여 웹소켓을 주고 받을 SockJsClient 컴포넌트를 생성한다.

  SockJsClient 생성 시 url은 WebSocket Config에서 Endpoint로 추가한 주소를 지정한다. 
  topics는 서버가 메시지를 보낼 시 수신할 토픽을 지정한다. 다중 지정할 수 있다.

  예제에서는 서버에서 3가지 방식으로 발신하는 모든 메시지를 수신한다. 

 

- SendTo, SendTemplate 버튼은 위 Controller에서 지정한 함수를 트리거하는 이벤트를 작성한다. 

   버튼 클릭 시 SockJsClient의 ref가 지정된 websocket에서 각 sendMessage 함수를 사용하여 서버에 메시지를 보낸다. 

- SockJsClient 관련 Docs : https://github.com/lahsivjar/react-stomp/blob/master/API.md

import React, {useRef} from 'react';

import SockJsClient from 'react-stomp';

function App () {
  const $websocket = useRef (null);

  const handleMsg = msg => {
    console.log (msg);
  };

  const handleClickSendTo = () => {
    $websocket.current.sendMessage ('/sendTo');
  };

  const handleClickSendTemplate = () => {
    $websocket.current.sendMessage ('/Template');
  };

  return (
    <div>

      <SockJsClient
        url="http://localhost:8080/start"
        topics={['/topics/sendTo', '/topics/template', '/topics/api']}
        onMessage={msg => {
          console.log (msg);
        }}
        ref={$websocket}
      />
      <button onClick={handleClickSendTo}>SendTo</button>
      <button onClick={handleClickSendTemplate}>SendTemplate</button>

    </div>
  );
}

export default App;

 

3. 실행 결과

- SendTo 버튼 클릭 시 

 

- SendTemplate 버튼 클릭 시

 

- 외부에서 http://localhost:8080/api 호출 시

다른 카테고리의 글 목록

Spring 카테고리의 포스트를 톺아봅니다