소켓통신

소켓통신이란 TCP 혹은 UDP 프로토콜을 사용하는 두 기기 간의 연결이다.

이런 연결을 하기 위해선 특정한 IP주소와 포트 번호를 이용해서 통신 연결을 유지해야 한다.

만일, 채팅프로그램을 만들었는데 HTTP 연결만으로 구현했다면 계속해서 연결을 해줘야 하는 문제가 생길 것이다.

왜냐면 HTTP 통신은 연결이 유지되지 않기 때문이다.

HTTP 통신으로 계속 연결을 하게 되면 컴퓨터의 자원을 계속 소모하기에 부하가 발생할 것이다.

그렇기에 통신이 자주 발생하지 않는다면 HTTP 통신, 통신이 자주 발생한다면 소켓통신이 적합할 것이다.

양방향 통신은 socket 만있는가?

놉, http를 이용한 양방향 통신도 존재

  • 폴링 (polling): 클라이언트가 특정 시간을 간격으로 계속 서버에 request를 요청. 근데 계속요청해서 응답이 있는지 없는지 확인해서 불필요한 요청과 부하 발생
  • long polling: 폴링의 무분별한 확인 요청과 서버 부하를 줄이기 위한 방법 . 서버에서 이벤트가 발생하면 클라이언트에게 응답을 주는 방식
  • 스트리밍(streaming): 롱 폴링처럼 연결을 맺고 끊는게 아니라 지속적인 연결상태로 서버의 데이터를 클라이언트가 받을 수 있음

위 방식을 모두 구현이 단순하지만, HTTP 통신을 기반으로 하기에 헤더 정보는 서버에 부담이 될 수 있음. 폴링은 실시간통신으로 보기 어려움


Socket.io

socket.io는 웹 서비스를 위한 라이브러리이다.

socket.io 특징

  • 서버, 클라이언트 하위 브라우저까지 지원 가능
    • websocket을 지원하지 않는 브라우저가 존재할 수도 있다. 이때 socket.io는 long polling 방식으로 전환해 실시간 통신을 한다.
  • 다양한 언어로 구현 가능
  • 자동 연결 기능
  • socket.io는 API 추상화를 통해 간편하게 데이터를 전송할 수 있는 함수 제공
  • 손쉽게 채널 및 방 단위 설계 가능

socket.io 주요 기능

소켓 이벤트

  • connection: 클라이언트 연결 시 동작
  • disconnect: 클라이언트 연결 해제 시 동작
  • on(): 소켓 이벤트 연결
  • emit(): 소켓 이벤트 생성

client

// socket 연결
const socket = io('socket address', option);
socket.connect()
// 해당 이벤트를 받고 콜백함수 실행
socket.on('event name', (msg) => {})

// 이벤트 이름을 정하고 메시지 전송
socket.emit("event name", msg)

server

// socket server
const { Server } = require('socket.io');
const io = new Server("port", option);

// 웹소켓 연결 시
io.on('connection', (socket) => {
    // 연결 해제 시
    socket.on('disconnect', () => {})
    // 클라이언트로부터 받고 콜백함수 실행
    socket.on('event name', () => {})
    // 클라이언트에게 전달
    socket.emit('event name', data);
})

통신 종류(채널 생성)

socket.io가 지원하는 통신 종료는 3가지가 있다.

  • private: 1:1통신
  • public: 전송자를 포함 모두에게 전달
  • broadcast: 전송자를 제외한 모두에게 전달
// private user id 에게만 전송
io.to(user id).emit();
// public
io.emit();
// broadcast
socket.broadcast.emit();

room

socket.io 는 room 이라는 개념이 존재한다.

쉽게 말해 카톡방이라고 생각하면 된다.

// room id 에 접속
socket.join('room id');
// room id에 메세지 전송
socket.to('room id').emit();

Namespace

url에 지정된 위치에 따라 신호를 다르게 처리하는 기술이다.

서버와 클라이언트가 연결되면 실시간 데이터 공유가 가능한다. socket을 그냥 사용하면 모든 socket으로 들어가게 된다.

하지만 특정 페이지에서는 소켓이 보내주는 모든 데이터를 받을 필요가 없다. 불필요하며 낭비이기 때문인다.

그래서 특정 노드끼리만 연결해주는 namespace가 존재한다.

각기 다른 네임스페이스를 만들게 되면 신호를 각기 독립적으로 처리할 수 있다.

즉, 지정한 namespace에 있는 소켓끼리만 통신하게 된다.

// goods namespace 생성
const goods = io.of("/goods");
// user namespace 생성
const user = io.of('/user');

goods.on('connection', (socket) => {
    // goods namespace 연결
})

user.on('connection', (socket) => {
    // user namespace 연결
})

namespace 와 room에 대해선 다음 글에서 더 자세히 설명하겠다.

참고 자료

댓글남기기