상세 컨텐츠

본문 제목

[SPRING BOOT] 2521 과몰입러의 스프링부트 웹소켓 채팅 서비스 만들기(1) 자바소스

JAVA/SPRING

by ranlan 2022. 3. 14. 22:38

본문

728x90

블로그 쓰다 한번 날아가서 2회차 쓰는 중 티스토리 넘 빡쳐 🤯

 

지난 주말 드라마 <스물 다섯, 스물 하나> 보다가 삘 받아서 만든 채팅 웹 서비스

백이진도 백이진이지만.. 태리야끼.. 넘 귀여워...... 나희도 사랑해..

 

아무튼 이전에 만들던 게시판 살짝 질리기도 했고 웹 소켓 이용한 개발도 해보고 싶었어서 일요일 방송 끝나자마자 시작했당

오늘부터 자사 비대면 신입교육인데 교육 후반부에 좀 늘어져서 귀로는 수업듣고 눈과 손으로는 플젝했당 ㅎㅋ

어째저째 이틀이지만 대충 총 5시간? 좀 안되게 걸려서 만든 스프링부트 채팅 웹 서비스

나름 PC통신 시절 흉내내려고 배경은 파란색, 글씨는 하얀색으로 바꿨는데.. 뭐 부트스트랩을 이용하긴 했다만은 혼자서 웹개발할때 프론트 정말 힘들다,,^^

 

 

 

웹 소켓(WebSocket)이란

웹 소켓은 TCP 연결에 완전한 이중 통신 채널을 제공하는 컴퓨터 통신 프로토콜이다.

웹 소켓은 HTTP 프로토콜을 사용하는 네트워크 데이터 통신의 단점을 보완한다. 모든 HTTP 통신은 클라이언트가 요청을 보내고 그 요청에 따라 서버가 응답하는 형태이며 웹 서버는 응답을 보낸 후 웹 브라우저와 연결을 끊는다. 양쪽이 데이터를 동시에 보내는 것이  아니기 때문에 이러한 통신 방식을 반이중 통신(Half Duplex)이라고 한다. 이러한 방식은 매 요청과 응답마다 연결을 수립하고 끊는 과정을 반복하기 때문에 유사한 통신을 계속 반복해야 한다는 비효율성 문제가 있었다.

실시간 통신에 대한 이러한 문제를 해결하기 위해 HTML5부터 웹 소켓이 등장하였다. 

웹 소켓은 실시간 양방향 통신을 지원하며 한번 연결이 수립되면 클라이언트와 서버 모두 자유롭게 데이터를 주고받을 수 있다.

웹 소켓과 HTTP 두 프로토콜 모두 OSI 모델의 7계층(애플리케이션), TCP/IP 계층의 4계층(애플리케이션)에 의존하지만 웹 소켓은 HTTP 포트 80 및 HTTPS 443 이상으로 실행되도록 설계되어 있으며 HTTP 프록시 및 중간 계층을 지원하도록 설게되어있어 HTTP 프로토콜과 호환된다. 호환성을 달성하기 위해 웹 소켓 핸드 셰이크는 HTTP 업그레이드 헤더를 사용하여 HTTP 프로토콜 내의 웹 소켓 프로토콜로 변경된다.

 

[정리] 웹 소켓은 양방향 소통실시간 네트워킹을 지원한다.

 

* 단방향 통신(Simplex)

한쪽 방향으로만 전송이 가능한 방식(라디오, TV 등). 데이터의 흐름이 한 방향으로만 한정되어 있다.

* 반이중 통신(Half Duplex)

양방향 전송이 가능하지만 동시에 양쪽 방향에서 전송할 수 없는 방식(무전기, 모뎀을 이용한 데이터 통신 등). 주 컴퓨터와 단말기가 있을 때, 주 컴퓨털가 단말기에 데이터를 보내는 동안은 단말기에서 데이터를 입력할 수 없으며 반대로 단말기에서 데이터가 입력되고 있는 동안은 주 컴퓨터가 단말기로 데이터를 보낼 수 없다.

* 전이중 통신(Full Duplex)

동시에 양방향 전송이 가능한 방식(전화, 전용선을 이용한 데이터 통신 등)으로, 전송량이 많고 전송 매체의 용량이 클 때 사용한다. 송신과 수신을 동시에 할 수 있는 방식이다. 

 

 

웹 소켓 작동방식

