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 또는 자체 오케스트레이션으로 배포하는 파이프라인을 구축하세요. 서버 헬스체크 엔드포인트와 그레이스풀 셧다운을 구현하세요.