PART 6 - 강의 1/3

Dedicated Server 아키텍처

헤드리스 서버 빌드와 대규모 멀티플레이어 서버 구조

01

서버 타입 비교

Dedicated vs Listen Server

비교표 ┌─────────────────┬────────────────────┬────────────────────┐ │ │ Dedicated Server │ Listen Server │ ├─────────────────┼────────────────────┼────────────────────┤ │ 호스트 │ 전용 서버 머신 │ 플레이어 중 1명 │ │ 그래픽 렌더링 │ 없음 (Headless) │ 있음 │ │ 플레이어 수 │ 64+ (게임에 따라) │ 보통 4-16명 │ │ 지연 시간 │ 균등한 핑 │ 호스트 유리 │ │ 비용 │ 서버 호스팅 필요 │ 무료 │ │ 호스트 이탈 │ 영향 없음 │ 세션 종료/마이그레이션│ │ 치트 방지 │ 강력 │ 호스트 치트 가능 │ └─────────────────┴────────────────────┴────────────────────┘
선택 가이드

경쟁 게임이나 대규모 멀티플레이어는 Dedicated Server, 캐주얼 코옵이나 소규모 세션은 Listen Server가 적합합니다.

02

Headless 서버 빌드

그래픽 없는 서버 전용 빌드

MyGame.Target.cs using UnrealBuildTool; public class MyGameServerTarget : TargetRules { public MyGameServerTarget(TargetInfo Target) : base(Target) { Type = TargetType.Server; DefaultBuildSettings = BuildSettingsVersion.V4; IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_3; // 서버 전용 설정 bUseLoggingInShipping = true; bCompileAgainstEngine = true; // 그래픽/오디오 제외 bBuildWithEditorOnlyData = false; ExtraModuleNames.Add("MyGame"); } }
빌드 명령 # 서버 빌드 RunUAT.bat BuildCookRun -project=MyGame.uproject -platform=Linux -serverconfig=Development -server -noclient -build -cook -stage -pak -archive # 서버 실행 ./MyGameServer -log -port=7777
03

서버 전용 코드 분기

WITH_SERVER_CODE 매크로 활용

C++ // 서버 전용 헤더 포함 #if WITH_SERVER_CODE #include "ServerOnlyFeature.h" #endif void AMyGameMode::InitGame(...) { Super::InitGame(...); #if WITH_SERVER_CODE // 서버에서만 실행되는 초기화 InitializeServerSystems(); ConnectToMatchmaker(); #endif } // 런타임 체크 (덜 효율적이지만 유연함) void AMyActor::DoSomething() { if (IsRunningDedicatedServer()) { // Dedicated Server에서만 실행 } if (HasAuthority()) { // 서버(Dedicated 또는 Listen)에서 실행 } }
빌드 최적화

WITH_SERVER_CODE는 컴파일 타임에 결정되어 불필요한 코드가 서버 빌드에서 제외됩니다. IsRunningDedicatedServer()는 런타임 체크로 두 빌드에 모두 포함됩니다.

04

서버 GameMode 설계

서버 전용 게임 로직

C++ UCLASS() class AMyGameMode : public AGameModeBase { GENERATED_BODY() public: AMyGameMode(); // 플레이어 접속 처리 virtual void PostLogin(APlayerController* NewPlayer) override; virtual void Logout(AController* Exiting) override; // 접속 승인 virtual void PreLogin( const FString& Options, const FString& Address, const FUniqueNetId& UniqueId, FString& ErrorMessage) override; protected: // 서버 설정 UPROPERTY(EditDefaultsOnly) int32 MaxPlayers = 64; UPROPERTY(EditDefaultsOnly) float MatchDuration = 600.f; // 10분 }; void AMyGameMode::PreLogin(..., FString& ErrorMessage) { Super::PreLogin(..., ErrorMessage); // 서버가 가득 찬 경우 if (GetNumPlayers() >= MaxPlayers) { ErrorMessage = TEXT("Server is full"); return; } // 밴 체크 등 추가 검증 if (IsPlayerBanned(UniqueId)) { ErrorMessage = TEXT("You are banned from this server"); } }
SUMMARY

핵심 요약

  • Dedicated Server - 그래픽 없는 전용 서버, 대규모 멀티플레이어에 적합
  • Server Target - MyGameServer.Target.cs로 별도 빌드 구성
  • WITH_SERVER_CODE - 컴파일 타임 서버 전용 코드 분기
  • GameMode - PreLogin/PostLogin으로 접속 관리
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: Dedicated Server 빌드

프로젝트의 Target.cs에서 ServerTargetRules를 설정하고 Dedicated Server 빌드를 생성하세요. -server -log 명령줄 옵션으로 실행하고, 별도 클라이언트로 접속 테스트를 수행하세요.

실습 2: 서버 전용 로직 분리

WITH_SERVER_CODE 매크로와 NM_DedicatedServer 체크를 사용하여 AI 로직, 스폰 관리자 등 서버 전용 코드를 분리하세요. 클라이언트 빌드에서 불필요한 코드가 컴파일되지 않는지 확인하세요.

심화 과제

Docker 컨테이너로 Dedicated Server를 패키징하고 AWS GameLift 또는 자체 오케스트레이션으로 배포하는 파이프라인을 구축하세요. 서버 헬스체크 엔드포인트와 그레이스풀 셧다운을 구현하세요.