Notice
Recent Posts
Recent Comments
Link
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

vonvon56 님의 블로그

실시간 채팅 구현 본문

카테고리 없음

실시간 채팅 구현

vonvon56 2024. 11. 7. 16:18

1. HTTP 프로토콜과 WebSocket 프로토콜의 특징 및 차이점

 

인터넷을 통해 정보를 주고받는 여러 방식 중 가장 많이 쓰이는 프로토콜이 바로 HTTP와 WebSocket이다.

둘 다 클라이언트와 서버를 연결해 주지만, 서로 다른 상황에 특화되어 있다. 


HTTP 프로토콜

HTTP(HyperText Transfer Protocol)는 웹 페이지를 주고받는 데 쓰이는 기본적인 프로토콜이다.

보통 우리가 웹사이트를 열 때 사용하는 대부분의 통신이 HTTP로 이루어진다.

요청-응답 구조이다. 즉 클라이언트가 서버에 정보를 요청하면 서버가 응답하는 방식으로 작동한다.

예를 들어, 어떤 웹페이지 주소를 입력하면 브라우저가 HTTP 요청을 보내고, 서버는 그에 맞는 HTML, CSS, 이미지 등을 응답으로 보내주는 식이다. HTTP의 주요 특징은 다음과 같다.

  • 요청-응답 구조: 클라이언트가 요청을 보낼 때만 서버가 응답을 보낸다.
  • 단방향 통신: 서버는 클라이언트의 요청이 있을 때만 데이터를 보낸다.
  • Stateless: 요청마다 독립적이어서 이전의 요청 정보를 유지하지 않는다. 매번 새로 연결을 설정하는 것.

WebSocket 프로토콜이란?

WebSocket은 HTTP의 단방향 통신의 한계를 해결하기 위해 고안된 프로토콜이다.

HTTP와 마찬가지로 클라이언트와 서버 간의 통신에 쓰이지만, 양방향 통신을 지원한다는 점에서 다르다.

초기 연결만 HTTP를 통해 설정하고 나면, 그 이후에는 끊기지 않는 상태로 지속적으로 데이터를 주고받을 수 있다.

WebSocket의 주요 특징은 다음과 같다.

  • 양방향 통신: 클라이언트와 서버가 서로에게 자유롭게 데이터를 주고받을 수 있다.
  • 지속적 연결 유지: 연결이 설정된 후에는 별도의 요청 없이도 데이터가 오갈 수 있다.
  • 상태 저장 가능: 연결이 계속 유지되므로 양쪽에서 이전 상태를 기억하고 그 위에서 작업을 이어갈 수 있다.

HTTP와 WebSocket의 차이점

표로 정리해서 이해해 보자!

 

  HTTP WebSocket
통신 방식 요청-응답 구조의 단방향 양방향 통신 가능
연결 유지 요청마다 새로운 연결 설정 초기 연결 후 지속적 연결 유지
데이터 전송 방식 요청마다 필요한 데이터 전송 필요한 데이터가 있을 때마다 즉시 전송 가능
사용 사례 웹페이지 로딩, 간단한 데이터 요청 채팅, 실시간 알림, 주식 시세 업데이트 등

적합한 상황

HTTP가 적합한 경우

  • 간단한 요청-응답이 필요한 경우. 예를 들어, 검색 결과 페이지를 요청할 때나 사용자 프로필을 불러올 때.
  • 데이터를 주기적으로 갱신할 필요가 없는 경우. 일반적인 웹 페이지 탐색에 적합하다.
  • API 호출이 자주 일어나지 않는 경우. HTTP API를 사용하는 시스템이라면 대부분 이런 구조를 사용한다.

WebSocket이 적합한 경우

  • 실시간 통신이 중요한 경우. e.g., 채팅 애플리케이션, 온라인 게임, 주식 거래 시스템 등 빠른 데이터 갱신이 필요한 서비스
  • 서버가 클라이언트에 즉시 알림을 보내야 하는 경우. e.g., 새로운 메시지 알림, 스포츠 경기의 점수 업데이트 등
  • 끊기지 않는 연결이 필요한 경우. 

