# NestJS i WebSockets w 2026: Komunikacja w Czasie Rzeczywistym, Gateway i Pytania Rekrutacyjne > Kompleksowy przewodnik po WebSockets w NestJS z wzorcem Gateway, integracją Socket.IO, uwierzytelnianiem, obsługą błędów i pytaniami rekrutacyjnymi na 2026 rok. - Published: 2026-08-10 - Updated: 2026-08-10 - Author: Anthony Fillion-Maillet - Tags: nestjs, websockets, real-time, socket.io, gateway - Reading time: 5 min --- NestJS WebSockets oferują strukturalne podejście do komunikacji w czasie rzeczywistym przy użyciu wzorca Gateway. W przeciwieństwie do surowych implementacji WebSocket, NestJS abstrahuje złożoność poprzez dekoratory i bezproblemowo integruje się z systemem wstrzykiwania zależności. > **Szybka Definicja** > > WebSocket Gateway w NestJS to klasa ozdobiona dekoratorem `@WebSocketGateway()`, która obsługuje dwukierunkową komunikację między klientem a serwerem. Obsługuje wiele adapterów (Socket.IO, ws) i integruje się z Guards, Pipes oraz Interceptors w NestJS. ## Konfiguracja WebSocket Gateway z Socket.IO Domyślny adapter w NestJS wykorzystuje [Socket.IO](https://socket.io/docs/v4/), który zapewnia automatyczne ponowne łączenie, obsługę pokoi i fallback do HTTP long-polling. Instalacja wymaga pakietu specyficznego dla platformy wraz z głównym modułem WebSockets. ```bash # terminal npm install @nestjs/websockets @nestjs/platform-socket.io socket.io ``` Podstawowy gateway nasłuchuje przychodzących wiadomości i może rozsyłać odpowiedzi do połączonych klientów. ```typescript // chat.gateway.ts import { WebSocketGateway, WebSocketServer, SubscribeMessage, MessageBody, ConnectedSocket, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; @WebSocketGateway({ cors: { origin: '*' }, // Configure CORS for browser clients }) export class ChatGateway { @WebSocketServer() server: Server; // Access to the underlying Socket.IO server @SubscribeMessage('message') // Listen for 'message' events handleMessage( @MessageBody() data: { text: string; room: string }, @ConnectedSocket() client: Socket, ): void { // Broadcast to all clients in the room except sender client.to(data.room).emit('message', { text: data.text, senderId: client.id, timestamp: Date.now(), }); } } ``` Dekorator `@SubscribeMessage` wiąże metodę z konkretną nazwą zdarzenia. `@MessageBody()` wyodrębnia payload, podczas gdy `@ConnectedSocket()` zapewnia dostęp do gniazda klienta dla ukierunkowanych odpowiedzi. ## Hooki Cyklu Życia do Zarządzania Połączeniami Gatewaye NestJS implementują interfejsy cyklu życia do obsługi połączeń i rozłączeń klientów. Te hooki umożliwiają czyszczenie zasobów, śledzenie obecności i walidację połączeń. ```typescript // presence.gateway.ts import { WebSocketGateway, OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; import { Logger } from '@nestjs/common'; @WebSocketGateway() export class PresenceGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect { private readonly logger = new Logger(PresenceGateway.name); private connectedUsers = new Map(); afterInit(server: Server): void { // Called once when the gateway initializes this.logger.log('WebSocket Gateway initialized'); } handleConnection(client: Socket): void { // Track new connections this.connectedUsers.set(client.id, { joinedAt: new Date() }); this.logger.log(`Client connected: ${client.id}`); } handleDisconnect(client: Socket): void { // Cleanup on disconnect this.connectedUsers.delete(client.id); this.logger.log(`Client disconnected: ${client.id}`); } } ``` Trzy interfejsy cyklu życia służą różnym celom: `OnGatewayInit` uruchamia się raz przy starcie, `OnGatewayConnection` wyzwala się przy każdym połączeniu klienta, a `OnGatewayDisconnect` obsługuje czyszczenie gdy klienci opuszczają połączenie. ## Uwierzytelnianie z WebSocket Guards Połączenia WebSocket wymagają walidacji uwierzytelniania przed zezwoleniem na dostęp do chronionych zdarzeń. NestJS Guards współpracują z gatewayami, chociaż kontekst wykonania różni się od żądań HTTP. Oficjalna [dokumentacja NestJS WebSockets](https://docs.nestjs.com/websockets/gateways) szczegółowo opisuje integrację guards. ```typescript // ws-auth.guard.ts import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { WsException } from '@nestjs/websockets'; import { JwtService } from '@nestjs/jwt'; import { Socket } from 'socket.io'; @Injectable() export class WsAuthGuard implements CanActivate { constructor(private jwtService: JwtService) {} canActivate(context: ExecutionContext): boolean { const client: Socket = context.switchToWs().getClient(); // Extract token from handshake auth or query params const token = client.handshake.auth?.token || client.handshake.query?.token; if (!token) { throw new WsException('Missing authentication token'); } try { const payload = this.jwtService.verify(token as string); // Attach user data to socket for later use client.data.user = payload; return true; } catch { throw new WsException('Invalid token'); } } } ``` Guard stosuje się do klasy gateway lub poszczególnych handlerów wiadomości za pomocą dekoratora `@UseGuards()`. Klasa `WsException` rzuca błędy, które klient otrzymuje poprzez zdarzenie error Socket.IO. ```typescript // secure-chat.gateway.ts import { UseGuards } from '@nestjs/common'; import { WebSocketGateway, SubscribeMessage } from '@nestjs/websockets'; import { WsAuthGuard } from './ws-auth.guard'; @WebSocketGateway() @UseGuards(WsAuthGuard) // Protect all handlers in this gateway export class SecureChatGateway { @SubscribeMessage('privateMessage') handlePrivateMessage(): void { // Only authenticated clients reach this handler } } ``` Dla pytań dotyczących uwierzytelniania na poziomie modułu warto zapoznać się z [modułem pytań rekrutacyjnych NestJS o uwierzytelnianiu](/technologies/node-nestjs/interview-questions/authentication-jwt) obejmującym strategie JWT i zarządzanie sesjami. ## Wzorce Rozgłaszania Oparte na Pokojach Pokoje Socket.IO umożliwiają ukierunkowane dostarczanie wiadomości do podzbiorów połączonych klientów. Typowe przypadki użycia obejmują pokoje czatu, lobby gier i funkcje współpracy na żywo. ```typescript // room.gateway.ts import { WebSocketGateway, SubscribeMessage, ConnectedSocket, MessageBody, WebSocketServer, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; @WebSocketGateway() export class RoomGateway { @WebSocketServer() server: Server; @SubscribeMessage('joinRoom') handleJoinRoom( @MessageBody() roomId: string, @ConnectedSocket() client: Socket, ): { event: string; data: string } { // Add client to the specified room client.join(roomId); // Notify others in the room client.to(roomId).emit('userJoined', { userId: client.id }); return { event: 'joinedRoom', data: roomId }; } @SubscribeMessage('leaveRoom') handleLeaveRoom( @MessageBody() roomId: string, @ConnectedSocket() client: Socket, ): void { client.leave(roomId); client.to(roomId).emit('userLeft', { userId: client.id }); } @SubscribeMessage('roomBroadcast') handleRoomBroadcast( @MessageBody() payload: { roomId: string; message: string }, ): void { // Send to all clients in room, including sender this.server.to(payload.roomId).emit('roomMessage', payload.message); } } ``` Różnica między `client.to(room).emit()` a `server.to(room).emit()` ma znaczenie: pierwsza wyklucza nadawcę, podczas gdy druga obejmuje wszystkich członków pokoju. ## Obsługa Błędów z Filtrami Wyjątków Wyjątki WebSocket wymagają dedykowanych filtrów, ponieważ filtry wyjątków HTTP nie mają zastosowania w kontekstach gateway. Niestandardowe filtry przechwytują `WsException` i formatują odpowiedzi błędów dla klientów. ```typescript // ws-exception.filter.ts import { Catch, ArgumentsHost, ExceptionFilter } from '@nestjs/common'; import { WsException } from '@nestjs/websockets'; import { Socket } from 'socket.io'; @Catch(WsException) export class WsExceptionFilter implements ExceptionFilter { catch(exception: WsException, host: ArgumentsHost): void { const client: Socket = host.switchToWs().getClient(); const error = exception.getError(); // Send structured error to client client.emit('error', { type: 'WsException', message: typeof error === 'string' ? error : error, timestamp: new Date().toISOString(), }); } } ``` Filtry stosuje się na poziomie gateway dla spójnej obsługi błędów we wszystkich handlerach wiadomości. ```typescript // filtered.gateway.ts import { UseFilters } from '@nestjs/common'; import { WebSocketGateway } from '@nestjs/websockets'; import { WsExceptionFilter } from './ws-exception.filter'; @WebSocketGateway() @UseFilters(WsExceptionFilter) export class FilteredGateway { // All handlers benefit from centralized error handling } ``` Ten wzorzec odzwierciedla filozofię NestJS dotyczącą dekoratorów i filtrów opisaną w [module middleware i interceptors](/technologies/node-nestjs/interview-questions/middleware-interceptors). ## Skalowanie WebSockets z Adapterem Redis Wdrożenia WebSocket na pojedynczym serwerze zawodzą, gdy load balancing rozprowadza klientów na wiele instancji. [Adapter Redis Socket.IO](https://socket.io/docs/v4/redis-adapter/) synchronizuje zdarzenia między instancjami poprzez mechanizm pub/sub. ```typescript // app.module.ts import { Module } from '@nestjs/common'; import { createAdapter } from '@socket.io/redis-adapter'; import { createClient } from 'redis'; import { ChatGateway } from './chat.gateway'; @Module({ providers: [ ChatGateway, { provide: 'REDIS_ADAPTER', useFactory: async () => { const pubClient = createClient({ url: process.env.REDIS_URL }); const subClient = pubClient.duplicate(); await Promise.all([pubClient.connect(), subClient.connect()]); return createAdapter(pubClient, subClient); }, }, ], }) export class AppModule {} ``` Następnie gateway używa adaptera do komunikacji między instancjami. ```typescript // scalable.gateway.ts import { WebSocketGateway, WebSocketServer, OnGatewayInit, } from '@nestjs/websockets'; import { Inject } from '@nestjs/common'; import { Server } from 'socket.io'; import { Adapter } from 'socket.io-adapter'; @WebSocketGateway() export class ScalableGateway implements OnGatewayInit { @WebSocketServer() server: Server; constructor(@Inject('REDIS_ADAPTER') private redisAdapter: Adapter) {} afterInit(): void { // Attach Redis adapter for multi-instance support this.server.adapter(this.redisAdapter as any); } } ``` Z adapterem Redis wiadomość wyemitowana na jednej instancji serwera dociera do klientów połączonych z dowolną instancją w klastrze. ## Popularne Pytania Rekrutacyjne dotyczące NestJS WebSockets Rozmowy techniczne często badają zrozumienie decyzji architektonicznych dotyczących czasu rzeczywistego i szczegółów implementacyjnych specyficznych dla NestJS. > **Często Zadawane** > > **Jak NestJS obsługuje uwierzytelnianie WebSocket inaczej niż HTTP?** > > Middleware HTTP nie wykonuje się dla połączeń WebSocket. Uwierzytelnianie odbywa się podczas fazy handshake lub poprzez Guards zastosowane do gateway. Walidacja tokenów zazwyczaj odbywa się w `handleConnection()` lub w niestandardowym Guard, który odczytuje z `socket.handshake.auth`. **Jaka jest różnica między konfiguracją portu `@WebSocketGateway()` a głównym portem aplikacji?** Domyślnie gatewaye WebSocket współdzielą port serwera HTTP. Określenie portu w `@WebSocketGateway(3001)` tworzy oddzielny serwer WebSocket na tym porcie. Współdzielone porty upraszczają wdrożenie, ale wymagają routingu opartego na ścieżkach (`/socket.io`) przy użyciu reverse proxy. **Jak testować gatewaye WebSocket w NestJS?** Narzędzia testowe NestJS wspierają testowanie gateway poprzez `Test.createTestingModule()`. Biblioteka [socket.io-client](https://github.com/socketio/socket.io-client) łączy się z serwerem testowym. Hooki cyklu życia i handlery wiadomości testuje się emitując zdarzenia i sprawdzając odpowiedzi lub efekty uboczne. ```typescript // chat.gateway.spec.ts import { Test } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import { io, Socket } from 'socket.io-client'; import { ChatGateway } from './chat.gateway'; describe('ChatGateway', () => { let app: INestApplication; let client: Socket; beforeAll(async () => { const module = await Test.createTestingModule({ providers: [ChatGateway], }).compile(); app = module.createNestApplication(); await app.listen(3000); client = io('http://localhost:3000'); }); afterAll(async () => { client.disconnect(); await app.close(); }); it('receives message acknowledgment', (done) => { client.emit('message', { text: 'test', room: 'lobby' }); client.on('message', (data) => { expect(data.text).toBe('test'); done(); }); }); }); ``` **Kiedy należy używać adaptera ws zamiast Socket.IO?** Adapter [biblioteki ws](https://github.com/websockets/ws) (`@nestjs/platform-ws`) oferuje mniejszy narzut dla aplikacji, które nie potrzebują funkcji Socket.IO takich jak automatyczne ponowne łączenie, pokoje czy transporty fallback. Systemy handlu wysokiej częstotliwości i serwery gier często preferują ws ze względu na zmniejszone opóźnienia. Dla szerszych koncepcji architektury NestJS, powiązany artykuł o [Guards, Interceptors i Architekturze Modularnej](/blog/node-nestjs/nestjs-guards-interceptors-modular-architecture) opisuje jak te wzorce integrują się w kontekstach HTTP i WebSocket. ## Podsumowanie - WebSocket Gateways integrują się z dependency injection NestJS, Guards i Filters dla spójnych wzorców w endpointach HTTP i czasu rzeczywistego - Hooki cyklu życia (`OnGatewayConnection`, `OnGatewayDisconnect`) zarządzają śledzeniem obecności i czyszczeniem zasobów - Przepływy uwierzytelniania różnią się od HTTP; walidacja tokenów odbywa się podczas handshake lub poprzez dedykowane WebSocket Guards - Rozgłaszanie oparte na pokojach z Socket.IO umożliwia ukierunkowane wiadomości bez ręcznego zarządzania listami socketów - Adapter Redis rozwiązuje skalowanie horyzontalne przez synchronizację zdarzeń między wieloma instancjami serwera - Filtry wyjątków wymagają implementacji specyficznych dla WebSocket przy użyciu `WsException` i niestandardowych filtrów --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pl/blog/node-nestjs/nestjs-websockets-real-time-gateway-best-practices