Unreal C++ 프로젝트 구조
3강. Unreal C++ 프로젝트 구조
1. 이번 강의에서 해결할 문제
헤더를 추가했는데 찾지 못하거나 Enhanced Input 코드는 작성됐지만 링크 단계에서 실패합니다. 파일 위치와 모듈 의존성이 컴파일 흐름에 어떻게 연결되는지 확인합니다.
2. 학습 목표
3. 핵심 개념
TopDownSurvival은 하나의 게임 모듈로 시작합니다. TopDownSurvival.Build.cs는 이 모듈이 사용할 다른 모듈을 선언하고, TopDownSurvival.Target.cs와 TopDownSurvivalEditor.Target.cs는 게임 실행 파일과 에디터 실행 파일의 빌드 대상을 정의합니다.
용어 정리
| 용어 | 무엇인가 | 왜 필요한가 |
|---|---|---|
| Project | .uproject, 설정, Content, Source를 묶은 게임 작업 단위 | Editor가 어떤 모듈과 플러그인을 열지 알게 합니다. |
| Target | 어떤 실행 결과를 만들지 정의하는 빌드 대상 | 게임 실행 파일과 Editor 실행 파일은 포함하는 모듈과 빌드 환경이 다릅니다. |
| Module | 함께 컴파일·링크·로드되는 C++ 코드 단위 | 의존성과 빌드 경계를 관리합니다. 폴더 하나와 같은 뜻은 아닙니다. |
Build.cs | 해당 모듈의 빌드 규칙을 적는 C# 파일 | 사용할 엔진 모듈, include 경로와 빌드 옵션을 Unreal Build Tool에 알립니다. |
| include | 현재 C++ 파일에서 타입 선언을 읽게 하는 전처리 지시 | 헤더를 읽었다고 그 구현 모듈까지 자동으로 링크되는 것은 아닙니다. |
처음에는 “헤더 파일을 찾으면 빌드된다”고 생각하기 쉽지만 Unreal 빌드에는 여러 단계가 있습니다.
- **Unreal Build Tool(UBT)**이 Target과 각
Build.cs를 읽어 빌드 구성을 만듭니다. - **Unreal Header Tool(UHT)**이
UCLASS,UPROPERTY같은 Reflection 선언에 필요한 코드를 생성합니다. - C++ 컴파일러가 각 소스 파일을 컴파일합니다.
- 링커가 선언한 모듈의 기호를 연결합니다.
- Editor 또는 게임이 모듈을 로드합니다.
따라서 “헤더를 찾지 못함”, “unresolved external symbol”, “Missing Module”은 같은 오류가 아닙니다. 첫 번째는 include·파일 위치, 두 번째는 구현이나 링크 의존성, 세 번째는 빌드 결과·버전·로드 설정을 순서대로 확인합니다.
TopDownSurvival/
├─ TopDownSurvival.uproject
├─ Config/
├─ Content/
└─ Source/
├─ TopDownSurvival.Target.cs
├─ TopDownSurvivalEditor.Target.cs
└─ TopDownSurvival/
├─ TopDownSurvival.Build.cs
├─ TopDownSurvival.h
├─ TopDownSurvival.cpp
├─ Characters/
├─ Components/
├─ Data/
├─ Systems/
└─ UI/
4. 단계별 실습
파일 경로: Source/TopDownSurvival/TopDownSurvival.Build.cs
using UnrealBuildTool;
public class TopDownSurvival : ModuleRules
{
public TopDownSurvival(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine",
"InputCore",
"EnhancedInput",
"UMG",
"AIModule",
"NavigationSystem"
});
}
}
Build.cs 한 줄씩 이해하기
using UnrealBuildTool;은ModuleRules와ReadOnlyTargetRules타입을 사용하게 합니다.- 클래스 이름
TopDownSurvival은 모듈 이름과 일치해야 합니다. - 생성자는 UBT가 이 Target용 모듈 규칙을 계산할 때 호출합니다. 게임 런타임 C++ 생성자가 아닙니다.
UseExplicitOrSharedPCHs는 명시적인 include 구조와 공유 PCH 정책을 사용합니다.Core,CoreUObject,Engine은 기본 타입, UObject 시스템, Actor·World 같은 엔진 기능을 제공합니다.EnhancedInput,UMG,AIModule,NavigationSystem은 이후 강의에서 입력·UI·AI·길 찾기 타입을 사용할 수 있게 합니다.
PublicDependencyModuleNames와 PrivateDependencyModuleNames의 기준은 “많이 쓰는가”가 아닙니다. 내 모듈의 Public 헤더가 다른 모듈 타입을 노출하면 소비 모듈에도 의존성이 전파되어야 하므로 Public을 고려합니다. 구현 파일에서만 쓰는 타입은 가능한 한 Private에 두어 불필요한 재컴파일과 의존성 노출을 줄입니다. 이 입문 과정은 단일 모듈 구조를 먼저 익히기 위해 목록을 단순하게 시작합니다.
프로젝트 폴더를 직접 확인하기
PowerShell · 실행 위치: 프로젝트 루트
New-Item -ItemType Directory -Force .\Source\TopDownSurvival\Characters
New-Item -ItemType Directory -Force .\Source\TopDownSurvival\Components
New-Item -ItemType Directory -Force .\Source\TopDownSurvival\Data
New-Item -ItemType Directory -Force .\Source\TopDownSurvival\Systems
New-Item -ItemType Directory -Force .\Source\TopDownSurvival\UI
Get-ChildItem .\Source\TopDownSurvival -Directory
폴더를 만든 뒤 IDE 프로젝트 보기에 즉시 나타나지 않으면 Editor의 Tools 메뉴에서 프로젝트 파일을 새로 고치거나 uproject 컨텍스트 메뉴의 프로젝트 파일 생성 기능을 사용합니다. 메뉴 이름은 버전에 따라 다를 수 있습니다.
명령 실행 뒤 Characters, Components, Data, Systems, UI 다섯 폴더가 출력되어야 합니다. 폴더는 코드를 찾기 쉽게 분류할 뿐 새 모듈을 만들지 않습니다. 새 모듈이라면 별도의 Build.cs, 구현 파일, 프로젝트 또는 플러그인 Descriptor 등록이 필요합니다.
5. 코드가 동작하는 이유
Build.cs는 C++ include 문보다 앞선 의존성 경계입니다. 예를 들어 EnhancedInput 모듈을 선언하지 않으면 헤더를 찾더라도 링크나 모듈 로드 단계에서 실패할 수 있습니다. Public과 Private 구분은 내 공개 헤더가 해당 모듈 타입을 노출하는지에 따라 결정합니다. 처음에는 학습 편의를 위해 Public 목록에 두고, 구조가 안정되면 Private 의존성을 정리합니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
실습 목표
현재 프로젝트가 어떤 Target과 Module로 빌드되는지 파일에서 찾아보고, C++ 타입과 Build.cs 의존성을 연결해 설명합니다.
시작 전 상태
Editor와 IDE에서 TopDownSurvival.uproject, Source/TopDownSurvival.Target.cs, Source/TopDownSurvivalEditor.Target.cs, Source/TopDownSurvival/TopDownSurvival.Build.cs의 실제 위치를 확인합니다. 엔진 버전에 따라 생성된 코드가 조금 다를 수 있으므로 무작정 예제 내용으로 덮어쓰지 않습니다.
1단계: 가장 작은 확인
프로젝트 루트에서 위 PowerShell 명령으로 책임별 폴더를 만들고 출력 결과를 확인합니다. Characters에는 Character, Components에는 HealthComponent처럼 각 폴더에 들어갈 클래스 후보를 두 개씩 적습니다.
2단계: 의존성 하나 추적
프로젝트에서 UInputMappingContext 또는 UInputAction을 사용하는 헤더를 찾습니다. 해당 API 문서나 헤더 경로에서 소속 모듈이 EnhancedInput인지 확인하고, Build.cs 목록과 연결합니다. “include가 있으므로 충분하다”가 아니라 헤더 접근과 모듈 링크가 모두 필요하다고 설명할 수 있어야 합니다.
3단계: 실패를 안전하게 예측하고 확인
Git 또는 별도 복사본으로 Build.cs를 되돌릴 수 있는지 확인한 뒤, 학습용 변경에서만 EnhancedInput을 잠시 제거해 빌드 오류가 어느 단계에서 나타나는지 관찰합니다. 오류 문구는 엔진 버전과 기존 include 구조에 따라 컴파일 또는 링크 단계로 달라질 수 있습니다. 확인 직후 원래 의존성을 복원하고 다시 빌드합니다.
4단계: 스스로 확인
막혔을 때
| 증상 | 먼저 확인할 곳 | 해결 방향 |
|---|---|---|
| 헤더를 찾을 수 없음 | 파일 경로, include 철자, 소속 모듈 | API 문서의 Header와 Module 항목을 확인합니다. |
| unresolved external symbol | 함수 정의 누락, Build.cs 의존성 | 선언만 있고 구현이 없는지와 링크할 모듈을 확인합니다. |
| IDE에 새 폴더가 보이지 않음 | 실제 디스크에는 생성됐는지 | 프로젝트 파일을 새로 생성하거나 IDE를 새로 고칩니다. |
| Missing Module 또는 재빌드 안내 | 엔진 버전, 빌드 구성, 이전 바이너리 | 같은 엔진 버전으로 Editor Target을 빌드하고 첫 오류부터 확인합니다. |
8. 이해 점검 질문 3개
9. 핵심 요약
다음 강의 연결
다음 강의에서는 이 모듈의 Actors 폴더에 첫 C++ Actor를 만들고, UHT가 처리하는 클래스 매크로와 Actor 수명 주기를 실제 코드로 확인합니다.
Unreal C++ 프로젝트 구조 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.