Adapters
Adapters
WebSockets ๋ชจ๋์ ํ๋ซํผ์ ๊ตฌ์ ๋ฐ์ง ์์ผ๋ฏ๋ก WebSocketAdapter
์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ (๋๋ ๊ธฐ๋ณธ ๊ตฌํ)๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ์ด ์ธํฐํ์ด์ค๋ ๋ค์ ํ์ ์ค๋ช
๋ ๋ช๊ฐ์ง ๋ฉ์๋๋ฅผ ๊ฐ์ ๋ก ๊ตฌํํฉ๋๋ค.
create
์ ๋ฌ๋ ์ธ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ผ ์ธ์คํด์ค๋ฅผ ๋ง๋ญ๋๋ค.
bindClientConnect
ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ธ๋
bindClientDisconnect
ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ ๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ธ๋ํฉ๋๋ค (์ ํ ์ฌํญ *).
bindMessageHandlers
๋ค์ด์ค๋ ๋ฉ์์ง๋ฅผ ํด๋น ๋ฉ์์ง ์ฒ๋ฆฌ๊ธฐ์ ๋ฐ์ธ๋ฉ
close
์๋ฒ ์ธ์คํด์ค๋ฅผ ์ข ๋ฃํฉ๋๋ค
Extend socket.io
socket.io ํจํค์ง๋ IoAdapter
ํด๋์ค์ ์ธ์ฌ ์์ต๋๋ค. ์ด๋ํฐ์ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ํฅ์ ์ํค๋ ค๋ฉด ์ด๋ป๊ฒํฉ๋๊น? ์๋ฅผ ๋ค์ด, ๊ธฐ์ ์๊ตฌ ์ฌํญ์๋ ์น ์๋น์ค์ ์ฌ๋ฌ ๋ถํ ๋ถ์ฐ ์ธ์คํด์ค์์ ์ด๋ฒคํธ๋ฅผ ๋ธ๋ก๋ ์บ์คํธํ๋ ๊ธฐ๋ฅ์ด ํ์ํฉ๋๋ค. ์ด๋ฅผ ์ํด IoAdapter
๋ฅผ ํ์ฅํ๊ณ ์๋ก์ด socket.io ์๋ฒ๋ฅผ ์ธ์คํด์คํํ๋ ๋จ์ผ ๋ฐฉ๋ฒ์ ์ฌ ์ ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋จผ์ ํ์ํ ํจํค์ง๋ฅผ ์ค์นํ์ญ์์ค.
$ npm i --save socket.io-redis
ํจํค์ง๊ฐ ์ค์น๋๋ฉด RedisIoAdapter
ํด๋์ค๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
import { IoAdapter } from '@nestjs/platform-socket.io';
import * as redisIoAdapter from 'socket.io-redis';
const redisAdapter = redisIoAdapter({ host: 'localhost', port: 6379 });
export class RedisIoAdapter extends IoAdapter {
createIOServer(port: number, options?: any): any {
const server = super.createIOServer(port, options);
server.adapter(redisAdapter);
return server;
}
}
๊ทธ๋ฐ ๋ค์ ์๋ก ์์ฑ๋ Redis ์ด๋ํฐ๋ก ์ ํํ๋ฉด๋ฉ๋๋ค.
const app = await NestFactory.create(ApplicationModule);
app.useWebSocketAdapter(new RedisIoAdapter(app));
Ws library
์ฌ์ฉ ๊ฐ๋ฅํ ๋ ๋ค๋ฅธ ์ด๋ํฐ๋ WsAdapter
์ธ๋ฐ, ์ด๋ ์ฐจ๋ก๋ก ํ๋ ์ ์ํฌ ์ฌ์ด์ ํ๋ก์์ฒ๋ผ ์๋ํ๋ฉฐ ๋น ๋ฅด๊ณ ์ฒ ์ ํ๊ฒ ํ
์คํธ ๋ ws ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํฉํฉ๋๋ค. ์ด ์ด๋ํฐ๋ ๊ธฐ๋ณธ ๋ธ๋ผ์ฐ์ WebSocket๊ณผ ์๋ฒฝํ๊ฒ ํธํ๋๋ฉฐ socket.io ํจํค์ง๋ณด๋ค ํจ์ฌ ๋น ๋ฆ
๋๋ค. ๋ถํํ๋, ์ฆ์ ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ฅ์ด ํจ์ฌ ๋ ์ ์ต๋๋ค. ๊ฒฝ์ฐ์ ๋ฐ๋ผ ๊ผญ ํ์ํ ๊ฒ์ ์๋๋๋ค.
ws
๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๋จผ์ ํ์ํ ํจํค์ง๋ฅผ ์ค์นํด์ผํฉ๋๋ค :
$ npm i --save @nestjs/platform-ws
ํจํค์ง๊ฐ ์ค์น๋๋ฉด ์ด๋ํฐ๋ฅผ ์ ํํ ์ ์์ต๋๋ค.
const app = await NestFactory.create(ApplicationModule);
app.useWebSocketAdapter(new WsAdapter(app));
info ํํธ
WsAdapter
๋@nestjs/platform-ws
์์ ๊ฐ์ ธ์ต๋๋ค.
Advanced (custom adapter)
๋ฐ๋ชจ ๋ชฉ์ ์ผ๋ก ws ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์๋์ผ๋ก ํตํฉํ๋ ค๊ณ ํฉ๋๋ค. ์ธ๊ธํ ๋ฐ์ ๊ฐ์ด ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ด๋ํฐ๋ ์ด๋ฏธ ์์ฑ๋์์ผ๋ฉฐ @nestjs/platform-ws
ํจํค์ง์์ WsAdapter
ํด๋์ค๋ก ๊ฐ์ ธ์ต๋๋ค. ๋จ์ํ๋ ๊ตฌํ์ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ผ ์ ์์ต๋๋ค.
@@filename(ws-adapter)
import * as WebSocket from 'ws';
import { WebSocketAdapter, INestApplicationContext } from '@nestjs/common';
import { MessageMappingProperties } from '@nestjs/websockets';
import { Observable, fromEvent, EMPTY } from 'rxjs';
import { mergeMap, filter } from 'rxjs/operators';
export class WsAdapter implements WebSocketAdapter {
constructor(private readonly app: INestApplicationContext) {}
create(port: number, options: any = {}): any {
return new ws.Server({ port, ...options });
}
bindClientConnect(server, callback: Function) {
server.on('connection', callback);
}
bindMessageHandlers(
client: WebSocket,
handlers: MessageMappingProperties[],
process: (data: any) => Observable<any>,
) {
fromEvent(client, 'message')
.pipe(
mergeMap(data => this.bindMessageHandler(data, handlers, process)),
filter(result => result),
)
.subscribe(response => client.send(JSON.stringify(response)));
}
bindMessageHandler(
buffer,
handlers: MessageMappingProperties[],
process: (data: any) => Observable<any>,
): Observable<any> {
const message = JSON.parse(buffer.data);
const messageHandler = handlers.find(
handler => handler.message === message.event,
);
if (!messageHandler) {
return EMPTY;
}
return process(messageHandler.callback(message.data));
}
close(server) {
server.close();
}
}
info ํํธ ws ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ๋ ค๋ฉด ์์ฒด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์์ฑํ๋ ๋์ ๋ด์ฅ
WsAdapter
๋ฅผ ์ฌ์ฉํ์ญ์์ค.
๊ทธ๋ฐ ๋ค์ useWebSocketAdapter()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ์ ์ ์ด๋ํฐ๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
@@filename(main)
const app = await NestFactory.create(ApplicationModule);
app.useWebSocketAdapter(new WsAdapter(app));
Example
WsAdapter
๋ฅผ ์ฌ์ฉํ๋ ์ค์ ์์ ๋ ์ฌ๊ธฐ์ ์์ต๋๋ค.
Last updated
Was this helpful?