240929 TlL - 폭풍처럼 지나가는 웹소켓

LIHA·2024년 9월 29일
0

내일배움캠프

목록 보기
64/117
post-thumbnail

패킷 처리 방법에 따라 두 가지로 구분!

이벤트 기반 (이름으로 가져오는 것)

-> 이 경우 두 이벤트의 이름을 똑같이 맵핑해줘야 한다.
서버 수신 - 클라 발신 시 보내고 받는 그 '이름'이 같아야 하고, 서버 발신 - 클라 수신의 이름이 같아야 한다. 지금 이 경우는 chat-message 라는 이름으로 맵핑 되고있다.

// 서버 수신
socket.on('chat-message', (data) => {
  // 서버 발신
  io.emit('chat-message', { id: socket.id, msg: data });
});

// 클라이언트 발신
socket.emit('chat-message', message); // 서버로 메시지 전송

// 클라이언트 수신
socket.on('chat-message', ({ id, msg }) => {
   // ... 비즈니스 로직
};

-> 코드가 왜 이런 형태로 쓰이냐면 공식문서에서 이게 기본 형태라고 안내하고 있기 때문이다. 당장은 낯설겠지만 익숙해지는 것이 좋을듯🤔

-> 나중 가면 바이트 배열 형태로 데이터를 보내는 '버퍼객체' 라는 걸 배우게 될 거다. 나중에 TCP 서버 공부하면 알게될 것.

-> ~.on : 나 받는다
~emit : 나 발신한다

핸들러 ID 방식 (패킷 구조 내가 정해야함)

이 방식에서는 무조건 event라는 이름으로 주고받기 때문에 이름으로 구분할 수는 없다.
-> 다만 이 안에서 핸들러 번호 맵핑을 잘 해야 한다. event라는 이름 하나 안에서 여러 개로 쪼개지기 때문.

  • 빠른 속도를 위해 시도해볼만 한 것 두 가지?
  1. 패킷 크기 최소화 -> 이건 해볼 수 있음
  2. 네트워크 통신 속도 -> 이건 우리가 할 수 있는게 아님

결론은 위 두 방식을 적절히 섞어서 쓰는 게 중요하다

const handlerMapping = {
  11: () => {
	  // 비즈니스 로직
  },
};

const handleEvent = (io, socket, { handlerId, data }) => {
  const handler = handlerMapping[handlerId];
  // 적절한 핸들러가 없다면 실패처리합니다.
  if (!handler) {
    socket.emit('response', { status: 'fail', message: 'Handler not found' });
    return;
  }

  const response = handler(io, socket, data);
  io.emit('response', { status: 'success', handlerId, data: response });
};


socket.on('event', (data) => handleEvent(io, socket, data));

대충 이런식으로 코드가 생겼을 것이다. 핸들러 맵핑을 봤을 때 특정 핸들러가 11번에 맵핑되어 있다는 얘기.

-> 왜 섞어쓰는게 중요하냐면, 'monster-event' 라는 이름 안에 있는 핸들러가 한 20개 정도 되고 'user-event' 안에 있는 핸들러가 한 30개 정도 되는 식의 구조가 될 것이다. 이름으로 한번 분류하고, 기능에 따라 핸들러 번호를 맵핑하는 식으로 내부에서 또 나누게 될 것. 어느 한 방식만 쓰는 데에는 한계가 있기 때문.

-> 이때 response에서 클라이언트한테 handlerId는 왜 주냐면,

패킷 구조는 반드시 약속된 형태로 보내주어야 한다!

C++이나 C#은 원하는 구조대로 오지 않으면 읽지도 못한다. 특히 C++은 원하는 구조 아니면 에러를 터트린다. (젠장...)

io.attach(server); 로 서버를 붙인다. (웹소켓 서버 오픈!)
io.on('connection', (socket) => {} 로 'connection'이라는 이름으로 socket을 인자로 받는다.

socket.emit()과 io.emit()의 차이?

일단 서버는 io.emit() 을 쓴다. 둘이 뭐가 다르냐?

socket.emit()은 이 연결을 한 클라이언트 한명에게만 답장을 해주는 것.
io.emit()은 이 소켓의 전체 유저에게 답장을 뿌려주는 것.
-> 이 io.emit()은 진짜로 모든 서버 전체 유저에게 보내는 것이다!

  • 내가 원하는 건 지금 내 채팅방에 있는 사람들에게만 보내고 싶은데...
    -> 이건 우리가 한번 방법을 찾아보도록 하자

서버가 받는이름 = 클라가 보내는이름, 서버가 보내는이름 = 클라가 받는이름

그래서 서버단인 socket.js에서는 11번인 sendMessage라고 되어 있고,

클라단인 script.js에서는 sendMessage인 11번이라고 되어있다.

아니, 내 const socket = io() 는 왜 동작을 안하지?

왜 찾을 수 없다는거야? 🤔🤔🤔🤔🤔

-> HTML의 오타 때문이었다...... 😭😭😭😭😭

그래서 소켓이 대체 뭔데요?!

역시 기대를 저버리지 않는 인파님의 블로그. 여기를 참고

profile
갑자기 왜 춤춰?

0개의 댓글