[WebSocket] 실시간 Stateful 통신의 세계로
WebSocket을 통해서 실시간 채팅을 넣기 위해 이 긴 이야기를 시작해야겠다.
먼저 HTTP와 WebSocket의 차이를 이해해야 한다. 이를 위해서는 두 가지를 비교해서 보여주는 요청&응답 흐름을 보면 좋다. HTTP는 클라이언트가 요청을 보내면 서버가 응답을 반환한 뒤 연결을 끊는 구조로, Stateless한 방식이다. 반면 WebSocket은 클라이언트와 서버 간의 연결을 유지하면서 양방향으로 데이터를 주고받는 구조다. 실시간 채팅이나 알림 시스템에 웹소켓이 많이 쓰일 수밖에 없는 이유이다.
출처: APIDOG
Django Channels
장고에서 에서 웹소켓 연결을 구축할 수 있도록 해주는 라이브러리다. 좀더 정확히 찾아보니 "비동기 통신" 을 핵심적으로 지원하는 라이브러리라고 한다. 채널의 핵심 구성 요소는 'Consumer'와 Channels Layer인데, Consumer는 기존 템플릿 엔진에서의 View와 비슷하게 특정 이벤트를 처리하는 역할을 하고, Channels Layer는 Consumer 간에 메시지를 주고받게 한다.
챗지피티의 도움을 받아 웹소켓을 적용하는 간단한 예제 코드를 가져와봤다. 이 코드에서 connect와 disconnect 메서드는 각각 연결이 열릴 때와 닫힐 때 호출되고, receive는 메시지를 받을 때 호출된다. 이 구조 덕분에 장고에서도 실시간 채팅 같은 기능을 구현할 수 있다.
from channels.generic.websocket import AsyncWebsocketConsumer
import json
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.accept()
async def disconnect(self, close_code):
pass
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
await self.send(text_data=json.dumps({
'message': message
}))
React에서 웹소켓 쓰는 법?!
React에서는 useWebSocket Hook을 사용해 WebSocket을 쉽게 다룰 수 있다. 이 Hook은 서버와의 연결 상태를 관리하고, 메시지를 주고받는 기능을 제공한다. 아래 코드는 useWebSocket을 사용해 버튼 클릭 시 서버에 메시지를 보내고, 서버에서 받은 메시지를 화면에 표시하는 예제다. readyState는 WebSocket 연결 상태를 나타내며, 연결이 잘 되어 있는지 확인할 때 유용하다.
import React, { useState, useCallback, useEffect } from 'react';
import useWebSocket from 'react-use-websocket';
export const WebSocketDemo = () => {
const [socketUrl, setSocketUrl] = useState('wss://echo.websocket.org');
const options = {
onOpen: () => console.log('연결이 성공적으로 열렸습니다.'),
onClose: () => console.log('연결이 닫혔습니다.'),
onError: (error) => console.error('웹소켓 에러:', error),
onMessage: (message) => console.log('수신된 메시지:', message.data),
};
const { sendJsonMessage } = useWebSocket(socketUrl, options, reconnectInterval: 1000,share: true,);
출처: 멋쟁이사자처럼 세미나 자료 아무리 찾아도 이만한게 없다
이렇게 하면 웹소켓 연결과 메시지 송수신을 단 몇 줄로 구현할 수 있다. sendMessage로 서버에 메시지를 보내고, lastMessage로 서버에서 받은 메시지를 즉시 확인할 수 있다.
useWebsocket 짱