캐주얼 혹은 모바일 게임을 위한 비동기 웹기반 게임 아키텍처 알아보기
수많은 게임사들이 다양한 장르 및 규모의 온라인 게임들을 AWS에서 운영하고 있습니다. 게임 장르 및 규모에 따라 요구사항이 천차만별이다 보니, 게임별로 기반으로 하는 기술 스택도, 아키텍처도 그만큼 다양합니다.
이 글에서는 그중 게임 서버 및 클라이언트 간의 실시간 상호작용이 필요하지 않은 캐주얼 게임이나 모바일 게임, 브라우저 기반 게임에서 보통 사용되는 비동기 웹 기반 게임 서버 아키텍처 패턴에 대해 알아보도록 하겠습니다.
웹 게임이란?
보통 웹 게임이라고 하면, 초창기에는 웹브라우저상에서 서비스되는 게임을 의미했습니다. 초기에는 웹 기술이 제약으로 Flash나 Java Applet과 같은 기술이 웹 게임에 널리 쓰이기도 했었지만, HTML5, canvas, WebGL, WebSocket 및 JavaScript의 발전으로 순수한 웹 기술만으로도 인터랙티브한 게임을 제작하는 것이 가능해졌습니다. 이러한 웹브라우저 기반 게임들은 사실 서비스하는 컨텐츠가 게임일 뿐, 기반 기술은 전통적인 웹 애플리케이션과 다르지 않음으로 전통적인 3계층 웹 애플리케이션 아키텍처를 차용할 수 있습니다. 또한, 반드시 웹 브라우저 기반 게임들이 아니더라도, 요즘 널리 사용되고 있는 http(s) 기반 RESTful API를 사용한다면 해당 부분의 아키텍처는 3계층 웹 애플리케이션 아키텍처를 사용할 수 있습니다.
3계층 웹 애플리케이션 아키텍처
3계층 웹 애플리케이션 아키텍처는 범용적으로 많이 사용되는 아키텍처이다 보니, 3계층 웹 아키텍처를 지원하는 다양한 오픈소스 및 상용 웹 프레임워크들이 나와 있습니다. 이러한 웹 프레임워크들을 활용하면, 개발 및 운영, 유지보수의 부담을 상당 부분 덜 수 있습니다. 또, 웹 브라우저 기반 게임이나 요즘 많이 사용하는 React Native 기반의 게임이라면 Node.js, Express와 같은 웹 프레임워크를 사용하면 클라이언트와 서버의 로직을 같은 언어(JavaScript/TypeScript)로 구현할 수 있어 개발 및 유지보수 편이성을 향상시킬 수 있습니다.
기본적으로 stateless한 http(s) 기반으로 클라이언트와 서버가 통신하므로 스케일 인/아웃이 용이하고 오토스케일링과 같은 클라우드의 강점을 충분히 활용할 수 있는 점도 장점입니다. 대부분의 웹 프레임워크들은 장애 조치 및 스케일 인/아웃을 고려하여 구현되어 있고, Redis나 Memcached와 같은 독립적인 캐시를 구성하여 세션 정보를 유지하는 방법도 널리 사용되고 있으므로, 이를 활용하면 탄력적인 백엔드를 상대적으로 쉽게 구축할 수 있습니다.
마지막으로, 위 아키텍처는 인스턴스 기반으로 설명되어 있으나, 게임 서버 로직들을 MSA(Microservice Architecture)로 구현할 수 있다면, 컨테이너 기반이나 서버리스 기반으로 마이그레이션하여 운영 효율성을 개선할 수 있습니다.
3계층 웹 애플리케이션 아키텍처는 표현 계층, 애플리케이션 계층, 데이터 계층의 3계층으로 나누어집니다.
- 표현 계층: 실제 웹브라우저에서 로딩할 HTML 파일들을 서비스하는 NGINX, Apache와 같은 프론트엔드 웹 서버들로 구성됩니다.
- 애플리케이션 계층: 애플리케이션 서버들로 구성되어 비즈니스 로직의 처리를 담당. 유명 웹 프레임워크들은 이 애플리케이션 계층의 관리 및 애플리케이션 개발, 배포를 손쉽게 하는 기능들을 제공합니다. ( 예) Python: Flask, Django, Java : Java EE, Spring, JavaScript/TypeScript: Node.js, Express … )
- 데이터 계층: 데이터들을 저장하고 읽을 수 있도록 서비스입니다. 가장 높은 수준의 보안이 요구되며, RDBMS, NoSQL, 인-메모리 DB(Redis, Memcached) 등으로 데이터 계층을 구성합니다.
계층별 고려사항
표현 계층
먼저 Amazon CloudFront(CDN)을 통한 라스트 마일 최적화를 고려해야 합니다. 전 세계 엣지 로케이션에 http(s) 요청들에 대한 응답을 캐싱하여 웹 응답을 최적화합니다. 게임에서는 S3를 오리진으로 하고 앞에 CloudFront를 두어, 클라이언트 다운로드 및 패치로 많이 활용합니다. 동적 콘텐츠의 경우에도 CloudFront의 캐시 정책을 짧게 가져가거나 아예 비활성화하더라도 엣지 로케이션과 리전 간 AWS 백본 네트워크를 통해 서비스하게 되므로 경로 최적화 효과를 볼 수 있습니다. 특히 요즘 웹게임에서 영속적인 세션 통신을 위하여 많이 사용되고 있는 WebSocket도 지원하고 있기 때문에 웹 백엔드를 한 리전에 두고 글로벌 서비스를 염두에 두고 계신다면 CloudFront는 필수 요소 중 하나가 됩니다.
다음으로 Application Load Balancer의 활용입니다. 기존 3계층 웹 애플리케이션 아키텍처에서 프론트엔드 웹 서버가 하던 http(s) 요청들을 백엔드 API 서버들에 라우팅하는 역할을 Application Load Balancer가 대체할 수 있습니다. 경로별 L7 라우팅으로 EC2 인스턴스, AWS Lambda, Amazon ECS/Amazon EKS/AWS Fargate를 지원하고 있으며, 트래픽에 따라 Application Load Balancer 자체가 스케일 인/아웃되므로 표현 계층 구성을 단순화할 수 있습니다. Application Load Balancer의 스케일링도 시간이 걸리기 때문에 급격한 트래픽의 증가가 예상될 경우, 프리워밍을 신청해두시는 것이 좋습니다. Application Load Balancer 역시 CloudFront 와 마찬가지로 WebSocket 기능을 지원하고 있습니다.
마지막으로, Amazon API Gateway의 활용입니다. API Gateway는 지원 대상으로 Lambda, AWS 서비스 API 들 외에도 http(s) 백엔드를 지원하므로 API Gateway 뒤에 EC2 웹 API 서버를 두실 수도 있습니다. 기존에 지원하던 RESTful API 외에도 단순화된 HTTP API 및 WebSocket API를 지원하여 메서드 정의 및 백엔드에 요청을 라우팅하고 사전 유효성 검사를 수행할 수 있습니다. REST API용 API Gateway는 http(s) 요청을 통한 접근 뿐 아니라, 지원되는 언어별로 API들에 대한 SDK를 생성하여 이를 통하여 API접근하도록 구성이 가능하므로, 개발 편의성을 높일 수 있습니다. API Gateway에 대한 접근지점에 따라 Private / Public, Edge 최적화 / Regional API 구성을 할 수 있습니다.
애플리케이션 계층
애플리케이션 계층은 아키텍처 패턴에 따라 EC2 기반으로 구성을 하거나, 요즘 트렌드인 컨테이너 기반 또는 서버리스로 구성할 수 있습니다. EC2 기반 구성의 경우 Amazon EC2, Amazon Lightsail, Amazon Elastic Beanstalk 등의 서비스를 이용하여 구성하게 되고, 컨테이너 기반 구성일 경우 Amazon ECS, Amazon EKS, AWS Fargate 등의 서비스를 이용하게 됩니다. 마지막으로 서버리스 구성일 경우, AWS Lambda를 활용하게 됩니다.
애플리케이션 계층은 트래픽에 따른 Auto Scaling 구성을 하여 트래픽의 증감에 따라 확장/축소가 가능하도록 구성할 수 있습니다. Amazon CloudWatch를 통하여 주요 지표 기반으로 Auto Scaling을 구성하거나, 커스텀 지표를 게시하고 이를 기반으로 확장/축소되도록 구성하실 수 있습니다. Lambda의 경우 Auto Scaling 구성 없이도 자동 확장/축소가 가능하지만, 동시성 제한이 있으므로, 높은 트래픽이 예상될 경우 미리 제한 해제를 신청해두셔야 합니다.
데이터 계층
데이터 계층을 구성할 때는 EC2에 선호하는 데이터베이스를 직접 설치하여 운영하는 Self-hosting 방식과 Amazon Relational Database Service(Amazon RDS)/Amazon DynamoDB/Amazon ElastiCache/Amazon MemoryDB for Redis와 같은 관리형 서비스를 활용하는 방식이 있습니다.
Self-hosting의 경우, EC2 위에 직접 데이터베이스 구성, HA 구성, 백업 구성, 읽기 복제본 구성 등을 직접 구성하고 운영하는 방식입니다. 보통 관리형 서비스에서 지원하지 않는 기능이나 데이터베이스 버전을 활용하여야 할 때 선택합니다. 직접 구성하기 때문에 구성의 자유도가 높지만 운영 부담이 그만큼 증가하는 문제가 있습니다.
관리형 RDBMS 서비스를 제공하는 Amazon RDS를 활용하면 가장 널리 활용되는 유명 데이터베이스 엔진들 대부분( MySQL, MariaDB, PostgreSQL, Oracle, Microsoft SQL Server, Aurora(MySQL/PostgreSQL) )에 대해 클릭 몇 번만으로 클러스터를 준비하고 백업 및 복구, 읽기 복제본 추가, 자동 장애 조치 구성을 손쉽게 활성화/비활성화하실 수 있습니다.
DynamoDB는 NoSQL 데이터베이스를 서버리스 방식의 완전 관리형 서비스로 제공합니다. 트래픽 및 저장용량에 따라 자동으로 확장되며, 매우 빠른 응답속도를 자랑합니다. DynamoDB를 기반으로하는 다중 리전, 다중 활성 데이터베이스인 DynamoDB 글로벌 테이블을 활용하면 복수 리전 간 DynamoDB 테이블을 빠르게 동기화할 수 있습니다.
ElastiCache는 관리형 인-메모리 DB 서비스로 가장 널리 쓰이는 메모리 DB인 Redis, Memcached 엔진에 대한 관리형 서비스 제공합니다. 클릭 몇 번만으로 클러스터 구성, 백업 및 복원, 읽기 복제본 추가 등의 작업을 수행할 수 있어 관리 부담을 줄일 수 있습니다. 최근 소개된 MemoryDB for Redis는 Redis 호환 메모리 DB에 내구성을 더하여 관리형 서비스로 제공하고 있습니다. MemoryDB for Redis를 활용하면 Redis를 단순한 캐시 계층으로서가 아닌 영속적 DB로 활용을 기대할 수 있습니다.
마치며
이번 포스팅에서는 다양한 게임 장르 및 규모별 아키텍처 패턴 중 웹 기반 게임을 위한 3계층 웹 애플리케이션 아키텍처 패턴에 대해 알아보았습니다. 이 아키텍처는 웹 게임 뿐만 아니라, RESTful API 서버 백엔드나 게임 서비스를 위한 플랫폼 서비스를 구성할 때에도 광범위하게 사용되는 아키텍처 패턴이므로, AWS에서 게임을 구성하실 때 유용하게 활용하셨으면 좋겠습니다.
– 김병수, AWS 게임 솔루션즈 아키텍트