2. Django Channels 라이브러리 구조

 

Django는 전통적으로 HTTP 요청-응답 기반의 동기식 프레임워크지만, 실시간 기능을 제공하는 데는 한계가 있다. 이런 한계를 극복하게 해주는 것이 바로 Django Channels다.

ASGI(Asynchronous Server Gateway Interface)를 기반으로 Django의 기존 WSGI 서버와 통합되어 작동한다.

Django Channels는 WebSocket과 같은 비동기 통신을 지원해 Django 기반의 애플리케이션에서도 실시간 기능을 쉽게 구현할 수 있도록 돕는다. 


Django Channels란?

Django Channels는 Django에 WebSocket, HTTP2, 그리고 기타 비동기 프로토콜 지원을 추가해주는 라이브러리다. 이를 통해 Django로 실시간 채팅, 알림, 라이브 스트리밍 등의 기능을 쉽게 구축할 수 있다.

Channels는 ASGI를 기반으로 Django의 기존 WSGI 서버와 통합되어 작동하며, 비동기와 동기 환경을 모두 지원할 수 있도록 설계되어 있다.

 

Django Channels의 주요 구성 요소

Django Channels는 기본적으로 다음 세 가지 요소로 구성되었다.

  1. Consumer: Django의 View에 해당하는 역할로, WebSocket을 비롯한 다양한 프로토콜 요청을 처리하는 비동기 함수.
  2. Channel Layer: 여러 Consumer 간에 데이터를 주고받을 수 있게 해주는 레이어. Redis와 같은 메시지 브로커를 사용해 Consumer 간에 메시지를 교환함
  3. Routing: URL과 비슷한 개념. 어떤 요청이 어떤 Consumer에 전달될지를 결정한다.

Consumer: 요청을 처리하는 핵심 역할

Channels에서 Consumer는 Django View와 유사한 역할을 한다. 하지만 Channels의 Consumer는 비동기적으로 작동하기 때문에 WebSocket처럼 연속적인 연결을 처리하는 데 유리하다. Django Channels는 두 가지 종류의 Consumer를 제공한다.

  • AsyncConsumer: 비동기적으로 동작하는 Consumer로, 주로 WebSocket 통신을 위해 사용된다.
  • SyncConsumer: 동기적으로 동작하는 Consumer로, 기존 Django의 동기 View와 유사하게 작동한다. 필요 시 비동기 작업과 통합하여 사용할 수 있다.

주요 메서드로는 WebSocket 연결 시 connect, 연결 해제 시 disconnect, 메시지 수신 시 receive 등이 있다. 각 메서드는 상황에 맞게 WebSocket 이벤트를 처리하도록 설정된다.

Channel Layer: Consumer 간의 소통을 돕는 중개자

Channel Layer는 Channels에서 Consumer 간에 데이터를 주고받기 위한 레이어다. 채팅 애플리케이션이나 실시간 알림 시스템처럼, 여러 사용자나 Consumer 간에 메시지를 주고받아야 하는 상황에서 Channel Layer가 필요하다. 이 레이어는 주로 RedisRabbitMQ 같은 메시지 브로커를 통해 구현된다.

Channel Layer에서는 '그룹'이라는 개념을 사용하여 여러 Consumer를 하나의 그룹으로 묶어 메시지를 브로드캐스트할 수 있다. 예를 들어, 채팅방에 들어온 모든 사용자에게 메시지를 보내려면 해당 채팅방 그룹에 메시지를 전송하면 된다.

Channel Layer의 주요 기능은 다음과 같다.

  • send: 특정 채널이나 그룹에 메시지를 전송한다.
  • group_add / group_discard: 특정 그룹에 Consumer를 추가하거나 제거한다.

 

Routing: 요청과 Consumer 연결하기

Channels에서 Routing은 Django의 URL 설정과 유사한 역할을 한다.

