Gateways

Gateways

๊ฒŒ์ดํŠธ์›จ์ด๋Š” @WebSocketGateway()๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ๊ฒŒ์ดํŠธ์›จ์ด๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ socket.io ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๊ธฐ๋ณธ ์›น ์†Œ์ผ“ ๊ตฌํ˜„์„ ํฌํ•จํ•˜์—ฌ ๊ด‘๋ฒ”์œ„ํ•œ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€์˜ ํ˜ธํ™˜์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ.

warning ํžŒํŠธ ๊ฒŒ์ดํŠธ์›จ์ด๋Š” ๋‹จ์ˆœํ•œ ๊ณต๊ธ‰์ž์™€ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋ฏ€๋กœ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์†์‰ฝ๊ฒŒ ์ข…์†์„ฑ์„ ์ฃผ์ž… ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ฒŒ์ดํŠธ์›จ์ด๋Š” ๋‹ค๋ฅธ ํด๋ž˜์Šค (๊ณต๊ธ‰์ž ๋ฐ ์ปจํŠธ๋กค๋Ÿฌ)์— ์˜ํ•ด ์ฃผ์ž… ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

Installation

๋จผ์ € ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

@@filename()
$ npm i --save @nestjs/websockets @nestjs/platform-socket.io
$ npm i --save-dev @types/socket.io
@@switch
$ npm i --save @nestjs/websockets @nestjs/platform-socket.io

Overview

์ผ๋ฐ˜์ ์œผ๋กœ ์•ฑ์ด ์›น ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์•„๋‹ˆ๊ฑฐ๋‚˜ ์ˆ˜๋™์œผ๋กœ ํฌํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๊ฐ ๊ฒŒ์ดํŠธ์›จ์ด๋Š” HTTP ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํฌํŠธ๋ฅผ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค. @WebSocketGateway(80)๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์— ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ์ด ๋™์ž‘์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ 80์€ ์„ ํƒ๋œ ํฌํŠธ ๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹ค์Œ ๊ตฌ์„ฑ์œผ๋กœ ์ด ๊ฒŒ์ดํŠธ์›จ์ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” namespace๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@WebSocketGateway(80, { namespace: 'events' })

๊ฒฝ๊ณ  ๊ฒŒ์ดํŠธ์›จ์ด๋Š” providers ๋ฐฐ์—ด ์•ˆ์— ๋„ฃ์„ ๋•Œ๊นŒ์ง€ ์‹œ์ž‘๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋„ค์ž„ ์ŠคํŽ˜์ด์Šค๋Š” ์œ ์ผํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์˜ต์…˜์ด ์•„๋‹™๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ์–ธ๊ธ‰๋œ ๋‹ค๋ฅธ ์†์„ฑ์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์†์„ฑ์€ ์ธ์Šคํ„ด์Šคํ™” ํ”„๋กœ์„ธ์Šค ๋™์•ˆ ์†Œ์ผ“ ์ƒ์„ฑ์ž๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

@WebSocketGateway(81, { transports: ['websocket'] })

์ข‹์•„, ๊ฒŒ์ดํŠธ์›จ์ด๋Š” ์ง€๊ธˆ ๋“ฃ๊ณ  ์žˆ์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ๊นŒ์ง€ ๋“ค์–ด์˜ค๋Š” ๋ฉ”์‹œ์ง€๋ฅผ subscriptํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. events ๋ฉ”์‹œ์ง€๋ฅผ subscriptionํ•˜๊ณ  ๋˜‘๊ฐ™์€ ๋ฐ์ดํ„ฐ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ์‘๋‹ตํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค.

@@filename(events.gateway)
@SubscribeMessage('events')
handleEvent(client: Client, data: string): string {
  return data;
}
@@switch
@SubscribeMessage('events')
handleEvent(client, data) {
  return data;
}

info ํžŒํŠธ @SubscribeMessage()๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” @nestjs/websockets ํŒจํ‚ค์ง€์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

handleEvent()ํ•จ์ˆ˜๋Š” ๋‘ ๊ฐœ์˜ ์ธ์ˆ˜๋ฅผ ์ทจํ•ฉ๋‹ˆ๋‹ค. ์ฒซ๋ฒˆ์งธ๋Š” ํ”Œ๋žซํผ ๋ณ„ ์†Œ์ผ“ ์ธ์Šคํ„ด์Šค์ด๊ณ  ๋‘ ๋ฒˆ์งธ๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค. ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์œผ๋ฉด ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ๋ณด๋‚ธ ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋กœ ์Šน์ธ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ณ„ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜์—ฌ, ์˜ˆ๋ฅผ ๋“ค์–ด client.emit()๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ๊ฒฝ์šฐ ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์—๊ฒŒ ์‘๋‹ตํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด ์•„๋ฌด ๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค (๋˜๋Š” "์ •์˜๋˜์ง€ ์•Š์€"๊ณผ ๊ฐ™์ด "๊ฑฐ์ง“"๊ฐ’์„ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ˜ํ™˜).

์ด์ œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ๋•Œ

socket.emit('events', { name: 'Nest' });

