Loading...
본문 바로가기
👥
총 방문자
📖
0개 이상
총 포스팅
🧑
오늘 방문자 수
📅
0일째
블로그 운영

여러분의 방문을 환영해요! 🎉

다양한 개발 지식을 쉽고 재미있게 알려드리는 블로그가 될게요. 함께 성장해요! 😊

코딩 정보/React

[React] 소켓 통신 전 개념에 대해 정리해보자

by 꽁이꽁설꽁돌 2025. 4. 11.
728x90
반응형
     

목차

     

     

     

     

     리액트로 소켓 통신을 구현하면서 sockjs, stompjs 등 이전에 써보지 못한 라이브러리를 그냥 쓰기보다는 이해하고

    써야 잘 쓸 수 있을 것 같아 이참에 정리하고자 한다.

     

    websocket이란?

    WebSocket 프로토콜이란 클라이언트와 서버 간의 실시간 양방향 통신을 위한 기술이다. HTTP가 각 요청과 응답 후 연결을 종료하는 connectionless 특성을 갖는 것과 다르게, WebSocket은 한 번의 핸드셰이크를 통해 클라이언트와 서버가 연결을 맺으면 그 연결이 지속된다.

     

    HTTP가 클라이언트의 요청에 따른 서버의 응답으로 이루어진 단방향 통신 방식이라면, WebSocket은 이벤트 중심(event-driven)의 양방향 통신 방식이다. 따라서 서버와 클라이언트 모두 상대방의 요청이 없더라도 데이터를 주고받을 수 있다. 이는 HTTP와는 달리 WebSocket은 애초에 양방향 통신을 위해 만들어진 프로토콜이기 때문이다.

     

     

    추가 정보++

    WebSocket 프로토콜은 기존 HTTP 프로토콜의 한계를 극복하기 위해 만들어졌으므로, HTTP를 지원하는 환경과 호환되도록 설계되었다. 한 예로 WebSocket 역시 HTTP와 같은 80 포트를 사용하며, WSS(WebSocket Secure)의 경우 HTTPS와 같은 443 포트를 사용한다. 또한 연결을 위한 오프닝 핸드셰이크 역시 HTTP 요청의 형태를 취한다. 아래는 클라이언트가 서버로 보내는 WebSocket 오프닝 핸드셰이크 HTTP 요청 헤더의 예시이다(RFC 6455 참조).

    # WS Opening Handshake HTTP Request Header
    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket              # <<< 웹소켓 프로토콜로 업그레이드 요청
    Connection: Upgrade
    ...
    Sec-WebSocket-Protocol: json, chat
    Sec-WebSocket-Version: 25

     

    서버가 이 요청을 받아 Upgrade 헤더에 websocket을 읽으면 정상적인 경우 101 Switching Protocols 응답을 내려준다. 말 그대로 프로토콜을 WebSocket으로 업그레이드한다는 뜻인데, 101 상태 코드를 전송한 직후 서버는 웹소켓 프로토콜을 사용하여 클라이언트와 소통하게 된다.

     

     

    websocket api

    위에 문서를 들어가보면 알 수 있듯이 websocket api는 HTTP의 RESTful API처럼 "URL + 메서드로 명확히 나뉜 API 체계가 아니다.

     

    의문점++

    websocket을 처음 연결 시 get 요청은 왜 있지?

     

    WebSocket에서 GET 요청이 있는 이유는 처음 연결을 시작할 때만 HTTP를 사용하기 때문이다.
    즉, WebSocket은 처음엔 HTTP로 문을 두드리고, 그 다음부터는 자기들만의 독립된 통신으로 전환된다.

     

     

    클라이언트가 서버에 HTTP GET 요청을 보냄

    GET /chat HTTP/1.1
    Host: example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    Sec-WebSocket-Version: 13

     

     

    서버가 OK 하면 이렇게 응답함

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

     

     

    의문점2++

    그렇다면 왜 get 요청을 통해 사전에 확인하는가? preflight가 확실하지 않나?

     

    간단하게 말하면 WebSocket은 CORS 정책의 대상이 아니다.

     

    WebSocket 프로토콜(WS/WSS)과 Cross-Site WebSocket Hijacking (CSWSH)

    SOP(같은 출처 정책)과 CORS(교차 출처 리소스 공유) 정책은 WebSocket에 적용되지 않는다. 이는 이러한 제한들이 HTTP 응답에 대해 적용되는 반면, WebSocket은 WS(WebSocket) 또는 WSS(WebSocket Secure) 프로토콜을 사용하기 때문이다.

    따라서 보안을 위해선 다음과 같이 한다.

     

    WebSocket 보안: SOP와 CORS가 WebSocket에 대해 비효과적이므로, 서버 구현에서는 Upgrade 요청의 Origin 헤더를 확인하여 크로스 사이트 WS 연결을 방지해야 한다.

     

    기존  websocket 방식의 문제점

    1. 모든 클라이언트의 브라우저에서 WebSocket을 지원한다는 보장이 없다.
    2. 또한, 서버/클라이언트 중간에 위치한 Proxy가 Upgrade 헤더를 해석하지 못해 서버에 전달하지 못할 수 있다.
    3. 마지막으로 서버/클라이언트 중간에 위치한 Proxy가 유휴 상태에서 도중에 connection을 종료시킬 수도 있다.

     

     

    WebSocket Emulation

     처음에는 webSocket을 시도하고 실패하면 다른 http 기반 통신 방식으로 전환하는 방식

    이 방식은 브라우저 호환성, 네트워크/프록시 문제, 방화벽 제한 등 다양한 환경적 제약을 자동으로 우회한다.

     

    그래서 아래와 같은 두가지 라이브러리가 존재한다.

    • Socket.IO
      • Node.js 백엔드에서 쓰기 좋고, 많은 부가 기능이 내장되어 있음
      • WebSocket과 유사하지만 독자적인 프로토콜을 사용함
      • 백엔드와 프론트엔드를 모두 Socket.IO로 맞춰야 함
    • SockJS
      • 다양한 서버 언어에서 사용 가능 (특히 Spring에서 많이 사용)
      • WebSocket 표준 프로토콜(STOMP 등) 기반이라 상호 운용성이 높음
      • 자체적으로 많은 기능은 없고, Spring 같은 프레임워크와의 연동으로 기능 확장

     

    sockJs

    이번 프로젝트에서는 sockjs로 소켓 통신을 진행할 것이므로 sockjs 위주로 정리해 보겠다.

    전송 타입은 3가지로 분류 된다.

     

    1. websocket

    양방향 통신 (Full-duplex)을 한다.

    최초 한 번 HTTP 요청으로 연결을 "업그레이드"하고, 이후 서버 ↔ 클라이언트 실시간 통신 가능하다.

     

     

    2.http streaming

    클라이언트가 요청하면, 서버가 응답을 끊지 않고 계속 데이터를 흘려보냄

     

     

    3.http long polling

    클라이언트가 요청을 보내면, 서버는 응답할 데이터가 생길 때까지 기다렸다가 응답

     

     

    WebSocket Emulation Process

    SockJS 클라이언트는 서버의 기본 정보를 얻기위해 GET /info를 호출하는데, 이는 다음과 같은 정보를 얻기 위함이다

     

     

    • 서버가 WebSocket을 지원하는지
    • 전송과정에서 Cookies 지원이 필요한지
    • CORS를 위한 Origin 정보

     

     

    StompJs

    이와 관련된 개념

    - 단순화된 메시징: STOMP는 텍스트 기반 프로토콜로 메시지를 주고 받는 형식이 간단하고 이해하기 쉽다.

     

    - 브로커 지원: STOMP는 RabbitMQ, ActiveMQ 등 여러 메시지 브로커와 호환된다. 따라서 이러한 브로커와 통신하기 위해 STOMP.js 를 사용할 수 있다.

     

    - WebSocket 통합: WebSocket API는 실시간 양방향 통신을 가능하게 하지만, 이를 직접 다루는 것은 복잡하다. STOMP.js는 WebSocket 위에서 동작하며, 메시지 송수신을 보다 간편하게 처리할 수 있게 해준다.

     

    - 구독/발행 : STOMP.js는 Topic과 큐에 메시지를 발행하거나 구독할 수 있는 기능을 제공하여 메시지 기반 애플리케이션을 쉽게 구현할 수 있다.

     

    - 헤더 : 헤더를 통해 인증 처리 로직 또한 구현할 수 있다.

     

    Topic

    - 메시지가 발행(Publish)되고 구독(Subscribe)될 수 있는 대상이다. 메시징 시스템에서 토픽은 특정 주제나 채널을 말하며, 발행된 메시지는 해당 토픽을 구동하는 모든 클라이언트에게 전달된다. 쉽게 말하면 채팅방에 있는 사람들을 채팅방(Topic)에 입장(Subscribe 구독)하게 되면 다른사람들이 보낸 메시지들(Publish 발행)을 볼 수 있게 되는걸 생각하면 된다.

     

    Sub(Subscribe)

    - 구독(Subscribe)은 클라이언트가 특정 토픽의 메시지를 수신할 수 있도록 하는 작업이다. 클라이언트는 stomp.js의 subscribe 메서드를 사용하여 특정 토픽을 구독한다. 구독한 후에는 해당 토픽으로 발행된 모든 메시지를 실시간으로 수신할 수 있다.

     

    Pub(Publish)

    - 발행(Publish)은 클라이언트가 특정 Topic으로 메시지를 보내는 작업이다. stomp.js의 send 메서드를 사용해서 메시지를 발행할 수 있다. 발행된 메시지는 해당 토픽을 구독한 모든 클라이언트에게 전달된다.

     

    메시지브로커

    - 메시지 브로커는 다양한 시스템, 서비스, 애플리케이션 간에 메시지를 전송하는 중간 매개체 역할을 하는 소프트웨어이다. 발신자(생성자)로 부터 메시지를 받아 이를 적절한 수신자(소비자)에게 전달한다.

    - 메시지 라우팅 : 메시지를 특정 조건에 따라 적절한 수진자에게 라우팅 한다.

    - 메시지 변환: 서로 다른 형식의 메시지를 변환하여 호환성을 유지한다.

    - 내구성: 메시지를 안전하게 저장하고 전달 실패 시 재전송을 지원한다.

     

    메시지 큐 시스템

    - 메시지 큐 시스템은 메시지를 임시로 저장하는 큐를 사용하여 비동기적으로 통신할 수 있게 해주는 시스템이다. 발신자는 메시지를 큐에 넣고, 수신자는 큐에서 메시지를 가져가 처리한다.

    - 비동기 통신 : 발신자와 수신자가 동시에 동작하지 않아도 메시지를 주고 받을 수 있다.

    - 부하 분산 : 여러 수신자에게 작업을 분산하여 처리할 수 있다.

    - 확장성 : 시스템의 부하에 따라 수신자의 수를 유연하게 조절할 수 있다.

     

     

    반응형