HTTP 요청에서 URL을 보고 어느 View를 호출할지 결정하는 것처럼, WebSocket이나 다른 프로토콜 요청에서 Routing을 보고 어느 Consumer로 연결할지를 결정하는 것이다.

URL 패턴과 Consumer를 연결하는 설정은 routings.py에서 한다. 기본적으로 Django의 urls.py와 비슷한 구조로 작성하며, ProtocolTypeRouter를 통해 WebSocket과 HTTP 프로토콜을 구분하여 라우팅할 수 있다.

 


3. React useWebSocket Hook 사용법

React 애플리케이션에서 실시간 기능을 구현하려면 WebSocket을 활용하는 것이 일반적이다. WebSocket은 지속적인 연결을 통해 실시간 데이터 전송이 가능하게 해준다.

 

여기서 더 나아가, useWebSocket Hook을 활용하면 훨씬 효율적으로 실시간 통신을 관리할 수 있다. 


useWebSocket Hook이란?

useWebSocket Hook은 React에서 WebSocket을 더 간편하게 사용할 수 있도록 만든 커스텀 Hook이다.

이 Hook은

1. WebSocket 연결 관리

2. 데이터 통신 기능 제공

3. 연결 상태에 따라 이벤트 처리할 수 있는 유연한 설정을 제공

 

-> WebSocket 통신을 복잡하게 설정하지 않아도 되고, React 컴포넌트에서 쉽게 WebSocket을 활용할 수 있다.


기본 사용법

useWebSocket Hook을 사용하는 기본 방법은 다음과 같다. 이 Hook은 WebSocket URL을 인자로 받으며, 연결 상태와 메시지 송수신, 그리고 연결 종료와 같은 다양한 기능을 제공한다.

import React from 'react';
import useWebSocket from 'react-use-websocket';

const WebSocketExample = () => {
  const { sendMessage, lastMessage, readyState } = useWebSocket('wss://your-websocket-url');

  return (
    <div>
      <button onClick={() => sendMessage('Hello WebSocket!')}>
        Send Message
      </button>
      <div>
        Last message: {lastMessage ? lastMessage.data : 'No message received'}
      </div>
      <div>
        Connection status: {readyState}
      </div>
    </div>
  );
};

export default WebSocketExample;
 

주요 옵션과 리턴 값

useWebSocket Hook은 다양한 옵션과 리턴 값을 제공하여 WebSocket 통신을 보다 유연하게 관리할 수 있다. 대표적인 리턴 값은 다음과 같다.

  • sendMessage: 서버로 메시지를 보낼 때 사용하는 함수. 버튼 클릭이나 특정 이벤트 발생 시 sendMessage 함수를 호출해 데이터 전송할 수 있음.
  • lastMessage: 서버로부터 마지막으로 받은 메시지를 담고 있는 객체. 실시간으로 데이터를 받아오는 데 유용하게 사용.
  • readyState: WebSocket 연결 상태를 나타내는 값. 연결 개방 유무, 오류 유무를 확인할 수 있다.

 

useWebSocket의 다양한 옵션

useWebSocket Hook은 다양한 옵션을 제공하여 WebSocket 연결을 더욱 세밀하게 제어할 수 있다. 몇 가지 유용한 옵션은 다음과 같다.

  • shouldReconnect: 연결이 끊어졌을 때 재연결을 시도할지 여부를 결정한다.
  • reconnectInterval: 재연결을 시도하는 간격을 설정할 수 있다.
  • onOpen / onClose: 연결이 열리거나 닫힐 때 특정 작업을 수행할 수 있도록 도와준다.

예를 들어, 연결이 끊어졌을 때 자동으로 재연결하고 싶다면 shouldReconnect 옵션을 사용하면 된다.]

const { sendMessage, lastMessage, readyState } = useWebSocket('wss://your-websocket-url', {
  shouldReconnect: () => true, // 자동 재연결 활성화
  reconnectInterval: 3000 // 3초 간격으로 재연결 시도
});