handleEvent()๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์œ„ ํ•ธ๋“ค๋Ÿฌ ๋‚ด์—์„œ ์ƒ์„ฑ๋œ ๋ฉ”์‹œ์ง€๋ฅผ ๋“ค์œผ๋ ค๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•ด๋‹น ์Šน์ธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ฒจ๋ถ€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

socket.emit('events', { name: 'Nest' }, data => console.log(data));

Multiple responses

์Šน์ธ์€ ํ•œ๋ฒˆ๋งŒ ๋ฐœ์†ก๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ธฐ๋ณธ WebSockets ๊ตฌํ˜„์—์„œ๋Š” ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์ œํ•œ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‘ ๊ฐ€์ง€ ์†์„ฑ์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ์„ฑ๋œ ์ด๋ฒคํŠธ์˜ ์ด๋ฆ„์ธ event์™€ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•ด์•ผ ํ•˜๋Š” data์ž…๋‹ˆ๋‹ค.

@@filename(events.gateway)
@SubscribeMessage('events')
handleEvent(client: Client, data: unknown): WsResponse<unknown> {
  const event = 'events';
  return { event, data };
}
@@switch
@SubscribeMessage('events')
handleEvent(client, data) {
  const event = 'events';
  return { event, data };
}

info ํžŒํŠธ WsResponse ์ธํ„ฐํŽ˜์ด์Šค๋Š” @nestjs/websockets ํŒจํ‚ค์ง€์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

๋“ค์–ด์˜ค๋Š” ์‘๋‹ต์„ ๋“ค์œผ๋ ค๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋‹ค๋ฅธ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

socket.on('events', data => console.log(data));

Asynchronous responses

๊ฐ ๋ฉ”์‹œ์ง€ ํ•ธ๋“ค๋Ÿฌ๋Š” ๋™๊ธฐ์‹ ๋˜๋Š” ๋น„๋™๊ธฐ์‹ (async) ์ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ Observable์„ ๋ฐ˜ํ™˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์—ฌ๋Ÿฌ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์ŠคํŠธ๋ฆผ์ด ์™„๋ฃŒ ๋  ๋•Œ๊นŒ์ง€ ๋ฐฉ์ถœ ๋จ).

@@filename(events.gateway)
@SubscribeMessage('events')
onEvent(client: Client, data: unknown): Observable<WsResponse<number>> {
  const event = 'events';
  const response = [1, 2, 3];

  return from(response).pipe(
    map(data => ({ event, data })),
  );
}
@@switch
@SubscribeMessage('events')
onEvent(client, data) {
  const event = 'events';
  const response = [1, 2, 3];

  return from(response).pipe(
    map(data => ({ event, data })),
  );
}

์œ„์˜ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๊ธฐ๋Š” 3 ๋ฒˆ (์ˆœ์„œ๋Œ€๋กœ response๋ฐฐ์—ด์˜ ๊ฐ ํ•ญ๋ชฉ๊ณผ ํ•จ๊ป˜) ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.

Lifecycle hooks

3 ๊ฐ€์ง€ ์œ ์šฉํ•œ ์ˆ˜๋ช…์ฃผ๊ธฐ ํ›„ํฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋‘ ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์œผ๋ฉฐ ๋‹ค์Œ ํ‘œ์— ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

OnGatewayInit

afterInit() ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ•์ œ๋กœ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŠน์ • ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค๋ฅผ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋‚˜๋จธ์ง€๋ฅผ ํ™•์‚ฐ์‹œํ‚ต๋‹ˆ๋‹ค).

OnGatewayConnection

handleConnection() ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ•์ œ๋กœ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŠน์ • ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ์ธ์Šคํ„ด์Šค๋ฅผ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

OnGatewayDisconnect

handleDisconnect() ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ•์ œ๋กœ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŠน์ • ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ์ธ์Šคํ„ด์Šค๋ฅผ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

info ํžŒํŠธ ๊ฐ ๋ผ์ดํ”„ ์‚ฌ์ดํด ์ธํ„ฐํŽ˜์ด์Šค๋Š”@nestjs/websockets ํŒจํ‚ค์ง€์—์„œ ๊ณต๊ฐœ๋ฉ๋‹ˆ๋‹ค.

Server

๊ฒฝ์šฐ์— ๋”ฐ๋ผ ํ”Œ๋žซํผ ๋ณ„ ๊ธฐ๋ณธ ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค์— ์ง์ ‘ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ๋Š” afterInit()๋ฉ”์†Œ๋“œ (OnGatewayInit ์ธํ„ฐํŽ˜์ด์Šค)์— ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ @WebSocketServer()๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@WebSocketServer()
server: Server;

warning ์•Œ๋ฆผ @WebSocketServer()๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” @nestjs/websockets ํŒจํ‚ค์ง€์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

Nest๋Š” ์‚ฌ์šฉํ•  ์ค€๋น„๊ฐ€ ๋˜๋ฉด ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค๋ฅผ ์ด ์†์„ฑ์— ์ž๋™์œผ๋กœ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

Example

์‹ค์ œ ์‚ฌ๋ก€๋Š” ์—ฌ๊ธฐ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Last updated

Was this helpful?