본문 바로가기

study/java

WebSocket 기초 예제

https://steady-record.tistory.com/entry/WebSocket

 

[Spring] WebSocket 기초 예제

Socket? WebSocket?🔎 - Socket Socket는 네트워크 통신을 위한 도구로, 무전기나 전화기와 같이 프로그램 간에 데이터를 주고받을 수 있게 해준다. 이는 특정한 인스턴스가 아닌 통신 규격을 나타낸다.

steady-record.tistory.com

[Spring] WebSocket 기초 예제

2023. 12. 1. 22:01

Socket? WebSocket?🔎

 

- Socket

  • Socket는 네트워크 통신을 위한 도구로, 무전기나 전화기와 같이 프로그램 간에 데이터를 주고받을 수 있게 해준다. 이는 특정한 인스턴스가 아닌 통신 규격을 나타낸다.
  • 프로그래밍 언어들은 이미 Socket을 구현해두어 프로그래머가 손쉽게 네트워크 통신을 구현할 수 있다.
  • 브라우저도 네트워크를 통해 데이터를 주고받을 때 Socket를 사용하여 통신한다. 그러나 최근에는 웹 기술의 발전으로 인해 Socket 사용률이 줄어들었다.

- WebSocket

  • WebSocket은 웹상에서 동작하는 Socket으로, 기존의 웹 통신 방식과는 다르게 양방향 통신을 지원한다.
  • Ajax와 유사한 면이 있지만 Ajax는 단방향 통신에 주로 사용되며, WebSocket은 웹 페이지에서 서버로부터 데이터를 받는 것뿐만 아니라, 웹 페이지에서 서버로 데이터를 보내는 양방향 통신이 가능하다. 이를 통해 다양한 실시간 데이터를 웹 애플리케이션에 적용할 수 있다.
  • WebSocket은 기존의 웹 통신 방식보다 빠르고 효율적이며, 실시간 기능을 제공하기 위해 널리 사용되고 있다.

WebSocket 프로젝트🔎

WebSocket를 이해할 수 있는 프로젝트를 진행한다.

 

- 파일 구성

상위 패키지(폴더) 하위 패키지(폴더) 파일명
src/main/java com.test.controller SocketController.java
  com.test.server SocketServer.java
WEB-INF views test.jsp

 


- 환경 설정

1. 자바 및 스프링 버전 변경 - pom.xml 

2. 의존성 추가

 

WebSocket를 사용하기 위한 의존성을 추가한다.

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-websocket</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
	
		<dependency>
			<groupId>javax.websocket</groupId>
			<artifactId>javax.websocket-api</artifactId>
			<version>1.1</version>
		</dependency>

 


- SocketServer.java

WebSoket 으로 클라이언트와 서버가 통신할 때는 Controller의 역할은 view를 띄어주는 역할만 존재한다. 

package com.test.controller;

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

@Controller
public class SocketController {
	
	@GetMapping(value = "/test.do")
	public String test(Model model) {
		return "test";
	}
}

 


📢 잠깐 여기서, 클라이언트와 SocketServer 의 관계

1. 일방적인 데이터 송수신

웹 소켓을 사용하면 양방향 통신이 가능하며, 클라이언트와 서버 간에 언제든 데이터를 주고 받을 수 있다. 이는 HTTP와는 다르게 일방적인 클라이언트에서 요청하고 서버가 응답하는 구조가 아닌, 양쪽에서 언제든 데이터를 주고 받을 수 있다.

 

2. 클라이언트의 연결 시작

Socketserver는 클라이언트가 누군지 모르기 때문에  웹 소켓에서는 클라이언트가 먼저 연결을 시작해야 한다. 이를 통해 클라이언트는 서버에게 연결을 요청하고, 서버는 해당 연결을 수락하여 양방향 통신이 가능한 상태가 된다.


3. @ServerEndpoint

@ServerEndpoint 어노테이션은 Java에서 웹 소켓 엔드포인트를 정의하는 데 사용된다. 종단점은 웹 소켓 서버에서 클라이언트의 요청을 처리하고, 연결을 관리하는 핵심 구성 요소이다.

 

4. 연결 지속성

한 쪽에서 일방적으로 연결을 끊어버리지 않는 한, 웹 소켓 연결은 계속해서 지속된다. 이 특징은 HTTP와 달리 지속적인 양방향 통신이 가능하도록 한다.


- WebSocket 연결하기

위 2번 특징으로 클라이언트(jsp)에서 먼저 연결 시도를 한다.

화면의 연결 버튼을 누르면 4가지 단계가 이뤄져야한다.

