*JAVA/JSP 35번 글의 시점부터는 노트북이 고장나는 바람에.. 다른 분의 글과 이전에 올렸던 글들을 참고하여, 다른 데스크탑의 윈도우 환경에 환경설정을 다시 진행한 후 작성하였습니다. 환경설정 관련 글들은 아래를 참고해 주세요.
- JDK11 설치 및 환경 변수(JAVA_HOME) 설정 - CLASSPATH는 추가하지 않음
자바(JAVA) 11 설치 및 환경설정 | 자바 11 환경 변수
자바로 코딩 공부를 하려면 개발 할 수 있는 환경을 만들어 주어야 한다. 그 순서를 먼저 작성하자면JAVA SE JDK 설치 -> JAVA 환경 변수 설정 -> IDE 설치 이렇게 볼 수 있겠다. 이 포스팅은 자바로 개
velog.io
- 톰캣 설치, 이클립스 설치 - 이 글을 쓰는 시점에서는 Tomcat 8버전이 없어, Tomcat 9버전 설치
JSP) JDK, 이클립스(eclipse), 톰캣 설치 및 환경 설정
1. JDK 설치 → Path 설정 2.eclipse JAVA EE버전 다운로드 3.웹컨테이너 톰캣 설치 →톰캣 환경설정 1. JDK 설치 - JAVA) 1. JDK 참고하여 설치하고 설정한다. -https://storyblogger.tistory.com/15?category=984696 2. 구글에
storyblogger.tistory.com
- 이클립스 JDK 버전 설정 - JDK11로 설정
[이클립스] JDK 버전 바꾸는 법
스프링을 사용하는 에러가 난다? 그러면 JRE 버전을 확인해보자! 프로젝트의 JRE System Library의 오른쪽을 살펴보면 [JavaSE-17]이라고 되어있다. 스프링이나 하이버네이트를 사용할 때, 자바 8이나 자
myvelop.tistory.com
- JDK 설치 및 환경 변수(JAVA_HOME) 설정, 톰캣 설치, 이클립스 설치 및 JDK 버전 설정 이후~ ⇒ 톰캣 버전과 jsp 파일 경로는 글 내용과 다르게 아래 이미지와 같음
JAVA/JSP 1. 개발 환경 구축 - 이클립스 기본 설정
*JDK 설치 및 환경 변수(JAVA_HOME) 설정, 톰캣 설치, 이클립스 설치를 완료한 상태OpenJDK 11: 자바 프로그램을 컴파일하고 실행해주는 기본 도구*이클립스 JDK-17이 설치되어있어서, https://coding-house.tisto
keep-programming-study.tistory.com
JAVA/JSP 1. 개발 환경 구축 - JSP 예제 테스트
1. 프로젝트 생성1) [File] → [New] → [Dynamic Web Project] 선택 2) 프로젝트 설정 화면 → Project name: HelloJSP, Target runtime: Apache Tomcat v9.0, Dynamic web module version: 4.0으로 설정 후 Next 클릭 3) 자바 소스 파일
keep-programming-study.tistory.com
JAVA/JSP 1. 개발 환경 구축 - 마지막 추가 설정
1. 외부 웹 브라우저로 실행하기-크롬이클립스는 웹 애플리케이션 실행 시, 자체 브라우저를 통해 실행 결과 출력웹 애플리케이션 배포 시 사용자는 크롬/파이어폭스 같은 전용 웹 브라우저로
keep-programming-study.tistory.com
- 오라클(Oracle Database 11gR2 Express Edition) 설치 및 설정
JAVA/JSP 14. 데이터베이스 - 특징, 오라클 설치(Oracle Database 11gR2 Express Edition), 사용자 계정 생성 및
1. 데이터베이스의 특징우리가 매일 PC나 스마트폰을 통해 접하는 거의 모든 웹 애플리케이션에서 사용함매일 업데이트되는 뉴스나 날씨 등의 정보는 데이터베이스가 없다면 클라이언트에 전달
keep-programming-study.tistory.com
JAVA/JSP 15. 데이터베이스 - 테이블 및 시퀀스 생성, JDBC 설정 및 데이터베이스 연결
*회원제 게시판 만들기-회원 인증 필요4. 테이블 및 시퀀스 생성1) 테이블 생성(1) member 테이블 - 아이디, 패스워드, 이름, 가입 날짜테이블 정의컬럼명데이터 타입 null 허용 키 기본값 설명idvarchar2
keep-programming-study.tistory.com
JAVA/JSP 16. 데이터베이스 - 커넥션 풀로 성능 개선, 간단한 쿼리 작성 및 실행
6. 커넥션 풀로 성능 개선웹은 클라이언트의 요청에 서버가 응답하는 구조→ Connection 객체 생성 때마다 네트워크 통신이 이뤄지며, 시간이 걸리는 작업들이 수반됨 == 시스템 성능에 큰 영향을
keep-programming-study.tistory.com
- 시퀀스 설정
JAVA/JSP 15. 데이터베이스 - 테이블 및 시퀀스 생성, JDBC 설정 및 데이터베이스 연결
*회원제 게시판 만들기-회원 인증 필요4. 테이블 및 시퀀스 생성1) 테이블 생성(1) member 테이블 - 아이디, 패스워드, 이름, 가입 날짜테이블 정의컬럼명데이터 타입 null 허용 키 기본값 설명idvarchar2
keep-programming-study.tistory.com
1. 사전 지식
1) 소켓(socket)
- 네트워크에서 동작하는 프로그램의 종착점(endpoint)
- IP 주소와 포트 번호로 이루어져 있으며, 서버-클라이언트 간 양방향 통신을 할 수 있게 해주는 소프트웨어 장치
-> 클라이언트와 서버에서 모두 소켓을 생성하여 연결해줘야 함 - 자바에서는 이 기능을 클래스로 만들어 지원
- 서버에서 서버용 소켓(ServerSocket)을 생성하고 클라이언트의 접속 대기
- 클라이언트가 소켓(Socket)을 생성하여 서버로 연결 요청
- 서버가 접속 허가(accept)
- 서버와 클라이언트에서 각각 통신을 위한 I/O 스트림 생성
- 스트림을 통해 서버와 클라이언트가 통신(write->read)
- 클라이언트가 모든 작업을 마친 후 소켓 종료(close)
- 서버는 새로운 클라이언트의 접속을 위해 대기(accept) or 종료(close)
2) 웹소켓(WebSocket)
- 클라이언트의 요청에 응답한 후에도 연결을 그대로 유지하는 연결 지향 방식(connection oriented)
-> 별도 요청 없이도 서버는 언제든 클라이언트로 데이터 전송 가능 - 톰캣 9.0.x 버전 사용 시, 웹소켓 버전 1.1
- 소켓과 다르게 어노테이션을 사용하여 구현
@ServerEndpoint | 웹소켓 서버의 요청명 설정 |
@OnOpen | 클라이언트가 접속했을 때 요청되는 메서드 정의 |
@OnMessage | 클라이언트로부터 메시지가 전송되었을 때 실행되는 메서드 정의 |
@OnClose | 클라이언트 접속 종료 시 실행되는 메서드 정의 |
@OnError | 에러 발생 시 실행되는 메서드 정의 |
2. 프로젝트 구상
- 에코 클라이언트/서버 모델 적용
-> 클라이언트가 서버로 보낸 메시지를, 접속해있는 모든 클라이언트로 그대로 전송 - 실제 웹소켓 서버 구현 시, 메시지를 보낸 클라이언트(나)를 제외한 나머지 클라이언트에게만 메시지를 전송할 수 있도록 구현
-> 특정 클라이언트에게만 전송할 수 있는 귓속말 기능도 추가
3. 채팅 서버/채팅 클라이언트 구현
1) 채팅 서버 구현(ChatServer.java)
// Java Resources/src/websocket/ChatServer.java
package websocket;
import java.io.IOException;
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;
// 1. 웹소켓 서버의 요청명을 지정하여, 해당 요청명으로 접속하는 클라이언트를 이 클래스가 처리
// -> HTTP가 아닌 ws 프로토콜 사용
@ServerEndpoint("/ChatingServer")
public class ChatServer {
// 2. 새로 접속한 클라이언트의 세션을 저장할 컬렉션 생성
// -> syschronizedSet으로 여러 클라이언트가 동시에 접속해도 문제가 생기지 않도록 동기화
private static Set<Session> clients
= Collections.synchronizedSet(new HashSet<Session>());
// 3. 클라이언트 접속 시 실행 - clients 컬렉션에 클라이언트의 세션 추가
@OnOpen
public void onOpen(Session session) {
clients.add(session); // 세션 추가
System.out.println("웹소켓 연결: "+session.getId());
}
// 4. 메시지를 받으면 실행 - 클라이언트가 보낸 메시지와, 클라이언트와 연결된 세션이 매개변수
@OnMessage
public void onMessage(String message, Session session) throws IOException {
System.out.println("메시지 전송: "+session.getId() + ":"+message);
// 5. 동기화 블록
synchronized (clients) {
// 6. 모든 클라이언트에 메시지 전달
for (Session client : clients) {
// 7. 메시지를 보낸 클라이언트는 제외하고 메시지 전달
if (!client.equals(session)) client.getBasicRemote().sendText(message);
}
}
}
// 8. 클라이언트와의 연결이 끊기면 실행 - 해당 클라이언트의 세션 삭제
@OnClose
public void onClose(Session session) {
clients.remove(session);
System.out.println("웹소켓 종료: "+session.getId());
}
// 9. 에러 발생 시 실행
@OnError
public void onError(Throwable e) {
System.out.println("에러 발생");
e.printStackTrace();
}
}
2) 채팅 클라이언트 구현
(1) 채팅 참여 화면 작성(JSP 파일) - MultiChatMain.jsp
<!-- src/main/webapp/websocket/MultiChatMain.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>웹소켓 채팅</title>
</head>
<body>
<script>
// 채팅창을 팝업창으로 열어주는 함수
function chatWinOpen() {
var id = document.getElementById("chatId");
if (id.value == "") {
alert("대화명을 입력 후 채팅창을 열어주세요");
id.focus();
return;
}
// 대화명을 매개변수로 전달해 채팅창 띄움
window.open("ChatWindow.jsp?chatId=" + id.value, "", "width=320, height=400");
// 새로운 대화명 입력 가능하도록 기존 내용 삭제
id.value = "";
}
</script>
<h2>웹소켓 채팅 - 대화명 적용해서 채팅창 띄워주기</h2>
대화명 : <input type="text" id="chatId" />
<button onclick="chatWinOpen();">채팅 참여</button>
</body>
</html>
(2) 채팅창 작성(JSP 파일) - ChatWindow.jsp
<!-- src/main/webapp/websocket/ChatWindow.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<title>웹소켓 채팅</title>
<script>
var webSocket = new WebSocket("<%= application.getInitParameter("CHAT_ADDR") %>/ChatingServer");
var chatWindow, chatMessage, chatId;
// 채팅창이 열리면 대화창, 메시지 입력창, 대화명 표시란으로 사용할 DOM 객체 저장
window.onload = function() {
chatWindow = document.getElementById("chatWindow");
chatMessage = document.getElementById("chatMessage");
chatId = document.getElementById('chatId').value;
}
// 메시지 전송
function sendMessage() {
// 대화창에 표시
chatWindow.innerHTML += "<div class='myMsg'>" + chatMessage.value + "</div>"
webSocket.send(chatId + '|' + chatMessage.value); // 서버로 전송
chatMessage.value = ""; // 메시지 입력창 내용 지우기
chatWindow.scrollTop = chatWindow.scrollHeight; // 대화창 스크롤
}
// 서버와의 연결 종료
function disconnect() {
webSocket.close();
}
// 엔터 키 입력 처리
function enterKey() {
if (window.event.keyCode == 13) { // 13은 'Enter' 키의 코드값
sendMessage();
}
}
// 웹소켓 서버에 연결됐을 때 실행
webSocket.onopen = function(event) {
chatWindow.innerHTML += "웹소켓 서버에 연결되었습니다.<br/>";
};
// 웹소켓이 닫혔을 때(서버와의 연결이 끊겼을 때) 실행
webSocket.onclose = function(event) {
chatWindow.innerHTML += "웹소켓 서버가 종료되었습니다.<br/>";
};
// 에러 발생 시 실행
webSocket.onerror = function(event) {
alert(event.data);
chatWindow.innerHTML += "채팅 중 에러가 발생하였습니다.<br/>";
};
// 메시지를 받았을 때 실행
webSocket.onmessage = function(event) {
var message = event.data.split("|"); // 대화명과 메시지 분리
var sender = message[0]; // 보낸 사람의 대화명
var content = message[1]; // 메시지 내용
if (content != "") {
if (content.match("/")) { // 귓속말
if (content.match(("/" + chatId))) { // 나에게 보낸 메시지만 출력
var temp = content.replace(("/" + chatId), "[귓속말] : ");
chatWindow.innerHTML += "<div>" + sender + "" + temp + "</div>";
}
} else { // 일반 대화
chatWindow.innerHTML += "<div>" + sender + " : " + content + "</div>";
}
}
chatWindow.scrollTop = chatWindow.scrollHeight;
};
</script>
<style> <!-- 대화창 스타일 지정 -->
#chatWindow{border:1px solid black; width:270px; height:310px; overflow:scroll; padding:5px;}
#chatMessage{width:236px; height:30px;}
#sendBtn{height:30px; position:relative; top:2px; left:-2px;}
#closeBtn{margin-bottom:3px; position:relative; top:2px; left:-2px;}
#chatId{width:158px; height:24px; border:1px solid #AAAAAA; background-color:#EEEEEE;}
.myMsg{text-align:right;}
</style>
</head>
<body> <!-- 대화창 UI 구조 정의 -->
대화명 : <input type="text" id="chatId" value="${ param.chatId }" readonly />
<button id="closeBtn" onclick="disconnect();">채팅 종료</button>
<div id="chatWindow"></div>
<div>
<input type="text" id="chatMessage" onkeyup="enterKey();">
<button id="sendBtn" onclick="sendMessage();">전송</button>
</div>
</body>
</html>
3) 동작 확인(MultiChatMain.jsp 우클릭 후 Run On Server)
undefined 오류 발생: 콘솔창에는 아무것도 찍히지 않으며, 채팅 자체는 됨 ..?
깜빡 잊고 web.xml에 코드를 추가하지 않아서였음...
<!-- src/main/webapp/WEB-INF/web.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>HelloJSP</display-name>
... 생략 ...
<context-param>
<param-name>CHAT_ADDR</param-name>
<param-value>ws://localhost:8081/HelloJSP</param-value>
</context-param>
</web-app>
코드 추가 후 정상 동작