썸네일-002 (6).png

<aside> 💡 NestJS 웹 소켓 서버 환경에서 클라이언트 - 서버간의 예외처리 구현하기!

</aside>

✔️ 현재 상황


Zello 팀은 CRA React로 클라이언트를, NestJS로 서버를 구현하고 있어요. 그리고 게임 로직은 Socket 통신을 통해 이루어지고 있어요.

현재 클라이언트 - 서버 간의 소켓 요청/응답 코드를 간단하게 아래에 표현하였어요.

💻 클라이언트 - 서버 소켓 코드

클라이언트 코드 component.tsx

/** some codes.... **/
useEffect(() => {
    socket.emit(
      'join-lobby',
      payload,
			// socket.io의 acknowledgements 를 이용하여 
			// emit한 request의 response를 받는 callback
      (res) => {
				 /* ...서버로부터 받은 response를 처리하는 로직... */
      }
  );
}, []);

클라이언트에서는 ‘join-lobby’ 라는 이벤트 이름을 가진 소켓 요청을 보내고 있어요. 그리고 특정 payload를 보내고 있고, socket.io의 acknowledgements를 이용하여 emit한 request에 대한 response를 처리하는 callback function도 파라미터로 전달하고 있어요.

emit 메서드의 마지막 argument가 function이면, 서버에서 이 이벤트를 acknowledge 할 때, 이 클라이언트의 callback function이 호출되어요. 이 기능을 socket.io에서 acknowledgement 라고 불려요. (더 자세한 내용은 여기를 참조하세요.) 앞으로는 이 callback function을 acknowledgement function이라고 할게요.

서버 코드 core.gateway.ts

// 데코레이터를 이용하여 어노테이션
@WebSocketGateway({ namespace: 'game' })
export class CoreGateway implements { 

  // 'join-lobby' 라는 이벤트 이름을 가진 소켓 요청을 핸들링하는 코드 
	@SubscribeMessage('join-lobby')
  async handleJoinLobby(
      // 클라이언트 소켓 객체
      @ConnectedSocket() client: Socket,
      // payload
      @MessageBody() body: JoinLobbyRequest,
  ) {
      try {
          const lobby = this.lobbyService.getLobby(body.lobbyId);
          const user = this.userService.getUser(client.id);

          /* ... 유저가 로비에 들어가는 로직 ... */
					/* ... 로비에 있는 다른 유저들에게 join-lobby 이벤트를 emit하는 로직 ...*/

					return result // acknowledgements 를 이용하여 response 보내기
      } catch (e) {
          console.log('BadRequest');
      }
  }

Nest에서는 socket 관련 요청을 Gateway에서 처리해요. handleJoinLobby는 ‘join-lobby’ 라는 소켓 이벤트를 받을 때 실행되는 메서드에요. 이 메서드는 요청을 보낸 클라이언트를 로비에 입장시켜주는 요청을 담당하고 있어요.

이 메서드는 현재 요청한 클라이언트를 로비에 입장시켜주고, 로비에 이미 들어가있던 다른 유저들에게 ‘join-lobby’ 라는 이벤트를 emit 하여 새로운 유저가 입장했다는 사실을 알려줘요. 그리고 마지막으로 return result 를 통해 acknowledgements를 이용하여 요청을 보낸 클라이언트에게 응답을 보내요.

Nest에서는 Gateway의 소켓 이벤트 핸들러에서 return 문을 통해 클라이언트에게 응답을 보낼 수 있어요. 자세한 내용은 여기를 참조하세요.

🧐 문제 상황