본문 바로가기

Language

[WebSocket] Spring 4를 이용한 WebSocket 구현하기

728x90

HTTP 환경에서 client-server간의 상호작용을 위한 WebSocket 기능이 있습니다.

Spring 4에서 해당 기능을 지원하며 다음과 같은 절차로 사용할 수 있습니다.

작업 환경

  • SpringFramework 4.0.4-RELEASE
  • Tomcat 7.0.54
  • Maven
  • Spring MVC로 구성된 프로젝트

구성 절차

1. Maven의 종속성 설정하기

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-websocket</artifactid>
    <version>${spring.version}</version>
</dependency>
spring-websocket 을 추가합니다.

2. websocket에 대한 핸들러를 등록합니다.

<websocket:handlers>
  <websocket:mapping handler="websocketHandler" path="/echo">
  </websocket:mapping>
</websocket:handlers>
<bean id="websocketHandler" class="net.oofbird.websocket.WebsocketEndPoint">
</bean>
이때 Client에서 접속할 Path를 지정하고 해당 Path에서 들어오는 WebSocket 요청을 처리할 클래스를 등록합니다.

여기서는 “/echo”로 요청이 들어오면 WebSocket을 처리하고, 처리하는 클래스는 “net.oofbird.websocket.WebsocketEndPoint”가 됩니다.

3. WebsocketEndPoint를 정의합니다.

package com.samsung.s3va.em.websocket;
 
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
 
import com.samsung.s3va.em.SessionManager;
 
// 서버단의 WebSocketEndPoint 정의
// Websocket에서 서버단의 프로세스를 정의할 수 있다
// xml에 설정안하고 @ServerEndpoint(path) 로 정의할 수 있다고 알고 있다.
public class WebsocketEndPoint extends TextWebSocketHandler {
    
    // 접속하는 사용자에 대한 세션을 보관하기 위해 정의
    private SessionManager clients;
 
    public WebsocketEndPoint() {
        super();
        clients = SessionManager.getInstance(); 
    }
 
    // 클라이언트에서 접속을 하여 성공할 경우 발생하는 이벤트
    @Override
    public void afterConnectionEstablished(WebSocketSession session)
            throws Exception {
        super.afterConnectionEstablished(session);
        System.out.println("Session Connected");
        
        // 메시지 발송을 위해 세션목록에 추가한다.
        clients.add(session);
    }
 
    // 클라이언트에서 send를 이용해서 메시지 발송을 한 경우 이벤트 핸들링
    @Override
    protected void handleTextMessage(WebSocketSession session,
            TextMessage message) throws Exception {
        String payloadMessage = message.getPayload();
        
        for (WebSocketSession client : clients.getList()) {
            client.sendMessage(new TextMessage("ECHO : " + payloadMessage));
        }
    }
 
    // 클라이언트에서 연결을 종료할 경우 발생하는 이벤트
    @Override
    public void afterConnectionClosed(WebSocketSession session,
            CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        System.out.println("Closed");
        // 메시지 발송 제외를 위해 세션목록에서 삭제한다.
        clients.remove(session);
    }
    
}

위 예제의 경우에는 TextWebSocketHandler를 상속받아서 구현하였으며,

중요 포인트는

Client가 접속을 하여 Session이 생성되면 afterConnectionEstablished 함수에서 이벤트 핸들링을 하고,

Client에서 send를 이용해서 요청을 하는 경우 handleTextMessage 함수에서 이벤트 핸들링을 하고,

Client에서 close를 이용해서 접속을 종료하는 경우 afterConnectionClosed 함수에서 이벤트 핸들링을 합니다.

 

AbstractWebSocketHandler를 좀 더 살펴보면,

handleMessage, handleTextMessage, handleBinaryMessage, handlePongMessage 등이 있습니다.

 

handleTextMessage 에서 파라미터로 넘어오는 session 객체에만 sendMessage를 할 경우 해당 세션만 전송이 되므로, 예제에서는 SessionManager를 이용해서 afterConnectionEstablished 에서 session을 추가하고, handleTextMessage 에서 전체 세션에 메시지를 발송하도록 하였습니다. (SessionManager는 단순 LinkedList로 보시면 됩니다.)

4. Client 화면 구현하기

<script type="text/javascript">
	var ws = null;
	var url = null;
 
	function connect() {
		<!-- 중요 포인트!! url을 이용해서 WebSocket을 생성하고 각각 이벤트에 대한 처리를 정의한다.-->
		ws = new WebSocket(url);
 
		ws.onopen = function () {
			// 서버에 접속한 후 이벤트 정의
		};
		ws.onmessage = function (event) {
			// 서버에서 Session.send를 이용해서 메시지 전송할 때 수신 이벤트 정의
		};
		ws.onclose = function (event) {
			// 서버에서 접속 종료한 후 이벤트 정의
		};
	}
 
	function disconnect() {
		ws.close();
		ws = null;
	}
 
	function echo() {
		// send 명령을 이용해서 전송을 한다.
		ws.send(message);
	}
</script>

new WebSocket(url)을 이용해서 접속을 처리하면 되며, ws.onopen, ws.onmessage, ws.onclose 등의 이벤트 처리함수를 정의해주면 됩니다.

서버에 메시지를 전송하고 싶으면 ws.send를 이용해서 메시지를 전송하면 됩니다.

반응형