[Spring4] 스프링 웹소켓(WebSocket) 예제

[Spring4] 스프링 웹소켓(WebSocket) 예제

스프링 웹소켓 예제를 구현해보았다.

검색해보니 구현방법이 무척 많았는데, 최대한 쉽게 구현된 형태를 참고하였다.

명월일지라는 블로그의 http://nowonbun.tistory.com/285 라는 포스트를 주로 참고하였다.

간단하게 다중 채팅방을 구현해보았다.

1. 스프링 웹 프로젝트 생성

먼저 스프링 웹 프로젝트가 필요하다.

기존에 있으면 건너뛰어도 된다. 기존에 없으면 아래 포스트를 참고해서 만들면 된다.

=> [Spring4] STS에서 스프링 웹 프로젝트 생성 (https://blog.naver.com/bb_/221339454799)

2. pom.xml 수정

WebSocket Server API 라는 라이브러리가 필요하다.

pom.xml 에 다음 코드를 추가하였다.

<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope>
</dependency>

따로 다운받고 싶으면 MVN Repository를 방문하면 된다. https://mvnrepository.com/artifact/javax.websocket/javax.websocket-api 에서 1.1 버전 다운받으면 된다.

3. Websocket.java 파일 작성

적당한 위치에 Websocket.java 파일을 만들고 아래처럼 코드를 작성한다.

// 패키지 위치는 자유롭게 결정

package com.bb.vivria.socket;

import java.util.ArrayList;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(“/websocket”)
public class Websocket {

    /**
     * 웹소켓 세션을 담는 ArrayList
     */

    private static ArrayList<Session> sessionList = new ArrayList<Session>();

    
    /**
     * 웹소켓 사용자 연결 성립하는 경우 호출
     */

    @OnOpen
    public void handleOpen(Session session) {
        if (session != null) {
            String sessionId = session.getId();
            
            System.out.println(“client is connected. sessionId == [“ + sessionId + “]”);
            sessionList.add(session);
            
            // 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
            sendMessageToAll(“***** [USER-“ + sessionId + “] is connected. *****”);
        }
    }
    

    /**
     * 웹소켓 메시지(From Client) 수신하는 경우 호출
     */

    @OnMessage
    public String handleMessage(String message, Session session) {
        if (session != null) {
            String sessionId = session.getId();
            System.out.println(“message is arrived. sessionId == [“ + sessionId + “] / message == [“ + message + “]”);

            // 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
            sendMessageToAll(“[USER-“ + sessionId + “] “ + message);
        }

        return null;
    }
    

    /**
     * 웹소켓 사용자 연결 해제하는 경우 호출
     */

    @OnClose
    public void handleClose(Session session) {
        if (session != null) {
            String sessionId = session.getId();
            System.out.println(“client is disconnected. sessionId == [“ + sessionId + “]”);
            
            // 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
            sendMessageToAll(“***** [USER-“ + sessionId + “] is disconnected. *****”);
        }
    }

    
    /**
     * 웹소켓 에러 발생하는 경우 호출
     */

    @OnError
    public void handleError(Throwable t) {
        t.printStackTrace();
    }
    
    
    /**
     * 웹소켓 연결 성립되어 있는 모든 사용자에게 메시지 전송
     */

    private boolean sendMessageToAll(String message) {
        if (sessionList == null) {
            return false;
        }

        int sessionCount = sessionList.size();
        if (sessionCount < 1) {
            return false;
        }

        Session singleSession = null;

        for (int i = 0; i < sessionCount; i++) {
            singleSession = sessionList.get(i);
            if (singleSession == null) {
                continue;
            }

            if (!singleSession.isOpen()) {
                continue;
            }

            sessionList.get(i).getAsyncRemote().sendText(message);
        }

        return true;
    }
}

 

4. test.jsp 파일 작성

적당한 위치에 test.jsp 파일을 만들고 아래처럼 코드를 작성한다.

여기서는 webapp/WEB-INF/chat/test.jsp 에 위치한다고 가정한다.

<%@ page contentType=“text/html; charset=utf-8” %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”>
<title>웹소켓 테스트 페이지</title>
<script type=“text/javascript”>
var g_webSocket = null;
window.onload = function() {
    g_webSocket = new WebSocket(“ws://localhost:8080/websocket”);
    
    
    /**
     * 웹소켓 사용자 연결 성립하는 경우 호출
     */

    g_webSocket.onopen = function(message) {
        addLineToChatBox(“Server is connected.”);
    };
    
    
    /**
     * 웹소켓 메시지(From Server) 수신하는 경우 호출
     */

    g_webSocket.onmessage = function(message) {
        addLineToChatBox(message.data);
    };

    /**
     * 웹소켓 사용자 연결 해제하는 경우 호출
     */

    g_webSocket.onclose = function(message) {
        addLineToChatBox(“Server is disconnected.”);
    };

    /**
     * 웹소켓 에러 발생하는 경우 호출
     */

    g_webSocket.onerror = function(message) {
        addLineToChatBox(“Error!”);
    };
}

/**
* 채팅 박스영역에 내용 한 줄 추가
*/

function addLineToChatBox(_line) {
    if (_line == null) {
        _line = “”;
    }
    
    var chatBoxArea = document.getElementById(“chatBoxArea”);
    chatBoxArea.value += _line + “\n”;
    chatBoxArea.scrollTop = chatBoxArea.scrollHeight;    
}

/**
* Send 버튼 클릭하는 경우 호출 (서버로 메시지 전송)
*/

function sendButton_onclick() {
    var inputMsgBox = document.getElementById(“inputMsgBox”);
    if (inputMsgBox == null || inputMsgBox.value == null || inputMsgBox.value.length == 0) {
        return false;
    }
    
    var chatBoxArea = document.getElementById(“chatBoxArea”);
    
    if (g_webSocket == null || g_webSocket.readyState == 3) {
        chatBoxArea.value += “Server is disconnected.\n”;
        return false;
    }
    
    // 서버로 메시지 전송
    g_webSocket.send(inputMsgBox.value);
    inputMsgBox.value = “”;
    inputMsgBox.focus();
    
    return true;
}

/**
* Disconnect 버튼 클릭하는 경우 호출
*/

function disconnectButton_onclick() {
    if (g_webSocket != null) {
        g_webSocket.close();    
    }
}

/**
* inputMsgBox 키입력하는 경우 호출
*/

function inputMsgBox_onkeypress() {
    if (event == null) {
        return false;
    }
    
    // 엔터키 누를 경우 서버로 메시지 전송
    var keyCode = event.keyCode || event.which;
    if (keyCode == 13) {
        sendButton_onclick();
    }
}
</script>
</head>
<body>
    <input id=“inputMsgBox” style=“width: 250px;” type=“text” onkeypress=“inputMsgBox_onkeypress()”>
    <input id=“sendButton” value=“Send” type=“button” onclick=“sendButton_onclick()”>
    <input id=“disconnectButton” value=“Disconnect” type=“button” onclick=“disconnectButton_onclick()”>
    <br/>
    <textarea id=“chatBoxArea” style=“width: 100%;” rows=“10” cols=“50” readonly=“readonly”></textarea>
</body>
</html>

5. ChatController.java 파일 작성

도메인:포트/chat 으로 접속하면 test.jsp 에 도달할 수 있도록 ChatController.java 파일을 작성한다.

패키지 위치는 자유롭게 결정하면 된다.

예를 들어 localhost:8080/chat 으로 접속했을 때 test.jsp 가 뜨면 성공이다.

// 패키지 위치는 자유롭게 결정

package com.bb.vivria.controller;

import java.util.Locale;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class ChatController {
    @RequestMapping(value = “/chat”, method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        
        return “chat/test”;
    }
}

5. 테스트

브라우저 여러 개를 띄워, 도메인:포트/chat (예를 들어 localhost:8080/chat) 에 접속한 후 채팅을 해보자.

잘되면 성공이다.

이상 스프링 웹소켓(WebSocket) 예제를 마친다.