Skip to content

iamkanguk97/nestjs-websocket

Repository files navigation

NestJS WebSocket 1대1 랜덤 채팅 시스템

NestJS와 Socket.io를 활용한 실시간 1대1 랜덤 채팅 애플리케이션입니다. WebSocket을 적용해 본 경험이 없는 것 같아서, 학습을 위해 WebSocket 기반 양방향 통신, JWT 인증, 자동 매칭 시스템, 실시간 메시지 저장 등의 기능을 구현해보았습니다.


📚 목차

  1. 프로젝트 개요
  2. 기술 스택
  3. 주요 기능
  4. ERD
  5. 실행 방법
  6. 학습 포인트
  7. 향후 개선 사항

🎯 프로젝트 개요

프로젝트 목표

  • NestJS에서 WebSocket을 활용한 실시간 통신 구현
  • Socket.io와 NestJS Gateway 패턴 학습
  • JWT 기반 WebSocket 인증 처리
  • 1대1 자동 매칭 알고리즘 구현
  • 실시간 메시지를 DB에 영구 저장
  • 외의 객체지향, 테스트 작성에 중점

주요 특징

  • 실시간 양방향 통신: Socket.io 기반 WebSocket
  • 자동 매칭 시스템: 대기열 기반 선착순 매칭
  • JWT 인증: WebSocket 연결 시 토큰 검증
  • 메시지 영구 저장: PostgreSQL을 통한 채팅 이력 관리
  • 중복 연결 방지: 같은 사용자의 여러 탭 접속 시 자동 처리

🛠 기술 스택

Backend

  • Framework: NestJS 10.x
  • Language: TypeScript 5.x
  • WebSocket: Socket.io 4.x
  • Database: PostgreSQL 16.x
  • ORM: Prisma 6.x
  • Authentication: JWT (jsonwebtoken, @nestjs/jwt)

Frontend (간단한 테스트 클라이언트)

  • HTML5, Vanilla JavaScript
  • Socket.io Client CDN

개발 도구

  • Package Manager: pnpm
  • Code Quality: ESLint, Prettier
  • Testing: Jest

✨ 주요 기능

WebSocket 연결 관리

  • JWT 기반 WebSocket 인증
  • 연결 시 자동 입장 처리
  • 중복 연결 감지 및 기존 연결 종료
  • 연결 해제 시 자동 정리 (매칭 취소, 채팅방 종료)

1대1 랜덤 매칭

  • 매칭 대기열 관리 (Memory Level, FIFO)
  • 2명 모이면 자동 매칭
  • 매칭 시 채팅방 자동 생성 (DB 저장)
  • 매칭 성공 시 상대방 정보 전달

실시간 채팅

  • 1대1 실시간 메시지 송수신
  • 메시지 DB 영구 저장
  • 채팅방 나가기
  • 상대방 나감 알림
  • 메시지 유효성 검증

ERD

prisma-markdown을 활용하여 문서를 작성했습니다.


🚀 실행 방법

1. 환경 설정

.env 파일 생성

# 데이터베이스
DATABASE_URL="postgresql://user:password@localhost:5432/chatdb"

# JWT
JWT_SECRET="your-secret-key-change-this"
JWT_EXPIRES_IN="1d"

# 서버
PORT=9090
NODE_ENV=development

2. 의존성 설치

pnpm install

3. 데이터베이스 설정

# Prisma 마이그레이션
pnpm prisma migrate dev

# Prisma Client 생성
pnpm prisma generate

4. 서버 실행

# 개발 모드
pnpm start:dev

# 프로덕션 빌드
pnpm build
pnpm start:prod

5. 접속


📝 학습 포인트

WebSocket과 HTTP의 차이, 그리고 Socket.io

  • HTTP와 다르게 WebSocket은 초기 연결 수립만 진행하고 양방향 실시간 통신 지원 프로토콜.
  • Socket.io는 Node 진영에서 WebSocket 프로토콜을 쉽게 구현할 수 있도록 도와주는 라이브러리.

NestJS WebSocket 패턴

  • WebSocket에서의 LifeCycle Hook (OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect)
  • 외에 다양하게 사용되는 이벤트 핸들러, 데코레이터 등

Socket.io 활용

  • 유니캐스트와 브로드캐스트

실시간 매칭 알고리즘

  • 메모리 기반 상태 관리
  • 대기열 자료구조 (FIFO Queue)
  • 매칭 로직 분리

메시지 영구 저장

  • 실시간 통신과 DB 저장의 분리
  • 비동기 처리 (async/await)
  • 에러 처리 (DB 저장 실패 시에도 실시간 전송 계속)

🎓 향후 개선 사항

  • 학습을 위한 프로젝트이지만, 실환경을 고려해서 심화 학습을 해보려고 합니다.
  • Claude의 도움을 받아 작성하게 되었습니다.

Redis 기반 분산 시스템

문제점:

  • 현재 매칭 큐와 연결 정보가 메모리에 저장
  • 서버 재시작 시 데이터 손실
  • 다중 서버 배포 불가능

개선 방안:

✅ Socket.io Redis Adapter 적용
✅ 매칭 큐를 Redis List/Set으로 관리
✅ 연결 정보를 Redis Hash로 저장
✅ Redis Pub/Sub으로 서버 간 통신

학습 효과:

  • 분산 시스템 아키텍처 이해
  • Redis 실전 활용
  • 수평 확장 (Scale-out) 경험

2. 동시성 제어 & Race Condition 방지

문제점:

  • 동시 매칭 요청 시 중복 매칭 가능
  • Race Condition

개선 방안:

✅ Redis 분산 락 (Redlock) 구현
✅ 매칭 프로세스에 락 적용
✅ 메시지 Sequence Number 추가
✅ DB Optimistic Locking

학습 효과:

  • 동시성 문제 해결 능력
  • 분산 락 개념 및 구현
  • 실무 버그 패턴 이해

3. 성능 최적화

✅ 메시지 배치 처리 (Bull Queue)
✅ Redis 캐싱 (유저 정보, 채팅방)
✅ DB 인덱스 최적화
✅ Connection Pool 튜닝

4. 보안 강화

✅ Rate Limiting (메시지 스팸 방지)
✅ XSS 방지 (메시지 sanitization)
✅ CORS 정책 강화

5. 기능 추가

✅ 재연결 처리 (Reconnection)

6. 테스트

✅ Unit Test (Jest)
✅ E2E Test (WebSocket)
✅ 부하 테스트 (Artillery.io)

💬 마무리

이 프로젝트를 통해 다음을 학습했습니다:

  1. ✅ NestJS에서 WebSocket 구현하는 방법
  2. ✅ Socket.io의 핵심 개념 (Room, Emit, Broadcast)
  3. ✅ WebSocket JWT 인증 처리
  4. ✅ 실시간 매칭 알고리즘 설계
  5. ✅ 실시간 데이터와 영구 저장소의 조화
  6. ✅ 클린 아키텍처 적용 (Layer 분리)

About

NestJS 에서의 WebSocket 학습

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors