카테고리 없음

Socket 통신, 간단한 소켓 채팅 웹

Lahezy 2023. 7. 17.
728x90

Socket 통신

  • 클라이언트와 서버 간의 TCP 연결을 길게 유지하고 서로 양방향으로 데이터를 전달하게 해주는 통신 규약의 일종이다.
  • HTTP 프로토콜는 stateless 하다면 socket 통신은 지속적인 연결을 유지할 수 있다.
  • 웹 소켓을 이용하여 클라이언트 간의 서버간에 실시간 푸시 알림, 채팅등의 실시간 기능을 지원할 수 있다
  • TCP 프로토콜위에서 동작하며 네트워크 계층에서 데이터 전송을 보장한다
  • 소켓 통신 초기 연결을 위해서 HTTP를 사용한다.

 

Http 통신

클라이언트가 서버에 요청을 보내고 서버는 클라이언트에 응답을 보내는 단방향 통신이다

클라이언트는 요청을 보내기 전 연결을 맺어야 하고 서버는 요청에 대한 응답을 보낸 후 연결을 종료한다

 

웹소켓의 동작원리

이미지 출처 : https://dev-gorany.tistory.com/212

1. 클라이언트가 서버에 WebSocket 연결 요청을 보낸다.
이 요청은 HTTP 프로토콜을 사용하여 보내지며, 요청 헤더에 "Upgrade"와 "Connection" 필드가 포함된다.

 

2. 서버는 클라이언트의 요청을 확인하고 WebSocket 연결을 수락한다.
서버는 HTTP 응답을 반환하며, 응답 헤더에 "Upgrade"와 "Connection" 필드를 포함시킨다. 또한, "Sec-WebSocket-Accept" 필드를 포함하여 요청의 유효성을 검증한다.

 

3. 클라이언트는 서버의 응답을 받으면, WebSocket 연결이 수락되었다는 것을 확인하고 연결을 확립한다. 이후부터는 클라이언트와 서버 간의 연결이 지속적으로 유지된다.

 

4. 연결이 확립된 후, 클라이언트와 서버는 웹 소켓 프레임 단위로 데이터를 주고받는다. 클라이언트나 서버는 원하는 시점에 데이터를 보내고, 상대방은 해당 데이터를 수신하여 처리한다

 

5. 클라이언트나 서버는 연결을 종료하기 위해 명시적으로 연결을 닫을 수 있다. 이를 위해 클라이언트나 서버는 웹 소켓 프레임에 종료 코드를 포함시켜 상대방에게 연결 종료를 알린다. 상대방은 이를 수신하고 연결을 닫는다

 

웹 소켓 프레임의 구성요소

https://swiftymind.tistory.com/104

프레임 : 데이터 전송의 단위

마스킹 키, 페이로드 데이터 등..

 

보안 고려 사항

웹 소켓은 사이트 간 스크립팅(XSS) 및 사이트 간 요청 위조(CSRF) 공격을 포함하여 웹 응용 프로그램에 보안 취약성을 초래할 수 있다. 이러한 공격을 방지하려면 보안 인증 및 권한 부여 메커니즘을 사용하는 것이 중요하다.

ws://를 통해 비암호화된 웹 소켓 연결을 설정, wss는 WebSocket Secure을 사용하는 웹 애플리케이션의 URL 경로로 웹 소켓 연결을 보안 소켓 계층

(SSL/TLS)을 통해 암호화된 연결로 설정할 수 있다.

 

 

간단한 웹 소켓이용 채팅 코드

깃허브링크 : 

https://github.com/juhee77/java-likeion/tree/b445d733d5c783ee747dae60851a7f8ec12cb773/websocket/chat 

WebSocketConfigurer

package com.example.chat.config;

import com.example.chat.SimpleChatHandler;
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
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer {
    private final SimpleChatHandler simpleChatHandler;

    @Override
    //WebSocketHandler 객체를 등록하기 위한 메소드
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        //다음으로 들어오는 URL을 처리한다. 모든 클라이언트가 접근할 수 있도록 .setAllowedOrigins(”*”)로 설정해 놓았다.
        registry.addHandler(simpleChatHandler, "ws/chat").setAllowedOriginPatterns("*");
    }
}

WebSocket 구성을 정의하고, WebSocketHandler 및 관련 구성 요소를 등록하여 WebSocket을 활성화한다
end point를 “/chat”으로 설정하고 모든 클라이언트에서 접속할 수 있도록. setAllowedOrigins(”*”)로 열어준다.

 

SimpleChatHandler

package com.example.chat;

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 SimpleChatHandler extends TextWebSocketHandler {

        //관리하는 세션들
    private final List<WebSocketSession> sessions = new ArrayList<>();

    //웹 소켓 세션이 성립되었다. 연결된 사용자를 구분할 수 있게 된다.
    //웹 소켓 최초 연결시 실행
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session); //현재 사용자 저장
        log.info("connected with session id :{}, total Session : {}", session.getId(), sessions.size());
    }

    @Override
    //소켓의 메세지를 받으면 실행될것 이다. (페이로드를 문자열로 자동으로 변환해준다)
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //데이터를 받는다.
        String payload = message.getPayload();
        log.info("receiver : {}", payload);
        //해당 정보를 다시 전달한다.
        for (WebSocketSession connected: sessions) {
            connected.sendMessage(message);
        }
    }

    @Override
    //WebSocket 연결이 종료 되었을때
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.info("connection with closed : {} ");
        sessions.remove(session); //세션을 삭제한다.
    }
}

TextWebSocketHandler

텍스트 기반의 메시지를 주고받을 수 있도록 도와주는 역할을 한다. 기본적으로 WebSocketHandler 인터페이스를 구현하며, WebSocket 연결의 여러 이벤트를 처리할 수 있는 메서드를 제공한다.

afterConnectionEstablished() : 연결 초기화

handleTextMessage() : 메시지 수신

handleTransportError() : 에러 처리

afterConnectionClosed() : 연결 종료

supportsPartialMessages() : 메시지 부분전송 지원을 확인

 

결과 화면

단점 :

만약 한 명에게만 전달하려고 한다면? → 사용자 이름을 연결하려면? 세션마다 유저의 정보를 저장해야 한다?? 불편 → STOMP를 활용 : 메시지 큐 시스템을 활용하여 클라이언트와 서버 간의 통신을 구현한다. STOMP는 웹 소켓과 함께 사용되어 웹 기반의 실시간 통신에 자주 활용되는 프로토콜이다.

Reference

HTTP 통신과 Socket 통신의 차이점

[네트워크, Network]3. WebSocket, 웹 소켓에 대해서

웹소켓으로 개발하기 전 알아야 할 것들 | 요즘 IT

[Spring Boot] WebSocket과 채팅 (1)

Websocket Protocol 분석

728x90

댓글