TIL | [Socket.io] NestJs에 설치 및 세팅하기

bubblegum·2024년 4월 12일
0

Today I learn(TIL)

목록 보기
71/84
post-thumbnail

Socket.IO는 실시간, 양방향 통신을 웹 애플리케이션에 쉽게 구현할 수 있게 해주는 JavaScript 라이브러리입니다. Node.js 서버와 클라이언트(웹 브라우저) 사이에서 WebSocket을 사용하여 실시간 데이터 교환을 가능하게 합니다.

1. 필요한 패키지 설치

먼저, NestJS 프로젝트를 생성하고, 필요한 Socket.IO 및 관련 패키지를 설치합니다. 프로젝트가 이미 존재한다면, 해당 디렉토리로 이동해서 다음 명령어를 실행합니다.

npm install @nestjs/platform-socket.io @nestjs/websockets socket.io

2. 게이트웨이 생성

Socket.IO를 사용하기 위해 NestJS에서는 게이트웨이라는 개념을 사용합니다. 게이트웨이는 특정 이벤트에 대해 소켓 연결을 관리합니다. 다음 명령어를 사용하여 새로운 게이트웨이를 생성합니다.

nest generate gateway chat

이 명령은 chat.gateway.ts 파일을 생성합니다. 이 파일을 수정하여 Socket.IO 이벤트를 처리할 수 있습니다.

3. ChatGateway 설정

chat.gateway.ts 파일을 열고, 간단한 채팅 로직을 추가합니다. 이 예시에서는 클라이언트로부터 "chat message" 이벤트를 받아 모든 클라이언트에게 메시지를 브로드캐스트합니다.

import { WebSocketGateway, SubscribeMessage, MessageBody, WebSocketServer } from '@nestjs/websockets';
import { Server } from 'socket.io';

@WebSocketGateway({
  cors: {
    origin: '*', // 실제 배포 시에는 보안을 위해 특정 도메인으로 제한해야 합니다.
  },
})
export class ChatGateway {
  @WebSocketServer()
  server: Server;

  @SubscribeMessage('chat message')
  handleMessage(@MessageBody() message: string): void {
    this.server.emit('chat message', message);
  }
}

주요 개념과 특징

  • 이벤트 핸들링: @SubscribeMessage() 데코레이터를 사용하여 특정 메시지 이벤트를 수신하고 처리할 메서드를 정의할 수 있습니다. 이 메서드 내에서 클라이언트로부터 받은 데이터를 처리하고, 필요한 경우 응답을 보낼 수 있습니다.

  • 클라이언트와의 통신: 게이트웨이 내에서 @WebSocketServer() 데코레이터를 사용하면, Socket.IO의 Server 인스턴스에 접근할 수 있습니다. 이를 통해 연결된 모든 클라이언트에게 메시지를 브로드캐스트하거나, 특정 클라이언트에게만 메시지를 보낼 수 있습니다.

  • 네임스페이스와 룸: Socket.IO의 개념인 네임스페이스와 룸을 사용하여 통신을 더 세밀하게 제어할 수 있습니다. 네임스페이스는 서로 다른 통신 채널을 생성하여 애플리케이션 내에서 분리된 통신 영역을 만들 수 있게 해줍니다. 룸은 네임스페이스 내에서 더 세분화된 그룹을 만들어, 특정 그룹의 클라이언트에게만 메시지를 보낼 수 있게 합니다.

  • cors: 이 설정은 WebSocket 연결을 통해 다른 출처에서 서버로의 접근을 허용하기 위한 CORS 정책을 구성합니다. CORS 정책은 HTTP 헤더를 사용하여 구현되며, 이 헤더들은 브라우저가 다른 출처의 리소스에 안전하게 접근할 수 있도록 정보를 제공합니다.

  • origin: origin 설정은 특정 출처에서 오는 요청만을 허용하도록 서버를 구성할 때 사용됩니다. origin: '*'는 모든 출처에서 오는 요청을 허용한다는 것을 의미합니다. 하지만, 이는 보안상 위험할 수 있으므로 실제 배포 환경에서는 허용할 특정 도메인을 지정하는 것이 좋습니다. 예를 들어, origin: 'https://www.example.com'은 오직 https://www.example.com에서 오는 요청만을 허용하도록 설정합니다.

CORS는 웹의 개방성과 보안 사이에서 균형을 맞추려는 시도 중 하나이며, 웹 애플리케이션 개발 시 이를 적절히 구성하는 것이 중요합니다. CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유)는 웹 페이지가 다른 도메인의 리소스에 접근할 수 있도록 허용하는 메커니즘입니다. 기본적으로 웹 브라우저는 같은 출처 정책(Same-Origin Policy)을 따르기 때문에, 한 출처(origin)에서 로드된 문서나 스크립트가 다른 출처의 리소스와 상호작용하는 것을 제한합니다. 이 정책은 보안상의 이유로 중요하지만, 때로는 다른 출처의 리소스에 접근할 필요가 있을 때 CORS가 사용됩니다.