1. 소켓 생성

2. 서버 접속(연결)

3. 통신

4. 서버 접속 해제(종료)

 

test.jsp

test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocketTest</title>
<link rel="stylesheet" href="https://me2.do/5BvBFJ57">
</head>
<body>
	<!-- test.jsp -->
	<h1>WebSocket <small>연결 테스트</small></h1>
	
	<div>
		<button type="button" class="in" id="btnConnect">연결하기</button>
		<button type="button" class="out" id="btnDisConnect">종료하기</button>
	</div>
	<hr>
	
	<div>
		<input type="text" class="long" id="msg">
		<button type="button" id="btnMsg">보내기</button>
	</div>
	
	<div class="message full"></div>
	<script src="https://code.jquery.com/jquery-1.12.4.js" ></script>
</body>
</html>

 

 

test.jsp (JavaScript)

	<script>
		const url = 'ws://localhost:8090/socket/testserver.do';
		
		let ws; //웹 소켓 참조 변수
        
		$('#btnConnect').click(function() {
			
			ws = new WebSocket(url);
			
			ws.onopen = function(evt) {
				log('서버와 연결하였습니다.');
			};
			
			ws.onclose = function(evt) {
				log('서버와 연결이 종료되었습니다.');
			};
			
			ws.onmessage = function(evt) {
				log(evt.data);
			};
			
			ws.onerror = function(evt) {
				log('에러가 발생했습니다.' + evt);
			};
		});
		
		$('#btnDisConnect').click(function() {
			ws.close();
			log('서버와 연결 종료를 시도합니다.');
			
		});
		
		function log(msg) {
			$('.message').prepend(`
				<div>[\${new Date().toLocaleTimeString()}] \${msg}</div>		
			`);
		}
		
		$('#btnMsg').click(function() {
			ws.send($('#msg').val());
			log('메시지를 전송했습니다.');
			
			$('#msg').val('');
		});
		
	</script>

 

 

const url = 'ws://localhost:8090/socket/testserver.do';

클라이언트와 서버 연결 할 때는 'http' 이 아닌 WebSocket 의 약자인 'ws' 프로토콜을 사용한다.

위 주소 중 testserver.do는 서버의 @ServerEndpoint 와 연결하여 클라이언트에서 서버를 매핑하는 역할을 한다. 

 

ws = new WebSocket(url);

WebSocket 메소드를 사용하면 소켓 생성과 동시에 서버에 접속 시도한다.

 

웹 소켓 이벤트

웹 소켓에는 각종 행위들이 이벤트로 구현되어있어, 클라이언트는 비동기 방식으로 다른 업무를 하다가 이벤트로 연락 오는 것을 확인할 수 있다.

ws.onopen : 서버측에서 소켓 연결을 받아들이고 연결이 되는 순간 이벤트가 발생한다.

ws.onclose : 웹 소켓 연결이 닫힐 때 발생한다.

ws.onmessage : 웹 소켓으로부터 메시지를 수신했을 때 발생한다.

ws.onerror : 웹 소켓 통신 중 에러가 발생했을 때 호출된다.

 

 

ws.send($('#msg').val());

연결된 서버에게 메시지를 전송할 때는 ws.send('전달할 메시지') 를 사용한다.

메시지를 서버에 전송하고나면 다음 입력을 위해 초기화를 한다.

 

SocketServer.java

package com.test.server;

@ServerEndpoint("/testserver.do")
public class SocketServer {

	@OnOpen
	public void handelOpen() {
		System.out.println("클라이언트가 접속했습니다.");
	}
	
	@OnClose
	public void handleClose() {
		System.out.println("클라이언트가 종료했습니다.");
	}
	
	@OnMessage
	public String handleMasseage(String msg) {
		System.out.println("클라이언트가 보낸 메시지: " + msg);
		
		return "(응답)" + msg;
	}
	
	@OnError
	public void handleError(Throwable e) {
		System.out.println("에러 발생 " + e.getMessage());
	}
	
}

 

@ServerEndpoint("/testserver.do")

위에서 클라이언트가 testserver.do 를 매핑하였다.

 

@OnMessage

서버 측에서 웹 소켓 이벤트를 처리하기 위해 어노테이션을 사용한다.

이 어노테이션은 클라이언트가 서버에게 메시지를 전송했을 때(ws.send) 반응하는 이벤트이다.  전달한 메시지가 매개변수로 설정된다.

 

보통 메소드 이름은 'handle + 이벤트' 으로 작명한다.

 

연결 및 메시지 전송 모습

 

연결, 전송, 연결종료
공유하기
게시글 관리
구독하기