35일차 - Node.js 심화(11) Socket.io

이상민·2024년 9월 26일

TIL

목록 보기
35/48

Socket.io란?

Socket.IO란 간단히 말하면 웹 소켓 연결을 통해 클라이언트와 서버간에 실시간 양방향 통신을 가능하게하는 JavaScript 라이브러리이다.

  • Socket.IO는 클라이언트와 서버 간의 실시간 통신을 위한 사용하기 쉬운 인터페이스를 제공하므로 실시간 업데이트 또는 양방향 통신이 필요한 응용 프로그램을 구축하는 데 널리 사용된다.(실시간 주문, 배달 현황 구축)

Socket.IO 기본 개념

Socket: 소켓은 클라이언트와 서버 간의 연결을 나타낸다. 소켓을 사용하여 실시간으로 데이터를 보내고 받을 수 있다.

Server: 서버는 클라이언트와의 소켓 연결을 설정하고 관리한다. 서버는 클라이언트로 이벤트를 방출하거나 클라이언트로부터 이벤트를 수신 할 수 있다.

Client: 클라이언트는 서버와의 소켓 연결을 설정하고 관리한다. 클라이언트는 서버와 동일하게, 서버로 이벤트를 방출하거나 서버에서 이벤트를 수신 할 수 있다.

Socket.IO 트래픽 격리 구분

Event: 이벤트는 소켓 연결을 통해 클라이언트와 서버간에 전송 된 메시지. 이벤트 이름은 서버와 클라이언트에서 동일하게 선언해야 한다. (JSON, 문자열, 이진 등 모든 형식의 데이터 포함 가능)

Namespace: 네임 스페이스는 클라이언트와 서버 간의 별도의 통신 채널. 단일 서버에서 여러 네임 스페이스를 작성할 수 있으며 클라이언트는 특정 네임 스페이스에 연결하여 해당 네임 스페이스의 다른 클라이언트에게만 이벤트를 수신하거나 방출 할 수 있다.

Room: 룸은 함께 결합 된 소켓 그룹입니다. 소켓은 여러 룸에 합류하거나 떠날 수 있다. 룸은 연결된 모든 고객에게 방송하는 대신 특정 클라이언트 그룹에 메시지를 보내는 데 유용.

웹소켓과 Socket.IO의 차이점

Socket.IO는 웹소켓만을 사용하지 않는다.

Socket.IO는 브라우저, 네트워크의 상태에 따라 아래 세 가지 low-level transports 옵션 중 하나를 선택하여 커넥션을 생성한다.

  1. HTTP long-polling
  2. WebSocket
  3. WebTransport: WebSocket의 modern update를 제공하는 API
  • 웹소켓은 Socket.IO가 사용하는 여러 통신 프로토콜 중 하나이다. 즉, Socket.IO와 웹소켓은 완전히 다른 층위에 속한 개념이라고 볼 수 있다.
  • Socket.IO이 WebSocket을 사용하긴 하지만, 각 패킷에 추가적인 메타데이터를 붙이기 때문에 순수 WebSocket과는 호환이 불가능

Socket.IO는 웹소켓에는 없는 여러 기능들을 제공한다.

  1. HTTP long-polling fallback: 웹소켓 연결이 불가능할 때 HTTP long-polling을 사용한다. 예컨대 유저의 브라우저가 웹소켓을 지원하지 않을 때

  2. Automatic reconnection: 주기적으로 연결의 상태를 체크한다. 클라이언트의 연결이 갑자기 끊어지면 자동으로 재연결을 시도한다.

  3. Packet buffering: 클라이언트 연결이 끊어지면 패킷들은 자동으로 버퍼에 쌓이고, 재연결 시에 전송된다. Socket이 연결되어 있지 않을 때에 전달된 이벤트는 버퍼에 쌓인다.

  4. Acknowledgements: 이벤트를 전송하고 이벤트 전송에 대한 응답을 받는 편리한 방식을 제공한다.

// 이벤트를 발송한다.
socket.emit("hello", "world", (response) => {
  console.log(response); // "got it"
});
// 이벤트 발생을 수신하고 핸들링 한다.
socket.on("hello", (arg, callback) => {
  console.log(arg); // "world"
  callback("got it");
});

socket.timeout(5000).emit("hello", "world", (err, response) => {
  if (err) {
  } else {
    console.log(response); // "got it"
  }
});
  1. Broadcasting: 연결되어 있는 모든 클라이언트에게 한 번에 이벤트를 전송할 수 있다.
// to all connected clients
io.emit("hello");

// to all connected clients in the "news" room
io.to("news").emit("hello");

Socket.IO의 엔진: Engine.IO

공식 문서에 뜬금 없이 Engine.IO라는 표현이 등장하는데, 이는 Socket.IO의 내부 엔진이다. Engine.IO는 데이터의 전송과 disconnection 감지를 담당하며, Socket.IO는 여기에 몇 가지 부가 기능을 추가한 것이라고 이해하면 된다.

Socket.IO의 기본적인 사용법

socket 인스턴스 생성

import { io } from "socket.io-client";

const socket = io("https://server-domain.com");

연결 상태 확인하기/표시하기

Socket.IO는 이벤트 기반의 라이브러리다. 실제 사용 코드를 보면 쉽게 이해할 수 있다. 네트워크가 연결되었을 때 화면에 초록불을 표시하고 싶다고 해보자.

import socket from './socket.ts'

export default function App() {
  const [isConnected, setIsConnected] = useState(false)

  useEffect(() => {
    socket.on("connect"), () => {
      setIsConnected(true)
    }
  }, [])
  
  return (
    <div>{isConnected ? <div>connected</div> : null} </div>
  )
}

즉 네트워크가 연결되었을 때 socket 인스턴스는 "connect" 라는 이름의 이벤트를 발생, 이 이벤트에 대한 리스너를 등록하고, (socket.on("connect")) 리스너에 원하는 콜백 함수를 전달.

메시지 주고 받기

서버와 메시지를 주고 받기 위한 이벤트를 정의해야 한다. 이벤트명은 자유이다. 가령 message 라는 이름의 이벤트를 정의할 수 있다. 그리고 이벤트 emit 시 넘겨줄 인자를 함께 정의해야 한다. 아래는 예시 코드다.

// 메시지 발송: 이벤트 emit

const sendMessage = () => {
  socket.emit('message',{name, message})
}

// 메시지 수신: 이벤트 listen

useEffect(() => {
  socket.on('message',({name,message})=>{
    setChat([...chat,{name,message}]) // 화면에 렌더링하는 chat state에 새 메시지를 추가한다.
  })
},[])

0개의 댓글