웹 소켓 기초

배성규·약 23시간 전
0

프로젝트

목록 보기
10/10
post-thumbnail

1초당 10장씩 이미지를 보여줘야하는 기능을 구현하는 과정에서 웹 소켓을 적용하였습니다.
해당 기능을 구현하면서 공부한 과정/문제/해결 과정을 정리하고자 작성했습니다.

1. Web Socket

웹 소켓은 하나의 TCP 접속에 전이중 통신 채널을 제공하는 통신 프로토콜입니다.

  • full duplex(전이중 통신)을 제공하기 때문에 웹 브라우저 - 웹 서버 간의 통신 및 실시간 데이터 전송을 할 수 있게 도와줍니다.
  • 웹 소켓은 연결을 유지한 상태에서 메시지들을 오갈 수 있게 허용해줍니다.
  • 연결이 된 이후 클라이언트-서버 간 연결이 유지됩니다.

장점

  • 웹 소켓은 지연이 적은 실시간 데이터 전송에 적합하여 채팅, 게임, 주식 등의 도메인에서 사용됩니다.
  • 연결이 된 이후에는 데이터 전송 시 http 헤더를 반복적으로 전송하지 않아도 됩니다.

단점

  • 연결이 지속적으로 유지되기 때문에 모바일 환경에서 배터리의 소모가 증가할 수 있습니다.

2. 리액트 + 노드에서 웹 소켓 사용하기

  • socket.io 라이브러리를 활용하여 구현

호출 프로토콜

웹 소켓을 사용하는 프로토콜에는 2가지 방법이 있습니다.

  • ws://
    • 데이터 전송 시, 암호화되지 않은 채로 전송되어 데이터가 그대로 노출된다.
  • wss://
    • 전송 보안 계층이라는 보안 계층을 통과해 전달하기 때문에 송신자 측에서 데이터가 암호화되고, 복호화는 수신자 측에서 이루어집니다.

http, https와 같이 보안/신뢰성에서 차이가 나는 프로토콜 종류입니다.

2-1. 노드에서 사용하기

노드에서 사용하기 위해서 socket.io라이브러리를 설치합니다
이후 아래와 같이 설정합니다.

import { createServer } from 'http';
import { Server } from 'socket.io'; 
import express, { Request, Response } from 'express';
// ...code 

const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, {
  cors: {
    origin: 'http://localhost:3000', // 리액트 앱 주소
    methods: ['GET', 'POST'],
  },
});

io.on('connection' , (socket) => {
	console.log('connected');  
  
  	// 로직 작성 
  	
  	socket.on('disconnect', () => {
    	console.log('disconnect'); 
    }
    socket.on('error', (error) => {
      console.error(error); 
    }
    
  
}

2-2. 리액트에서 연결하기

노드에서 선언한 웹 소켓을 리액트에서 호출하여 연결합니다.

socket.io-client 라이브러리로 쉽게 소켓에 연결을 진행합니다.

import { io } from 'socket.io-client'; 
import React, { useEffect, useState } from 'react';

const socket = io('http://localhost:8000');

function App() {
  useEffect(() => {
    socket.on('image-stream', (base64Image) => {
     // 로직 
    });

    return () => {
      socket.disconnect();
    };
  }, []);
}

2-3. 추가 설명

소켓을 통신하는 이벤트는 emiton을 사용합니다.

//보낼 때 
//많은 인수를 보내도 상관없으며, Buffer나 TypedArray등의 바이너리 객체도 지원
socket.emit('hello', 'world', (response) => {
	console.log(response); 
}); 

// 받을 때 
socket.on('hello', (arg, callback) => {
  	console.log(arg); // world
  	callback('got it'); 
}); 

//이벤트 제거 방법 
socket.off('hello'); 
socket.removeAllListeners(); 

또한 서버에서 연결된 모든/일부 클라이언트에 이벤트를 보낼 수 있습니다.

// 연결된 모든 클라이언트로 보냄
io.emit('hello'); 

// news룸으로 연결된 클라이언트에 보냄 
io.to('news').emit('hello'); 

연결 중 cors에러가 발생한 경우에는 아래와 같이 교차 출처를 허용하여 통신할 수 있도록 설정합니다.

// server-side
const io = new Server(httpServer, {
  cors: {
    origin: "https://example.com",
    allowedHeaders: ["my-custom-header"],
    credentials: true
  }
});

// client-side
import { io } from "socket.io-client";
const socket = io("https://api.example.com", {
  withCredentials: true,
  extraHeaders: {
    "my-custom-header": "abcd"
  }
});

아직 웹 소켓을 적용하는 과정에서 많은 에러들이 발생하고 있어 좀 더 학습해야합니다.

아래에서 웹 소켓에서 발생한 에러를 해결하는 과정을 담은 블로그를 참고하면 좋아보입니다.
우아한형제들 배달운영시스템

참고

ko.javascript.info
mdn
sendbird
소켓io docs

profile
FE 유망주🧑‍💻

0개의 댓글