[WebSocket] 웹소켓이란?

juiuj·2025년 4월 7일

📡 웹소켓(WebSocket)이란?

웹소켓은 웹에서 클라이언트(브라우저)와 서버가 실시간으로 양방향 통신을 할 수 있게 해주는 프로토콜

일반 HTTP 통신과 다르게 한 번 연결되면 끊어지지 않고 계속 연결을 유지하면서 서로 자유롭게 데이터를 주고 받을 수 있다는 것이 가장 큰 특징.

✅ 왜 필요한가?

  • 실시간 채팅
  • 실시간 알림
  • 주식 시세, 실시간 데이터 스트리밍
  • 위치 추적 서비스

🔥 TypeScript에서 웹소켓 연결하는 기본 구조

// 웹소켓 인스턴스 생성
const socket = new WebSocket('ws://서버주소:포트');

// 연결 성공 시
socket.addEventListener('open', (event: Event) => {
  console.log('웹소켓 연결 성공');
  socket.send('클라이언트에서 보낸 메시지');
});

// 메시지 수신 시
socket.addEventListener('message', (event: MessageEvent) => {
  console.log('서버로부터 받은 메시지:', event.data);
});

// 에러 발생 시
socket.addEventListener('error', (event: Event) => {
  console.error('웹소켓 에러:', event);
});

// 연결 종료 시
socket.addEventListener('close', (event: CloseEvent) => {
  console.log('웹소켓 연결 종료:', event.code, event.reason);
});

✅ 웹소켓 상태 확인

if (socket.readyState === WebSocket.OPEN) {
  socket.send('이미 연결되어 있음');
}

✅ 사용자 정의 타입으로 메시지 다루기

// 예: 서버로부터 오는 JSON 데이터를 파싱할 경우
socket.addEventListener('message', (event: MessageEvent) => {
  const data: { type: string; payload: any } = JSON.parse(event.data);
  
  switch (data.type) {
    case 'chat':
      console.log('채팅 메시지:', data.payload);
      break;
    case 'notification':
      console.log('알림:', data.payload);
      break;
    default:
      console.warn('알 수 없는 메시지 유형');
  }
});

🙋 정리

  • open : 연결 성공 시
  • message : 서버로부터 메시지 수신 시
  • error : 에러 발생 시
  • close : 연결 종료 시

✅ React + TypeScript에서 웹소켓 사용하는 경우

1️⃣ 웹소켓을 어디서 생성할까?

보통 useEffect 훅 안에서 생성하고, 컴포넌트가 언마운트될 때 닫아주는 패턴 사용

import React, { useEffect, useRef } from 'react';

const ChatComponent: React.FC = () => {
  const socketRef = useRef<WebSocket | null>(null);

  useEffect(() => {
    // 웹소켓 연결
    socketRef.current = new WebSocket('ws://서버주소:포트');

    socketRef.current.onopen = (event: Event) => {
      console.log('웹소켓 연결됨');
      socketRef.current?.send('안녕 서버야!');
    };

    socketRef.current.onmessage = (event: MessageEvent) => {
      console.log('받은 메시지:', event.data);
    };

    socketRef.current.onerror = (event: Event) => {
      console.error('에러 발생:', event);
    };

    socketRef.current.onclose = (event: CloseEvent) => {
      console.log('연결 종료:', event.code, event.reason);
    };

    // 클린업
    return () => {
      socketRef.current?.close();
    };
  }, []);

  return <div>채팅 중입니다...</div>;
};

2️⃣ 메시지 데이터 타입 처리

서버가 JSON으로 데이터를 보낼 경우, 타입을 명시해서 파싱하면 좋음

type ServerMessage = {
  type: 'chat' | 'notification';
  payload: any;
};

socketRef.current.onmessage = (event: MessageEvent) => {
  const data: ServerMessage = JSON.parse(event.data);
  if (data.type === 'chat') {
    console.log('채팅 메시지:', data.payload);
  }
};

➕ Tip

  • useRef로 socket 인스턴스를 관리하면 다시 렌더링될 때도 인스턴스를 유지할 수 있음.

0개의 댓글