본문 바로가기

Spring/Spring

Spring WebSocekt으로 채팅 기능 구현

HTTP 통신에서

웹 브라우저는 사용자가 무언가를 요청(Request) 하면 서버는 데이터를 뿌려주는(Response) 방식으로 작동한다.

하지만 메신저의 경우는 사용자가 브라우저에 접속한 상태...

그렇다고 언제 대화를 주고 받을지 모르는 상태이다.

이 때 사용할 수 있는 게 WebSocket이다.

WebSocket - HTTP 환경에서 전이중 통신(full, duplex, 2-way communication)을 지원하기 위한 프로토콜

 

1) spring-websocket 라이브러리 추가

우선 라이브러리를 가져와야겠지?

pom.xml에 다음 과 같이 spring-websocket 라이브러리를 추가한다.

  <!-- Spring-websocket -->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-websocket</artifactId>
      <version>${org.springframework-version}</version>
  </dependency>

+ json 라이브러리 추가

websocket은 json을 쓰기 때문에 json 라이브러리도 추가해준다

  <!-- json2 -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.11.0</version>
  </dependency>

  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.0</version>
  </dependency>

  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.11.0</version>
  </dependency>

 

 

2) servlet-context.xml에 매핑

servlet-context.xml에서 websocket namespace를 추가해준다.

 

나는 기능을 분리하기 위해 appServlet폴더 안에 socketContext.xml을 만들었다.

servlet-context.xml에는 해당 값을 추가해줬고,

	<beans:import resource="socketContext.xml"/>
	
	<context:component-scan base-package="chat" />

 

socketContext.xml에 다음과 같이 추가해줬다. (servlet-context.xml과 마찬가지로 namespace추가)

	<websocket:handlers>
		<websocket:mapping handler="chatHandler" path="/chat-ws"/>
		<websocket:handshake-interceptors>
			<bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
		</websocket:handshake-interceptors>
	</websocket:handlers>

 

 

3) ChatHandler 클래스 만들기

ChatHandler클래스를 만들어주는데 반드시 TextWebSocketHandler를 상속시켜 만들어야 한다.

이 클래스는 WebSocket 다루는데 사용되어질 예정

*( 나는 자바 밑에 chat으로 패키지를 만들고, ChatHandler클래스를 만들었다.

 마찬가지로 기능을 분리해주기 위해  )

package chat;

import java.util.*;

import org.springframework.stereotype.*;
import org.springframework.web.socket.*;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.handler.*;

// WebSocket을 사용하기 위해서는 반드시 TextWebSocketHandler를 상속해줘야 함

@Component
public class ChatHandler extends TextWebSocketHandler implements WebSocketConfigurer {
	
	private static List<WebSocketSession> list = new ArrayList<WebSocketSession>();
	
	// 사용자가 접속 했을 때 호출되는 메소드
	@Override	
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
		System.out.println(" ### 사용자 접속 ");
		list.add(session);
	}
	
	// 사용자가 메세지를 보냈을 때 호출되는 메소드
	@Override
	protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
		// 전송된 메세지를 List의 모든 세션에 전송
		String msg = message.getPayload();
		for(WebSocketSession s : list) {
			s.sendMessage(new TextMessage(session.getAcceptedProtocol() + msg));
		}
	}
	
	// 사용자 접속 해제했을 때 호출되는 메소드
	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
		System.out.println(" ### 사용자 접속 해제");
		list.remove(session);
	}
	
	@Override
	public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
		registry.addHandler(this, "/chat-ws").setAllowedOrigins("*");
	}

	
}

 

 

4) JSP를 만들어 작동시켜보자

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<div>탕코딩님의 채팅방</div>
	<input type="hidden" id="id" value="탕코딩">
	<div>
		<div id="chatarea" style="width: 300px; height: 300px; border: 1px solid black;"></div>
		<input type="text" id="message" />
		<input type="button" id="send" value="보내기" />
		<input type="button" id="exit" value="나가기" />
	</div>
</body>
<script type="text/javascript">
	// ##### 입장~~~!!
	let websocket;
	connect();
	function connect(){
// 		websocket = new WebSocket("ws://본인 아이 피주소/www/chat-ws");
		websocket = new WebSocket("ws://localhost/www/chat-ws");
			//웹 소켓에 이벤트가 발생했을 때 호출될 함수 등록
			websocket.onopen = onOpen;
			websocket.onmessage = onMessage;
	}
	
	// ##### 연결 되었습니다!
	function onOpen(){
		id = document.getElementById("id").value;
		websocket.send(id + "님 입장하셨습니다.");
	}
	
	// ##### 메세지 보내기 버튼 클릭!
	document.getElementById("send").addEventListener("click", function() {
		send();
	});
	
	function send(){
		id = document.getElementById("id").value;
		msg = document.getElementById("message").value;
		websocket.send(id + ":"+ msg);
		document.getElementById("message").value = "";
	}
	
	function onMessage(evt){
		data= evt.data;
		chatarea = document.getElementById("chatarea");
		chatarea.innerHTML = chatarea.innerHTML + "<br/>" + data
	}
	
	// ##### 연결을 해제합니다!
	document.getElementById("exit").addEventListener("click", function() {
		disconnect();
	});

	function disconnect(){
		id = document.getElementById("id").value;
		websocket.send(id+"님이 퇴장하셨습니다");
		websocket.close();
	}
	
	</script>
	
</html>

 

//  websocket = new WebSocket("ws://본인 아이피 주소/www/chat-ws"); 
websocket = new WebSocket("ws://localhost/www/chat-ws")

여기서 localhost로 하면... 본인 컴퓨터에서는 잘 접속 될텐데

외부에서 접속이 안되더라 ( 나의 경우 같은 공유기 내에서 휴대폰으로 테스트를 해보고 싶었다 )

그래서 그냥 내 아이피 주소 넣고, 접속하니까 되더라.

이름을 똑같이 해놔서 혼자 얘기한 것 같지만.. 실시간으로 채팅했다.

잘 작동된당!! 히히🌸

 

 

참고로 본인 아이피 보는 법 ]

cmd창 띄우고 ipconfig를 입력하면 확인할 수 있다.

반응형

'Spring > Spring' 카테고리의 다른 글

spring-boot View 환경 설정  (0) 2021.04.15
spring-boot 프로젝트 생성  (0) 2021.04.14
스프링과 싱글톤(Singleton)  (0) 2021.01.10
Gradle(그레이들) 설치하기  (0) 2021.01.10
메이븐(Maven)과 그레이들(gradle)  (0) 2021.01.08