- Published on
24.02.02 이찬우 회고
- Authors
- Name
- 이찬우

어제 작성한 ERD에 이어서, 아직 기획안이 완성되진 않았지만 지금까지 회의에서 나온 아이디어를 토대로 서버 아키텍쳐를 설계해 보았습니다. 서버는 크게 3부분으로 나뉩니다.
- Colyseus: 실시간으로 처리되어야 하는 부분을 담당할 서버입니다.
- Nestjs: API 요청을 처리할 서버입니다.
- DB: 데이터베이스입니다.
Colyseus
Colyseus는 멀티플레이어 게임을 구축하고 관리하기 위한 오픈 소스 게임 서버 프레임워크입니다. 주로 웹 기술과 함께 사용되며, JavaScript와 TypeScript로 작성되었습니다. Colyseus는 게임 서버 및 클라이언트 간의 실시간 통신을 용이하게 만들어주는 다양한 기능을 제공합니다.
Colyseus의 특징
- 실시간 통신: Colyseus는 WebSocket을 기반으로 하는 효율적인 실시간 통신을 제공하여 플레이어 간의 상호 작용을 지원합니다.
- 룸 시스템: 게임 서버에서 관리되는 각 게임 세션을 "룸"이라고 부르며, 이를 통해 여러 게임 인스턴스를 동시에 실행하고 관리할 수 있습니다.
- 상태 동기화: Colyseus는 게임 서버와 클라이언트 간에 데이터를 동기화하는 데 사용되는 내장된 상태 동기화 메커니즘을 제공합니다.
- 인증 및 보안: Colyseus는 인증 및 보안 기능을 지원하여 안전한 멀티플레이어 게임을 개발하는 데 도움을 줍니다.
- 플랫폼 독립성: Colyseus는 JavaScript 및 TypeScript를 사용하여 작성되었으므로 여러 플랫폼에서 사용할 수 있습니다.
또한 colyseus는 확장이 용이합니다.

우리가 만들 술래잡기 게임은 방을 만들고, 그 방 안에서 플레이어들이 게임을 플레이하는 구조입니다. 따라서 방을 만들기 쉽고, 방을 기준으로 관리하기 용이한 프레임워크인 colyseus를 사용하게 되었습니다.
Nestjs
NestJS는 TypeScript를 기반으로 하는 서버사이드 프레임워크로, Node.js를 위한 확장성 있고 모듈화된 웹 애플리케이션을 빌드할 수 있게 해주는 도구입니다.
Nestjs 특징
- 모듈화: NestJS는 모듈화된 구조를 채택하여 애플리케이션을 간결하게 유지하고 코드의 재사용성을 증가시킵니다. 각 모듈은 특정 기능 또는 비즈니스 로직을 담당하며, 모듈 간의 의존성을 명시적으로 정의할 수 있습니다.
- 의존성 주입 (Dependency Injection): NestJS는 의존성 주입을 통해 클래스 및 컴포넌트 간의 의존성을 쉽게 관리할 수 있습니다. 이는 테스트 용이성과 코드의 재사용성을 증가시키는 데 도움이 됩니다.
- Middleware 및 인터셉터: Express의 미들웨어를 사용하거나, NestJS에서 제공하는 인터셉터를 활용하여 요청 및 응답 처리를 중간에 가로챌 수 있습니다.
- ORM (Object-Relational Mapping) 지원: NestJS는 다양한 ORM 라이브러리를 지원하며, TypeORM이 기본적으로 내장되어 있습니다. 이를 통해 데이터베이스와의 상호 작용이 간편해집니다.
- WebSocket 지원: 실시간 통신을 위한 WebSocket을 쉽게 통합할 수 있습니다.
Nestjs는 API서버를 만드는데 특화된 서버 프레임워크입니다. 또한 microservice architecture(msa) 패턴을 쉽게 만들 수 있는 기능도 제공하기 때문에 채용하게 되었습니다. 우리의 프로젝트는 멀티플레이 온라인 게임입니다. 그러므로 대규모서비스를 제공할 수 있도록 서버의 부하를 줄이고, 장애가 발생했을 때 모든 서버가 중단되지 않고 단일 마이크로 서비스만 영향을 받도록 설계하여야한다고 판단하였습니다. 따라서 모놀리식 구조보다는 msa 패턴을 사용하여 설계하였습니다.
아래는 모놀리식 아키텍쳐 패턴과 msa 패턴의 장단점입니다.
모놀리식 아키텍쳐

모놀리식 아키텍처는 소프트웨어 애플리케이션을 개발하는 데 사용되는 전통적인 아키텍처 패턴 중 하나입니다. 이 아키텍처는 애플리케이션을 단일한 코드베이스로 구성하며, 모든 기능과 서비스가 하나의 통합된 시스템으로 동작하는 특징을 가지고 있습니다. 주로 대규모의 단일 응용프로그램으로 구성되어 있습니다.
모놀리식 아키텍처 특징
- 단일 코드베이스: 애플리케이션의 모든 구성 요소와 모듈이 하나의 코드베이스에 통합되어 있습니다.
- 단일 데이터베이스: 주로 하나의 중앙 데이터베이스가 사용되며, 모든 데이터는 해당 데이터베이스에서 관리됩니다.
- 단일 배포 단위: 전체 애플리케이션을 한 번에 배포합니다. 하나의 모듈을 업데이트하면 전체 애플리케이션이 새로운 버전으로 갱신되어야 합니다.
- 서비스 간 직접 호출: 모놀리식 아키텍처에서는 주로 서비스 간 직접 호출이 이루어집니다. 모듈 간 통신이 비교적 간단하게 이루어집니다.
- 확장이 어려움: 특정 기능이나 서비스의 확장이 어려울 수 있습니다. 전체 애플리케이션을 확장해야 하기 때문에 확장성이 떨어질 수 있습니다.
- 유지보수가 어려움: 큰 규모의 코드베이스를 관리하기 위해선 유지보수가 복잡해질 수 있습니다.
- 종속성 문제: 하나의 모듈에서 발생한 오류가 전체 시스템에 영향을 미칠 수 있습니다.
마이크로서비스 아키텍쳐