4. 클라이언트 코드

index.html 파일을 생성하고 다음과 같이 작성합니다.

<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <style>
      /* 여기에 채팅 UI 스타일을 추가하세요 */
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form id="form" action="">
      <input id="input" autocomplete="off" /><button>Send</button>
    </form>
    <script>
      document.addEventListener('DOMContentLoaded', function () {
          const socket = io();

          // 폼 제출 이벤트 리스너를 추가합니다.
          document.querySelector('form').addEventListener('submit', function(e) {
              // 기본 폼 제출 동작을 방지합니다.
              e.preventDefault();

              // 사용자가 입력한 메시지를 서버로 전송합니다.
              const inputElement = document.getElementById('input');
              socket.emit('chat message', inputElement.value);

              // 입력 필드를 비웁니다.
              inputElement.value = '';
              return false;
          });

          // 서버로부터 메시지를 받았을 때의 처리를 정의합니다.
          socket.on('chat message', function(msg){
              // 새 메시지를 위한 li 요소를 생성합니다.
              var newElement = document.createElement('li');
              newElement.textContent = msg;

              // 메시지 리스트에 새 메시지를 추가합니다.
              document.getElementById('messages').appendChild(newElement);
          });
      });

    </script>
  </body>
</html>

클라이언트 측 라이브러리는 CDN을 통해 쉽게 가져올 수 있습니다. HTML 파일 내에 다음 스크립트 태그를 추가하세요.

<script src="/socket.io/socket.io.js"></script>

또는 특정 버전을 지정하여 CDN에서 가져올 수도 있습니다.

<script src="https://cdn.socket.io/4.0.0/socket.io.min.js"></script>

네스트JS(NestJS)웹 프레임워크에서 채팅 채널(룸)을 설정하는 방법

게이트웨이 생성

네스트JS에서 Socket.IO를 사용하기 위해 게이트웨이를 생성합니다. 게이트웨이는 특정 네임스페이스(/posts)에 대한 소켓 연결을 처리합니다. 다음은 게이트웨이를 생성하는 명령어입니다:

nest generate gateway posts/posts

이 명령어는 posts 폴더 내에 posts.gateway.ts 파일을 생성합니다.

게이트웨이 구성

posts.gateway.ts 파일을 열고, 게시글별로 채팅 채널을 구성하기 위해 게이트웨이 클래스를 수정합니다. 각 게시글의 ID를 룸 이름으로 사용하여, 게시글에 대한 채팅을 별도로 관리할 수 있도록 합니다.

import { WebSocketGateway, SubscribeMessage, WebSocketServer, ConnectedSocket, MessageBody } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

@WebSocketGateway({
  namespace: '/posts' // 네임스페이스 설정
})
export class PostsGateway {
  @WebSocketServer()
  server: Server;

  @SubscribeMessage('joinRoom')
  handleJoinRoom(@MessageBody() data: { postId: string }, @ConnectedSocket() client: Socket) {
    const { postId } = data;
    client.join(postId); // 클라이언트를 게시글 ID에 해당하는 룸에 참여시킴
  }

  @SubscribeMessage('leaveRoom')
  handleLeaveRoom(@MessageBody() data: { postId: string }, @ConnectedSocket() client: Socket) {
    const { postId } = data;
    client.leave(postId); // 클라이언트를 게시글 ID에 해당하는 룸에서 탈퇴시킴
  }

  // 게시글 ID에 해당하는 룸에 메시지 보내기
  @SubscribeMessage('sendMessage')
  handleMessage(@MessageBody() data: { postId: string; message: string }) {
    this.server.to(data.postId).emit('newMessage', data.message);
  }
}

위 코드에서는 네임스페이스(/posts)를 설정하고, joinRoom, leaveRoom, sendMessage 이벤트를 처리하는 메소드를 구현했습니다. 클라이언트가 특정 게시글의 채팅에 참여하거나 탈퇴할 때, 그리고 메시지를 보낼 때 사용됩니다.

클라이언트 측 구현

클라이언트 측에서는 Socket.IO 클라이언트 라이브러리를 사용하여 서버와 통신합니다. 게시글 페이지에 들어갈 때 joinRoom 이벤트를, 페이지를 떠날 때 leaveRoom 이벤트를 발송하고, 메시지를 보낼 때는 sendMessage 이벤트를 사용합니다.

profile
황세민

0개의 댓글

관련 채용 정보