웹 소켓은 TCP/IP 위에서 동작하기 때문에 최초 접속에서만 일반적인 HTTP 프로토콜로 핸드쉐이킹을 수행한다. 이후 소켓을 HTTP 기반의 웹 소켓 프로토콜(ws)로 운영된다.

 

https://velog.io/@hahm0726/WebSocket1

 

 

프로젝트 생성과 웹 소켓 설정

내 깃허브에서 코드 보기 https://github.com/ijo0r98/chatting-web

 

GitHub - ijo0r98/chatting-web: 2521에 빠져 만드는 스프링부트 채팅 웹

2521에 빠져 만드는 스프링부트 채팅 웹. Contribute to ijo0r98/chatting-web development by creating an account on GitHub.

github.com

스프링부트 프로젝트 생성은 → https://start.spring.io/

 

웹 개발시 필요한 의존성들과 아직 데이터베이스 사용 계획은 없지만 고도화를 위해 JPA, MySQL도 미리 추가해주었다.

이번 프로젝트의 템플릿 엔진은 JSP가 아닌 Thymleaf를 사용할 예정

 

build.gradle에 직접 추가도 가능하다. 추가 후 Gradle Reload 는 필수!

dependencies {
	....

	// socket
	implementation 'org.springframework.boot:spring-boot-starter-websocket'

	....
}

 

 

핸들러와 설정 파일

📄  SocketHandler

서버에서 다수의 클라이언트가 보낸 메시지를 처리하기 위해 핸들러가 필요하다.

소켓으로 텍스트 데이터만 다룰것이기 때문에 구현하는 인터페이스는 스프링에서 제공하는 TextWebSocketHandler(BinaryWebSocketHandler도 있다.)

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
public class SocketHandler extends TextWebSocketHandler {

    private static List<WebSocketSession> list = new ArrayList<>();

    /* 텍스트 메시지 메서드 */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        log.info("payload: " + payload);
        for(WebSocketSession sess: list) {
            sess.sendMessage(message);
        }
    }

    /* 클라이언트가 접속 요청 시 호출*/
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        list.add(session);
        log.info(session + " 클라이언트 접속 요청");
    }

    /* 클라이언트가 접속 해제 시 호출 */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.info(session + " 클라이언트 접속 해제");
        list.remove(session);
    }
}

기본으로 오버라이딩해야될 메서드로 handleTextMessage()가 주어지는데 소켓 접속 요청과 해제시에도 호출되는 메서드도 함께 오버라이딩 해주었다.

다른 사람들 블로그를 참고하며 코드 한줄한줄, 클래스나 인터페이스 모든 의미를 꼼꼼히 보기 보다는 전체적인 흐름을 파악하는데 초점을 두었다.

그래서 사실 자세한 내용은 아직 잘 모른다..🥲

 

📄 WebSocketConfig

웹 소켓을 활성화하기 위한 설정 파일로 WebSocketConfigurer 인터페이스를 상속받는다..

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration // 설정 파일 등록
@RequiredArgsConstructor // final 필드 생성자 생성(의존성 주입)
@EnableWebSocket // 웹 소켓 활성화
public class WebSocketConfig implements WebSocketConfigurer {

    private final SocketHandler socketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(socketHandler, "ws/chat").setAllowedOrigins("*");
    }
}

웹 소켓에 접속하기 위한 Endpoint는 /chat으로 설정하고 도메인이 다른 서버에서도 접속 가능하도록 setAllowedOrigins("*")를 추가해주었다.

 

 

크롬 익스텐션 테스트

크롬 익스텐션 Simple WebSocket Client 다운로드 → https://chrome.google.com/webstore/detail/simple-websocket-client/pfdhoblngboilpfeibdedpjgfnlcodoo?hl=ko 

 

Simple WebSocket Client

Construct custom Web Socket requests and handle responses to directly test your Web Socket services.

chrome.google.com

 

아직 화면을 구성하기 전 크롬에서 제공하는 소켓 테스트 익스텐션 Simple WebSocket Client로 테스트를 해보았다. 

먼저 일단 웹 서버를 켜고..

 

url에 위의 설정파일에서 설정한 url(ws://localhost:8080/ws/chat)을 입력한다. (* 웹 소켓 프로토콜의 요청은 ws://~로 시작)

그리고 소켓으로 보낼 내용을 파란색 박스 Request에 입력하여 전송해보면 서버에서 전달받은 메시지가 아래 출력된다.

 

소켓 연결 일단 성공!

 

 

728x90

관련글 더보기

댓글 영역