PART 12 · 강의 1/8
프로젝트 구조 설계
대규모 오픈월드 RPG를 위한 모듈화된 프로젝트 아키텍처
01
프로젝트 디렉토리 구조
Epic 코딩 표준 기반 폴더 구성
OpenWorldRPG/ ├── Source/ │ ├── OpenWorldRPG/ # 메인 게임 모듈 │ │ ├── Public/ │ │ │ ├── Core/ # 핵심 게임 클래스 │ │ │ ├── Character/ # 캐릭터 시스템 │ │ │ ├── Combat/ # 전투 시스템 │ │ │ ├── Inventory/ # 인벤토리 │ │ │ ├── Quest/ # 퀘스트 │ │ │ └── UI/ # UI 클래스 │ │ └── Private/ │ ├── OpenWorldRPGAI/ # AI 모듈 │ ├── OpenWorldRPGNetwork/ # 네트워킹 모듈 │ └── OpenWorldRPGEditor/ # 에디터 전용 모듈 ├── Content/ │ ├── Characters/ │ ├── Environments/ │ ├── Effects/ │ ├── UI/ │ └── Maps/ ├── Config/ ├── Plugins/ │ └── GameFeatures/ └── OpenWorldRPG.uproject
폴더 구조 원칙
- Public/: 외부 모듈에 노출할 헤더 파일
- Private/: 내부 전용 헤더 및 cpp 파일
- 모듈별로 Build.cs 파일에서 의존성 관리
- API 매크로는 필요한 클래스에만 추가
02
모듈 설계
기능별 모듈 분리
OpenWorldRPG (Runtime)
핵심 게임플레이 로직, 캐릭터, 전투, 인벤토리, UI
OpenWorldRPGAI (Runtime)
NPC AI, 적 AI, Behavior Tree, EQS
OpenWorldRPGNetwork (Runtime)
네트워킹, 복제, 세션 관리, Co-op 시스템
OpenWorldRPGEditor (Editor)
에디터 확장, 커스텀 도구, 데이터 에디터
OpenWorldRPG.Build.cs
using UnrealBuildTool;
public class OpenWorldRPG : ModuleRules
{
public OpenWorldRPG(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
// Public 의존성 (이 모듈을 사용하는 다른 모듈도 접근)
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine",
"InputCore",
"EnhancedInput",
"GameplayAbilities",
"GameplayTags",
"GameplayTasks",
"UMG",
"Slate",
"SlateCore"
});
// Private 의존성 (이 모듈 내부에서만 사용)
PrivateDependencyModuleNames.AddRange(new string[]
{
"Niagara",
"AIModule",
"NavigationSystem",
"OnlineSubsystem",
"OnlineSubsystemUtils"
});
// AI 모듈 의존성
PrivateDependencyModuleNames.Add("OpenWorldRPGAI");
// 네트워킹 모듈 의존성
PrivateDependencyModuleNames.Add("OpenWorldRPGNetwork");
}
}
03
핵심 클래스 설계
게임 프레임워크 클래스
C++
// OpenWorldRPGGameInstance.h
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "OpenWorldRPGGameInstance.generated.h"
/**
* 게임 인스턴스 - 게임 세션 전체에서 유지되는 데이터
*/
UCLASS()
class OPENWORLDRPG_API UOpenWorldRPGGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
virtual void Init() override;
virtual void Shutdown() override;
// 현재 플레이어 세이브 데이터
UPROPERTY(BlueprintReadWrite, Category = "SaveGame")
TObjectPtr<UPlayerSaveData> CurrentSaveData;
// 글로벌 게임 설정
UPROPERTY(BlueprintReadOnly, Category = "Settings")
FGameSettings GameSettings;
// 세이브/로드
UFUNCTION(BlueprintCallable, Category = "SaveGame")
bool SaveGame(int32 SlotIndex);
UFUNCTION(BlueprintCallable, Category = "SaveGame")
bool LoadGame(int32 SlotIndex);
};
C++
// OpenWorldRPGGameMode.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "OpenWorldRPGGameMode.generated.h"
/**
* 게임 모드 - 게임 규칙 및 플레이어 관리
*/
UCLASS()
class OPENWORLDRPG_API AOpenWorldRPGGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
AOpenWorldRPGGameMode();
virtual void InitGame(
const FString& MapName,
const FString& Options,
FString& ErrorMessage) override;
virtual void PostLogin(APlayerController* NewPlayer) override;
virtual void Logout(AController* Exiting) override;
// 플레이어 리스폰
UFUNCTION(BlueprintCallable, Category = "Respawn")
void RespawnPlayer(APlayerController* Player);
protected:
// Seamless Travel 지원 (Co-op)
virtual void GetSeamlessTravelActorList(
bool bToTransition,
TArray<AActor*>& ActorList) override;
};
C++
// OpenWorldRPGPlayerController.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "OpenWorldRPGPlayerController.generated.h"
/**
* 플레이어 컨트롤러 - 입력 처리 및 UI 관리
*/
UCLASS()
class OPENWORLDRPG_API AOpenWorldRPGPlayerController : public APlayerController
{
GENERATED_BODY()
public:
AOpenWorldRPGPlayerController();
virtual void BeginPlay() override;
virtual void SetupInputComponent() override;
// UI 표시/숨김
UFUNCTION(BlueprintCallable, Category = "UI")
void ShowInventory();
UFUNCTION(BlueprintCallable, Category = "UI")
void ShowQuestLog();
UFUNCTION(BlueprintCallable, Category = "UI")
void ShowCharacterMenu();
protected:
// Enhanced Input
UPROPERTY(EditDefaultsOnly, Category = "Input")
TObjectPtr<UInputMappingContext> DefaultMappingContext;
// HUD 위젯
UPROPERTY()
TObjectPtr<UMainHUDWidget> MainHUD;
};
04
Subsystem 아키텍처
매니저 패턴 대신 Subsystem 활용
C++
// QuestSubsystem.h - 퀘스트 관리 Subsystem
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "QuestSubsystem.generated.h"
UCLASS()
class OPENWORLDRPG_API UQuestSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
// 퀘스트 수락
UFUNCTION(BlueprintCallable, Category = "Quest")
bool AcceptQuest(FName QuestID);
// 퀘스트 완료
UFUNCTION(BlueprintCallable, Category = "Quest")
bool CompleteQuest(FName QuestID);
// 진행 상황 업데이트
UFUNCTION(BlueprintCallable, Category = "Quest")
void UpdateQuestProgress(FName QuestID, FName ObjectiveID, int32 Progress);
// 이벤트
UPROPERTY(BlueprintAssignable, Category = "Quest")
FOnQuestUpdated OnQuestUpdated;
UPROPERTY(BlueprintAssignable, Category = "Quest")
FOnQuestCompleted OnQuestCompleted;
private:
UPROPERTY()
TMap<FName, FQuestState> ActiveQuests;
};
// WorldStateSubsystem.h - 월드 상태 관리
UCLASS()
class OPENWORLDRPG_API UWorldStateSubsystem : public UWorldSubsystem
{
GENERATED_BODY()
public:
virtual void OnWorldBeginPlay(UWorld& InWorld) override;
// 날씨 시스템
UFUNCTION(BlueprintCallable, Category = "Weather")
void SetWeather(EWeatherType NewWeather, float TransitionTime);
// 시간대
UFUNCTION(BlueprintCallable, Category = "Time")
void SetTimeOfDay(float Hour);
// 월드 이벤트
UFUNCTION(BlueprintCallable, Category = "Events")
void TriggerWorldEvent(FName EventID);
private:
EWeatherType CurrentWeather;
float CurrentTimeOfDay;
};
SUMMARY
핵심 요약
- 모듈 분리: 게임플레이, AI, 네트워킹, 에디터를 별도 모듈로
- Public/Private 폴더 구조로 API 경계 명확화
- GameInstance: 세션 전체 데이터 (세이브, 설정)
- GameMode: 게임 규칙, 플레이어 관리
- Subsystem: 싱글톤 대신 라이프사이클 관리되는 매니저
- Build.cs에서 모듈 의존성 명확히 정의
PRACTICE
도전 과제
배운 내용을 직접 실습해보세요
실습 1: RPG 프로젝트 기본 구조 생성
C++ 기반 UE5 프로젝트를 생성하고, RPGCore, RPGCombat, RPGUI, RPGWorld 모듈로 분리하세요. 각 모듈의 Build.cs를 작성하고, 모듈 간 의존성을 최소화하여 빌드 시간을 단축하세요.
실습 2: Git 워크플로우 설정
.gitignore에 UE5 관련 파일(Intermediate, Saved, DerivedDataCache)을 추가하고, Git LFS로 대용량 에셋을 관리하세요. Feature Branch 워크플로우와 PR 리뷰 프로세스를 수립하세요.
심화 과제: 기술 설계 문서 작성
RPG 프로젝트의 핵심 시스템(전투, 인벤토리, 퀘스트, 네트워킹, 월드 스트리밍)의 기술 설계 문서를 작성하세요. 클래스 다이어그램, 시퀀스 다이어그램, 데이터 플로우를 포함하세요.