이크로서비스 아키텍처는 소프트웨어 시스템을 작은, 독립적인 서비스로 분리하고 이 서비스들을 조합하여 전체 시스템을 구축하는 아키텍처 패턴입니다. 전통적인 몰리식(monolithic) 아키텍처와 대조되며, 마이크로서비스는 작고 자율적인 단위로 개발, 배포, 확장이 가능하게끔 설계됩니다.
마이크로서비스 아키텍처 특징:
- 독립성 (Independence): 각 마이크로서비스는 독립적으로 개발, 배포, 운영될 수 있습니다. 따라서 하나의 서비스에 문제가 발생해도 다른 서비스에 영향을 미치지 않습니다.
- 분산 시스템 (Distributed System): 마이크로서비스는 분산 아키텍처를 채택하고, 각 서비스는 독립적으로 실행되며 서로 통신합니다. 이는 높은 확장성과 유연성을 제공합니다.
- 단일 책임 원칙 (Single Responsibility Principle): 각 마이크로서비스는 특정 비즈니스 기능이나 업무 영역에 집중하며, 그에 따른 단일 책임을 갖습니다.
- 자율성 (Autonomy): 각 마이크로서비스 팀은 자체적으로 개발, 배포, 스케일링, 모니터링 등의 결정을 내릴 수 있습니다.
- 다양한 기술 스택 (Polyglot): 서비스 간의 독립성으로 각각의 마이크로서비스는 다른 기술 스택과 언어를 사용할 수 있습니다.
- 서비스 디스커버리 (Service Discovery): 마이크로서비스는 서로를 자동으로 발견하고 통신할 수 있는 방법을 가지고 있어야 합니다.
- 탄력적 확장성 (Elasticity): 각 마이크로서비스는 개별적으로 확장 가능하며, 부하 분산이 용이합니다.
- API 게이트웨이 (API Gateway): 클라이언트와 통신을 위한 통합된 인터페이스를 제공하는 API 게이트웨이를 통해 마이크로서비스들은 외부와 소통합니다.
Database
데이터베이스는 mysql, mongodb, redis를 사용할 예정입니다.
mysql은 24.02.01 이찬우 회고를 참고하시면 됩니다.
mongodb의 경우는 업적이나, 칭호 시스템을 도입한다면 사용할 예정입니다.
redis는 간단한 유저 정보나, 친구목록등을 조회하기 위해 사용할 예정입니다.
아래는 mongodb와 redis의 차이입니다.
몽고디비 (MongoDB):
- 데이터 모델:
- 몽고디비는 문서 지향 데이터베이스로, BSON(Binary JSON) 형식의 도큐먼트를 사용합니다. 이는 유연하고 중첩된 구조를 갖는 데이터를 저장할 수 있습니다.
- 스키마가 유동적(dynamic)이므로, 필드를 동적으로 추가하거나 제거할 수 있습니다.
- 쿼리 언어:
- 몽고디비는 JSON 형태의 쿼리 언어를 사용하며, 복잡한 쿼리도 지원합니다.
- MapReduce와 같은 집계 프레임워크를 제공하여 데이터 처리 기능을 확장할 수 있습니다.
- 사용 사례:
- 대용량의 정형화되지 않은 데이터를 다루는 경우에 적합합니다.
- 스키마가 자주 변경되는 환경이나 개발 속도가 빠른 Agile 개발 방식에 적합합니다.
- 인덱싱:
- 몽고디비는 다양한 인덱스를 지원하여 쿼리 성능을 향상시킬 수 있습니다.
Redis:
- 데이터 모델:
- Redis는 인메모리 데이터 스토어로서, 주로 키-값 쌍을 저장합니다. 각 키 또는 값은 단순한 데이터 타입 또는 복잡한 데이터 구조 (예: 리스트, 세트, 해시)를 가질 수 있습니다.
- 쿼리 언어:
- Redis는 키를 사용한 단순한 연산에 중점을 둡니다. 데이터 캐싱, 메시지 브로커, 세션 스토어 등의 용도로 사용됩니다.
- SQL과 비슷한 쿼리 언어는 없으며, 기본적으로 키 기반의 명령어를 사용합니다.
- 사용 사례:
- 높은 처리 속도와 낮은 지연 시간이 필요한 실시간 데이터 처리에 적합합니다.
- 캐싱, 세션 관리, 메시지 브로커, 리더보드와 같은 간단한 구조의 데이터를 다루는데 사용됩니다.
- 인덱싱:
- Redis는 키를 기반으로 데이터를 저장하기 때문에, 키에 대한 인덱싱은 빠르게 이루어집니다.