본문 바로가기
JAVA

Web 채팅 프로그램 만들기

by 집도리잡동사니 2023. 6. 19.
반응형

안녕하세요, 이번에는 웹에서 실시간 채팅 프로그램을 만들어 볼려고합니다!

만드는 이유는... 프로젝트를 하다가... 저만 메신저 아이디가 없어서 저희 솔루션 웹에도 메신저가 있으면 좋겠다는 생각이 들었을 무렵 회사에서 시간이 남아서 잠깐 개발하게되었습니다!

 

제가 사용한 기능은 자바스크립트 WebSocket 기능을 사용하였습니다.

우선 예제 소스를 보여드리겠습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <title>Chat</title>
<%@ include file="/jsp/layout/common/frismBasicInc.jsp" %>
<%
	String userIp = request.getRemoteAddr();
%>
<script>
    var socket;
	$(document).ready(function() {
	    socket = new WebSocket("ws://127.0.0.1:8080/Server");
	  
	    socket.onopen = function(event) {
	        console.log("WebSocket connected");
	    };
	  
	    socket.onmessage = function(event) {
	        var message = event.data;
	        var ip = "<%= userIp%>"; 
	        var currentTime = new Date();
	        var currentHour = timeTemplet(currentTime.getHours());
	        var currentMinute = timeTemplet(currentTime.getMinutes());
	        var currentSecond = timeTemplet(currentTime.getSeconds());
	                
	        if(message.indexOf(ip) >-1){
	        	$("#messages").append("<div style='text-align: right;'>"+currentHour+":"+currentMinute+":"+currentSecond+"<p style='position:relative; background-color:#F0F0F0; padding:10px; border-radius:10px; display:inline-block; margin:5px;'>" + message + "</p></div>");
	        } else {
	        	$("#messages").append("<div><p style='position:relative; background-color:#F0F0F0; padding:10px; border-radius:10px; display:inline-block; margin:5px;'>" + message + "</p>"+currentHour+":"+currentMinute+":"+currentSecond+"</div>");
	        }
	        
	        $("#messages").scrollTop($("#messages")[0].scrollHeight);
	    };
	
	    socket.onerror = function(event) {
	    	console.log("error => "+ JSON.stringify(event));
	    }
	    
	    $("#sendBtn").click(function() {
	    	sendMess();
	    });
	});
	
	function timeTemplet(number){
		if (number < 10) {
			return "0" + number;
		}
		
		return number;
	}
	
	function sendMess() {
		var message = $("#messageInput").val();
		var userId = $("#userId").val();
	    var ip = "<%= userIp%>";
	    
	    $("#messageInput").val("");
	    if(userId.trim() == ""){
		    socket.send("이름안쓴놈("+ip+") : "+ message);	    	
	    } else {
		    socket.send(userId+"("+ip+") : "+ message);
	    }
	}
</script>
</head>
<body style="padding: 5px;">
    <h1>Chat</h1>
    <div id="messages" style="width: 500px; height: 500px; border: 1px solid black; overflow: scroll;"></div>
    <div style="margin-top: 5px;">
	   <input type="text" style="width: 400px; margin-top: 5px;" id="messageInput" onkeypress="javascript:if(window.event.keyCode==13){sendMess()}">
	   <button id="sendBtn" style="margin-top: 5px;" >Send</button>
    </div>
    <div style="margin-top: 5px;">
    	<input id="userId">사용자 이름
    </div>
</body>
</html>

 

혼자서 테스트 하기위해서 브라우저 체크로, 크롬인지, 엣지인지 확인해서 ip를 강제로 할당해서 다른 사람이 쓴것처럼 UI는 대충 꾸몄습니다 저는 회사 사람들과 대충 테스트와 재미를 위해서 UI는 신경쓰지 않았지만. 실제로 서비스를 하고싶은 사람들은 XSS라던가 기타등등 보안취약성을 막으셔야 될꺼같아요.

 

우선 소스를 한줄한줄 설명드리면

socket = new WebSocket("ws://자신의 ip:port/서블릿URL"); // socket 연결

// 저는 소스를 보여드리기위해서 로컬호스트 경로로 하였지만, 실제 다른 사람들이 들어올때는 자신의 IP를 적어주셔야돼요

socket.onoepn = function(event) { // 함수를 통해서 소켓 connection을 맺습니다.

}

socket.onmessage = function(event) { // java단에서 받은 event.data 메시지로 화면에 출력
	
}

socket.onerror = function(data) { //socket error 났을경우 처리 로직

}

socket.send(); // 함수를 통해서 메시지를 java단에 전달합니다.
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

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("/Server")
public class Server /* extends HttpServlet */{
    private static Set<Session> clients = Collections.synchronizedSet(new HashSet<>());

    @OnOpen
    public void onOpen(Session session) {
        clients.add(session);
        System.out.println("새로운 클라이언트가 연결되었습니다.");
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        System.out.println("클라이언트로부터 메시지를 받았습니다: " + message);
//        message = StringUtil.CrossScriptingFilter(message);
        
        // 모든 클라이언트에게 메시지 전송
        synchronized (clients) {
            for (Session client : clients) {
                client.getBasicRemote().sendText(message);
            }
        }
    }

    @OnClose
    public void onClose(Session session) {
        clients.remove(session);
        System.out.println("클라이언트와의 연결이 종료되었습니다.");
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        System.out.println("에러 발생: " + throwable.getMessage());
    }
}

@ServerEndpoint("/Server") 를 통해서 javascript에서 socket = new WebSocket("ws://127.0.0.1:8080/Server"); 경로를 찾아옵니다. 

 

 

public void onOpen(Session session) { // 클라이언트 목록을 추가합니다.

}

@OnMessage
public void onMessage(String message, Session session) throws IOException { 
	// 클라이언트로부터 메시지를 받고 해당 메시지를 다시 클라이언트들에게 전송합니다.
}

@OnClose
public void onClose(Session session) { // 클라리언트가 접속을 해제하였을때 처리하는 로직
    
}

@OnError
public void onError(Session session, Throwable throwable) { // 오류가 났을때 처리 로직
    
}

기본적인 java 로직은 이정도이며 저는 테스트를 위해서 만든거지만 실제 서비스를 하기위해선 UI layout이나 CSS나 손볼곳이 많습니다. 그리고 alert이나 XSS 보안취약성을 필수로 막으셔야합니다!

 

누군가에게 도움이 되길바라며 작성해봅니다.

728x90
반응형

'JAVA' 카테고리의 다른 글

함수형 프로그래밍(Functional Programming) 이란?  (3) 2023.05.21
JAVA 메모리 영역  (0) 2023.03.21
[JAVA] - try(){}, Try-with-resources 란?  (1) 2022.11.07

댓글