실시간 채팅 서버 개발 - 03 (방 접속하기)

2026. 1. 19. 10:55·NestJS/개발

이전 프로젝트 정리

이전 포스트에서는 채팅 서버에서 방을 어떻게 생성하고, Redis를 이용해 방의 상태와 생명주기를 관리하는 구조를 정리했다. 방은 단순히 생성되고 사라지는 데이터가 아니라, WAIT → PLAYING → END 로 이어지는 명확한 상태를 가지며, 각 상태에 따라 TTL을 다르게 적용해 안전하게 관리해야 한다고 생각을 가지며 마무리 하였다. 이를 통해 유령방은 자동으로 정리하면서도, 게임이 진행 중인 방이 TTL 만료로 삭제되는 문제는 방지할 수 있었다. 이제 다음으로 해결해야 할 문제는 "방에 어떻게 입장할 것인가"이다. 방 접속은 단순히 인원 수를 증가시키는 작업처럼 보이지만, 실제로는 다음과 같은 요구사항을 동시에 만족해야 한다.

  • 최대 인원 수 초과 방지
  • 동시 접속 상황에서도 정확한 인원 관리
  • 정상적인 요청만 소켓 join 으로 연결
  • Redis 상태와 실제 접속 상태의 일관성 유지

이번 포스트에서는 위의 사항들을 고려해서 HTTP 기반 방 접속 로직을 설계하고, 검증이 완료된 경우에만 WebSocket join 이 이루어지도록 전체 흐름을 정리해보려고 한다.


방 참여 로직 설계 전 고려사항

  • Redis로 방 관리를 한번 체크 해준다.
    먼저 HTTP API에서 Redis를 통해 방 상태를 검증한다.
    이 단계에서는 방 존재 여부, 현재 인원 수, 최대 인원 제한과 같은
    모든 인증 및 검증 로직을 처리한다.

  • 그리고 소켓으로 join 시킨다.
    검증이 완료된 이후에만 WebSocket을 통해 room join 을 수행한다.
    소켓은 상태를 판단하지 않고, 실시간 통신과 연결 관리에만 집중한다.

  • 소켓으로만 관리하지 않는다. 
    방 참여를 소켓으로만 처리하지 않는 이유는 명확하다.
    방 인원 관리, 정리 로직까지 모두 소켓 이벤트에 포함시키면
    소켓 핸들러가 빠르게 비대해지고, 예외 처리와 테스트가 어려워진다.

  • 소켓은 join을 할 경우에 방이 자동으로 생성된다.
    Socket.io 특성상 join 시 방은 자동으로 생성된다.
    따라서 방의 생성과 생명주기는 Redis에서 명시적으로 관리하고,
    소켓 방은 비어 있는 경우 자연스럽게 정리되도록 맡긴다.

닉네임 설정하기 - HTTP

소켓 서버는 아무 요청이나 받아들여서는 안 된다. JWT 토큰은 소켓 서버 접속 시 전달되어, 이 사용자가 서버에서 정상적인 흐름을 거쳐 발급된 사용자인지를 확인하는 역할을 한다. 결론적으로 닉네임을 설정하면서 JWT 토큰을 발행하고 추후에 소켓서버에 참여할때 전송하여 검증까지 완료시킨다.

async createNickname(nickname: string) {
  const result = { nickname , Authorization: await this.jwt.createJwt(nickname) };
  return result;
}


방 참여하기 - HTTP

메인코드

import {
  BadRequestException,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { randomUUID } from 'crypto';
import { RedisService } from 'src/redis/redis.service';

@Injectable()
export class RoomService {
  constructor(private readonly redis: RedisService) {}
  
  async joinRoom(roomId: string) {
    const key = `room:${roomId}`;

    const room = await this.redis.client.hgetall(key);

    if (Object.keys(room).length === 0) {
      throw new NotFoundException('방이 존재하지 않습니다.');
    }

    const players = Number(room.players);
    const maxPlayers = Number(room.maxPlayers);

    if (players >= maxPlayers) {
      throw new BadRequestException('방이 가득 찼습니다.');
    }

    await this.redis.client.hincrby(key, 'players', 1);

    return { roomJoin: true, players: players + 1, maxPlayers };
  }
}

 

코드설명

const room = await this.redis.client.hgetall(key);
const maxPlayers = room.maxPlayers;

if (Object.keys(room).length === 0) {
  throw new NotFoundException('방이 존재하지 않습니다.');
}

 

roomId를 기반으로 Redis Hash 전체를 조회한다. 방이 존재한다면 최소한 하나 이상의 필드를 가지고 있어야 하며, 빈 객체가 반환되었다는 것은 방이 이미 삭제되었거나 존재하지 않는다는 의미다. 이 검증을 통해서 생성되지 않은 방이나, 이미 만료되어 사라진 방에 접속하는것을 초기에 차단해버린다.

const players = Number(room.players);
const maxPlayers = Number(room.maxPlayers);
if (players >= maxPlayers) {
  throw new BadRequestException('방이 가득 찼습니다.');
}

그리고 마지막으로 방이 풀인지 확인하여 기본적인 검증으로 기본적인 유효성을 검사한다.

await this.redis.client.hincrby(key, 'players', 1);

검증이 완료된 이후에만 현재 인원 수를 1 증가시킨다. 이렇게 HTTP 단계에서 인원 수를 먼저 증가시킴으로써, 소켓 join 이후 발생할 수 있는 상태 불일치 비정상적인 중복 입장 을 어느 정도 예방할 수 있다.


방 참여하기 - Socket

 

 

'NestJS > 개발' 카테고리의 다른 글

실시간 채팅 서버 개발 - 02 (방 생성하기)  (0) 2026.01.18
실시간 채팅 서버 개발 - 01 (Redis 및 NestJS 셋팅)  (1) 2026.01.14
Redis/BullMQ 이용하여 연산 작업 따로하기  (0) 2025.12.23
JWT - Passport 사용하기  (0) 2025.12.22
JWT - 역할 기반 관리하기  (1) 2025.12.21
'NestJS/개발' 카테고리의 다른 글
  • 실시간 채팅 서버 개발 - 02 (방 생성하기)
  • 실시간 채팅 서버 개발 - 01 (Redis 및 NestJS 셋팅)
  • Redis/BullMQ 이용하여 연산 작업 따로하기
  • JWT - Passport 사용하기
나는지토
나는지토
  • 나는지토
    안녕은헬로입니다.
    나는지토
  • 전체
    오늘
    어제
    • 분류 전체보기 (27)
      • Backend Design (1)
      • NestJS (19)
        • 개발 (9)
        • 개념과 구조 정리 (10)
      • SpringBoot (0)
      • Java (4)
        • 코테 (0)
      • PostgreSQL (2)
      • Docker (1)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    nestjs
    토큰 검사
    db 연결 오류
    ArrayList
    Collections
    조회 방식
    nestjs/jwt
    채팅
    서비스
    Java
    커서기반 조회
    JWT
    BullMQ
    코딩테스트
    PostgreSQL
    역할 검사
    컨트롤러
    자료구조
    Redis
    인증 가드
  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
나는지토
실시간 채팅 서버 개발 - 03 (방 접속하기)
상단으로

티스토리툴바