【NestJS】WebsocketGatewayを作成する

# はじめに
WebsocketGatewayの理解を深めるためにサンプルソースを交えて本記事を作成しています。
参考にしたのは[公式ドキュメント](https://docs.nestjs.com/websockets/gateways)になります。

**Client side**(今回はPostman)から**Gateway**にアクセスされた時の挙動について触れています。
![スクリーンショット 2023-02-12 12.13.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554111/9d307409-6326-c7ac-c997-436c3e228fff.png)


# 実装
### プロジェクト作成
```
nest new nestjs-websocket
```

### パッケージをインストール
```
npm i --save @nestjs/websockets @nestjs/platform-socket.io
```

### Gateways作成
プロジェクト配下のsrcフォルダに新規`gateway`フォルダを作成し、フォルダ内に`gateway.module.ts`と`gateway.ts`を作成する

```
ファイル構成
|──nestjs-websocket
| |──src
|   |──gateway
|     |──gateway.ts
|     |──gateway.module.ts
|
|   |──app.module.ts
```
     

```gateway.module.ts
import { Module } from '@nestjs/common';
import { Gateway } from './gateway';

@Module({
  providers: [Gateway],
})
export class GatewayModule {}
```


```gateway.ts
import { OnModuleInit } from '@nestjs/common';
import {
  MessageBody,
  SubscribeMessage,
  WebSocketGateway,
  WebSocketServer,
} from '@nestjs/websockets';
import { Server } from 'socket.io';

@WebSocketGateway()
export class Gateway implements OnModuleInit {
  @WebSocketServer()
  server: Server;

  onModuleInit() {
    this.server.on('connection', (socket) => {
      console.log(socket.id);
      console.log('connected!');
    });
  }

  @SubscribeMessage('newMessage')
  onnewMessage(@MessageBody() body: any) {
    console.log(body);
    this.server.emit('onMessage', {
      msg: 'New Message',
      content: body,
    });
  }
}
```

```app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { GatewayModule } from './gateway/gateway.module';

@Module({
  imports: [GatewayModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
```

# Postmanでソケット通信の確認
postmanでのソケット通信の確認方法は[こちら](https://tech-broccoli.life/articles/engineer/check-the-socketio-with-postman/)をご参考ください。

### ローカルサーバー起動
```
npm run start
```

### PostmanでSocket.IO接続
![スクリーンショット 2023-02-12 17.43.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554111/770fb8c1-06ae-7f28-4176-0e0c527b9fd0.png)

接続が成功するとログが出力されます
出力処理しているのは`gateway.ts`のonModuleInitメソッドの部分
```
rqfA4At3AECFhrZSAAAB
connected!
```

### イベントを発行する
![スクリーンショット 2023-02-12 17.48.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554111/9b6fb587-8a3b-4293-aed1-b1ebab4ed8a6.png)

発行したイベント「newMessage」を`gateway.ts`の下記処理で受信しています
```gateway.ts
  @SubscribeMessage('newMessage')
  onnewMessage(@MessageBody() body: any) {
    console.log(body);
  }
```


### イベントを受信する
イベント「newMessage」を受信したら、イベント「onMessage」を発行する流れ
```gateway.ts
@SubscribeMessage('newMessage')
  onnewMessage(@MessageBody() body: any) {
    console.log(body);
    this.server.emit('onMessage', {
      msg: 'New Message',
      content: body,
    });
  }
```

一連の流れを確認するために
まずは、Postmanで新しくタブを開いて受信したいイベントに「onMessage」を入力する
![スクリーンショット 2023-02-12 17.57.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554111/fd6a239f-0dca-bb8f-47e4-8a4b5f8c13b8.png)


イベント「newMessage」を発行する
![スクリーンショット 2023-02-12 18.07.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554111/01c512bd-af0a-070f-3954-d12f3dd10b53.png)


サーバー上でイベント「newMessage」を受信後、イベント「onMessage」が発行し、Postmanでイベントを受信する
![スクリーンショット 2023-02-12 18.09.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554111/e65f1be4-5aae-e76f-77a0-8cb87a6bb177.png)