TIL 2026-05-07
2026-05-07 UE5 모듈 폴더 구조 정식 분리(Public/Private) + 팀원 GitHub PR 워크플로우 전수
목차
- 2026-05-07 UE5 모듈 폴더 구조 정식 분리(Public/Private) + 팀원 GitHub PR 워크플로우 전수
오늘 한 일 요약
- NBC_Ch3 모듈 폴더 구조 정식 분리 — 카테고리별 평면(
AI/,Combat/,Core/,Player/,System/,UI/)에서 표준 UE5 레이아웃(Public/{Category}/*.h+Private/{Category}/*.cpp)으로 이전. 27개 파일git mv이동(헤더 13 / cpp 12 / 모듈.h+모듈.cpp / OWNER.txt 6) - include 경로 모던 UE5 스타일로 일괄 변경 —
#include "Foo.h"→#include "AI/Foo.h"같은 카테고리 prefix 풀 경로로 19개 파일 수정. UBT가 자동 추가하는 include path는 모듈의Public/루트뿐이라 카테고리 서브폴더는 prefix 필수 - 참조 모델 검증 —
D:/Unreal/VoidUnreal/Source/VoidUnreal/의 패턴 확인.bLegacyPublicIncludePaths미설정(=false) 모드에서 모든 include는 Public 루트 기준 풀 경로. 모듈.h는 Public 루트, 모듈.cpp는 모듈 루트라는 미묘한 포인트도 그대로 따름 - 빌드 성공 후 develop 브랜치에 직접 push — 커밋
b2e36f5포함2d6cba3..b2e36f5범위. PR 흐름이 아닌 develop 직접 푸시는 폴더 구조 같은 인프라 변경 한정 - 팀원에게 GitHub PR 워크플로우 전수 — 5시 회의 또는 그 이후. 팀원들이 GitHub 사용·브랜치 컨벤션 익숙하지 않아 직접 설명. 브랜치 전략 / 작업 흐름 8단계 / Conventional Commits / PR 본문 양식 / 자주 하는 실수 4가지 / 우리 팀 머지 PR 3건 사례
- 어제(05/06)의 모듈 구조 결론 두 단계 진화 확인 — 05/06: “중첩 Combat/Public + Combat/Private은 실패” → flat 구조로 회복. 05/07: “그렇다고 flat이 표준은 아니다” → 모듈 루트의 단일 Public/Private + 카테고리 서브폴더가 정식 패턴. 두 결론 모두 유효, 단 후자가 협업·확장성 측면에서 우위
- TIL 작성 — 본 파일 — 하루 늦게 정리(05/08 기준 어제분 회고)
UE5 모듈 폴더 구조 — 평면 카테고리에서 Public/Private 표준으로 이전
어제(2026-05-06) 결론은 “중첩 Combat/Public + Combat/Private은 UBT 자동 인식이 안 되니 flat 구조로 회복”이었다. 그 결론 자체는 맞지만 한 단계 더 가야 할 곳이 있었다 — 모듈 루트 단일 Public/Private + 카테고리 서브폴더 구조. 어제는 회피책, 오늘은 정식 표준으로 이전한 셈.
어제(05/06)의 시행착오 정리 — “중첩 Public/Private은 동작 안 한다”는 결론에서 출발
먼저 두 결론의 관계를 정리.
1
2
3
4
5
6
7
8
9
05/06 (어제)
✗ 시도 1: Module/Combat/Public + Module/Combat/Private (중첩)
→ 빌드 실패 (UBT는 모듈 루트의 Public/Private만 자동 인식)
✓ 회복: Module/Combat/{*.h, *.cpp} (flat)
→ 빌드 성공. 단 Public/Private 분리 없음
05/07 (오늘)
✓ 정식: Module/Public/Combat/*.h + Module/Private/Combat/*.cpp
→ 빌드 성공 + Public/Private 분리 + 카테고리 보존
세 구조의 차이가 한눈에 보인다. 어제 회복한 flat은 빌드는 되지만 API 경계가 흐려진다 — 외부에서 가져갈 헤더와 내부 구현을 폴더 단위로 구분 못 함. 오늘 패턴은 두 가지를 동시에 만족.
참조 모델 — VoidUnreal 패턴의 미묘한 포인트
기준 자료는 D:/Unreal/VoidUnreal/Source/VoidUnreal/ — 내가 이전에 동작 검증한 프로젝트. 핵심 패턴 4가지.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
VoidUnreal/Source/VoidUnreal/
├── VoidUnreal.Build.cs ← 모듈 빌드 설정
├── VoidUnreal.cpp ← 모듈.cpp는 모듈 루트
├── Public/
│ ├── VoidUnreal.h ← 모듈.h는 Public 루트
│ ├── AI/
│ │ ├── VOIDAIController.h
│ │ └── ...
│ ├── Combat/
│ │ ├── HealthComponent.h
│ │ ├── WeaponComponent.h
│ │ └── ...
│ └── Player/
│ └── VOIDPlayerController.h
└── Private/
├── AI/
│ └── VOIDAIController.cpp
├── Combat/
│ └── HealthComponent.cpp
└── Player/
└── VOIDPlayerController.cpp
미묘한 포인트:
- 모듈.h는 Public 루트에, 모듈.cpp는 모듈 루트에 있다 (Private/ 안이 아님). 이건 UE5 템플릿이 만들어주는 그대로의 위치
- 카테고리(AI/Combat/Player)는 Public·Private 양쪽에 대칭으로 같은 이름이 존재
Public/,Private/외 다른 모든 것(Build.cs, 모듈 cpp 등)은 모듈 루트 직속
이 4가지를 그대로 따라야 UBT 자동 인식이 정상 동작.
이행 결과 — 27개 파일 이동, 19개 파일 include 경로 수정
NBC_Ch3 모듈을 위 패턴으로 정렬.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
이전 (카테고리별 평면)
NBC_Ch3/Source/NBC_Ch3_TeamProject/
├── AI/ ← .h와 .cpp 한 폴더에 섞임
├── Combat/
├── Core/
├── Player/
├── System/
├── UI/
└── (모듈 파일들 평면 배치)
이후 (Public/Private + 카테고리 서브폴더)
NBC_Ch3/Source/NBC_Ch3_TeamProject/
├── NBC_Ch3_TeamProject.Build.cs
├── NBC_Ch3_TeamProject.cpp ← 모듈 cpp는 루트
├── Public/
│ ├── NBC_Ch3_TeamProject.h ← 모듈 h는 Public 루트
│ ├── AI/*.h
│ ├── Combat/*.h
│ ├── Core/*.h
│ ├── Player/*.h
│ ├── System/*.h
│ └── UI/*.h
└── Private/
├── AI/*.cpp
├── Combat/*.cpp
├── Core/*.cpp
├── Player/*.cpp
├── System/*.cpp
└── UI/*.cpp
이동 통계:
| 분류 | 개수 | 비고 |
|---|---|---|
| 헤더(.h) | 13 | Public/{Category}/ 로 이동 |
| 구현(.cpp) | 12 | Private/{Category}/ 로 이동 |
| 모듈 파일 | 2 | 모듈.h → Public 루트 / 모듈.cpp → 모듈 루트 |
| OWNER.txt | 6 | Public/{Category}/ 로 이동(아래 별도 절) |
| 합계 | 27 | 모두 git mv 사용 — 히스토리 보존 |
| include 경로 수정 | 19개 파일 | #include "Foo.h" → #include "Category/Foo.h" |
git mv 를 쓴 이유는 단순 mv 후 git add 하면 Git이 100% 유사도로 자동 추적해 주긴 하지만, 명시적 rename이 PR diff에서 더 명확하기 때문. git log --follow 결과도 더 안정적.
UBT가 자동으로 추가하는 include path
오늘 정리한 가장 중요한 한 줄.
UnrealBuildTool은 모듈의
Public/루트만 자동으로 include path에 추가한다.Public/AI/같은 서브폴더는 추가하지 않는다.
이게 어제·오늘 구조 결정의 핵심 원리.
1
2
3
4
5
6
7
8
9
10
모듈 = NBC_Ch3_TeamProject
UBT가 자동 추가하는 PublicIncludePaths:
✓ NBC_Ch3_TeamProject/Public/ ← 자동
✗ NBC_Ch3_TeamProject/Public/AI/ ← 자동 X
✗ NBC_Ch3_TeamProject/Public/Combat/ ← 자동 X
UBT가 자동 추가하는 PrivateIncludePaths:
✓ NBC_Ch3_TeamProject/Private/ ← 자동
✗ NBC_Ch3_TeamProject/Private/AI/ ← 자동 X
따라서 같은 모듈 안에서 Combat/HealthComponent.h 를 가져오려면 반드시 #include "Combat/HealthComponent.h" 처럼 카테고리 prefix 풀 경로를 써야 한다. #include "HealthComponent.h" 만 쓰면 컴파일러가 못 찾음.
같은 모듈 내부 헤더 참조도 풀 경로 — 모던 UE5 스타일
이게 19개 파일을 수정한 이유. 이전 평면 구조에서는 모든 .h가 같은 모듈 루트 직속 카테고리 폴더 안에 있어서 #include "Foo.h" 만으로 충분했는데(UBT가 모듈 루트 하위 모든 폴더를 스캔해 주는 레거시 모드), 이제는 Public/Foo.h 또는 Public/Category/Foo.h 형태라 카테고리 prefix 가 필수.
1
2
3
4
5
6
7
8
9
// Before (평면 구조)
#include "HealthComponent.h"
#include "ZombieAIController.h"
#include "PlayerController.h"
// After (Public/Category 구조)
#include "Combat/HealthComponent.h"
#include "AI/ZombieAIController.h"
#include "Player/PlayerController.h"
수정 패턴은 단순 — 헤더가 어느 카테고리에 속하는지 보고 prefix 추가. 자동화 가능한 작업이지만 19개 파일 정도는 직접 확인하면서 했다(외부 모듈 헤더와 내부 헤더 구분 위해).
bLegacyPublicIncludePaths — 끄는 게 표준
UE5에는 빌드 옵션 하나가 있다 — bLegacyPublicIncludePaths. 이걸 true 로 두면 UBT가 Public/ 하위 모든 서브폴더도 자동으로 include path에 추가해 준다. 그러면 #include "HealthComponent.h" 같은 짧은 경로도 동작.
1
2
3
4
5
6
7
8
9
10
11
12
// Build.cs
public class NBC_Ch3_TeamProject : ModuleRules
{
public NBC_Ch3_TeamProject(ReadOnlyTargetRules Target) : base(Target)
{
// (1) Legacy 모드 — true 시 Public 하위 서브폴더도 자동 인식
bLegacyPublicIncludePaths = true;
// (2) 모던 모드 — false (또는 미설정 = 기본값 false)
// bLegacyPublicIncludePaths = false;
}
}
VoidUnreal 검증 결과 — 미설정 = false (모던 모드) 가 표준. 이유:
- legacy 모드는 UBT 가 모든 서브폴더를 스캔해 include path에 등록 → 빌드 시간 증가
- 짧은 경로는 모듈 간 헤더 충돌 가능성 ↑ (예: 두 모듈에
Foo.h가 있으면 어느 게 잡힐지 모호) - 풀 경로(
Combat/Foo.h)가 의도가 명확
NBC_Ch3 도 미설정으로 두고 모든 include를 풀 경로로 통일.
다른 모듈에서 가져갈 때 — Build.cs 의존성 + 동일 풀 경로
같은 모듈 내부 참조 규칙은 위와 같고, 다른 모듈에서 우리 헤더를 가져갈 때도 정확히 같은 형식.
1
2
3
4
5
// 가져가는 쪽 모듈의 Build.cs
PublicDependencyModuleNames.AddRange(new string[] {
"Core", "CoreUObject", "Engine", "InputCore",
"NBC_Ch3_TeamProject" // ← 우리 모듈을 의존성으로 추가
});
1
2
// 가져가는 쪽 .cpp
#include "Combat/HealthComponent.h" // ← 우리 모듈의 풀 경로 그대로
같은 풀 경로가 모듈 내부·외부 양쪽에서 통한다 — 이게 모던 UE5의 깔끔한 설계. legacy 모드면 모듈 외부에서는 풀 경로가 강제이고 모듈 내부에서는 짧은 경로가 동작해 일관성이 깨졌다.
OWNER.txt 같은 비코드 파일도 카테고리 따라 이동
발견한 디테일 — 각 카테고리 폴더에 OWNER.txt (담당자 표시) 가 있었다. 코드 파일은 아니지만 카테고리에 종속되는 메타데이터.
1
2
이전: NBC_Ch3_TeamProject/Combat/OWNER.txt
이후: NBC_Ch3_TeamProject/Public/Combat/OWNER.txt
선택지 두 가지 중 Public 쪽으로 결정:
- (A) Public/Category/ 에 두기 — 외부에서 “이 카테고리 소유자가 누구야”를 볼 때 헤더와 함께 보이는 게 자연스러움. 선택
- (B) Private/Category/ 에 두기 — 구현 디렉터리에 같이. 외부에서 안 보이게
OWNER.txt는 코드가 아니라 카테고리 자체의 메타 라 6개 모두 Public 쪽 카테고리 폴더로 이동. 모듈 사용자가 헤더 보러 들어왔을 때 같이 눈에 띈다.
이 결정에서 일반화한 룰: 비코드 파일이라도 카테고리에 종속되는 메타데이터는 카테고리 폴더 안에 함께 두고, Public/Private 분리 시에도 카테고리를 단위로 따라간다.
팀원에게 GitHub PR 워크플로우 전수
5시 회의 또는 그 직후. 팀원들 일부가 GitHub 사용·브랜치 컨벤션이 익숙하지 않아 본인이 직접 알려준 내용. 어제 스크럼의 “팀원 가ㅣㅅ허브 사용 및 브랜치 컨벤션” 메모가 이 작업.
브랜치 전략 — main 보호 / develop 통합 / feat/* 작업
가장 단순한 GitHub Flow + Git Flow 혼합 패턴.
1
2
3
4
5
6
7
main (보호) ← 발표·릴리즈 시점만 develop → main 머지
│
└─ develop (통합) ← 모든 feat/* 가 PR로 머지되는 곳
│
├─ feat/combat-hit-damage-system (작업 브랜치)
├─ feat/Player (작업 브랜치)
└─ feat/ZombieCharacter_ZombieAIController
세 줄로 요약:
- main — 보호 규칙. 직접 push 금지, develop 에서 PR 거쳐야만 머지. 실수 차단용
- develop — 통합 브랜치. 평소 빌드·플레이가 가능한 상태를 유지
- feat/* — 개인 작업 브랜치. 한 작업 = 한 브랜치 = 한 PR
브랜치 명 컨벤션은 Conventional Commits 와 결합:
feat/<scope>-<description>— 새 기능fix/<scope>-<description>— 버그 수정refactor/<scope>-<description>— 리팩터링chore/<description>— 빌드/설정/문서
작업 흐름 8단계
매 작업마다 반복하는 사이클.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1. develop 최신화
git pull origin develop
2. 작업 브랜치 생성
git checkout -b feat/<작업명>
3. 작업 + 커밋 (Conventional Commits 메시지)
git add <files>
git commit -m "feat(combat): add hit detection system"
4. 원격 push (-u 로 추적 설정)
git push -u origin feat/<작업명>
5. GitHub 웹에서 PR 생성
base: develop / compare: feat/<작업명>
6. PR 본문 작성
- 무엇을 했는지
- 왜 했는지 (배경/의도)
- 어떻게 검증했는지 (스크린샷·체크리스트)
7. 팀원 리뷰 → Approve → Merge
머지 방식 합의: squash / merge commit / rebase
8. 머지 후 작업 브랜치 정리
git branch -d feat/<작업명> (로컬)
git push origin --delete feat/<작업명> (원격)
각 단계의 의도를 한 문장으로:
- 1단계 pull 먼저가 빠지면 충돌 다발의 원인 1위
- 2단계 브랜치 안 끊고 develop 에서 바로 작업하면 PR 흐름이 깨짐
- 4단계
-u플래그 한 번 쓰면 다음부터git push만 해도 동작 - 6단계 PR 본문이 리뷰어의 문맥 — 잘 쓰면 리뷰 시간이 절반
- 8단계 브랜치 삭제는 머지 후 즉시 — 안 하면 브랜치 목록이 눈덩이
Conventional Commits — 메시지 일관성
커밋 메시지 형식:
1
2
3
4
5
<type>(<scope>): <subject>
[optional body]
[optional footer]
자주 쓰는 type:
| type | 의미 | 예시 |
|---|---|---|
feat | 새 기능 | feat(combat): add hit detection system |
fix | 버그 수정 | fix(ai): correct zombie spawn channel mismatch |
refactor | 동작 변화 없는 구조 변경 | refactor(module): split Public/Private layout |
chore | 빌드/설정/도구/문서 | chore: update gitignore for .idea and _Fab |
docs | 문서만 | docs(readme): add team workflow section |
test | 테스트만 | test(combat): add LineTrace unit test |
scope 는 모듈/카테고리 이름. NBC_Ch3 에서는 combat, ai, player, ui 등.
이 규칙의 가치:
git log --oneline한 번 보면 어떤 커밋이 무슨 일을 하는지 즉시 파악git log --grep="^fix"같은 필터링이 가능- changelog 자동 생성 도구(
conventional-changelog)와 호환
PR 본문 — 무엇을 / 왜 / 어떻게 검증했는지
세 항목 양식. 팀원에게 강조한 핵심.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## 무엇을
- HealthComponent / WeaponComponent 추가
- LineTrace 기반 히트 판정 + 펠릿 산탄 + 반동 누적/회복
## 왜
- C-TR-01 (히트 판정 / 데미지 시스템) 1차 골격 작업
- VoidUnreal 강결합 코드를 NBC_Ch3 디커플링 패턴으로 이식
- BaseCharacter 의존성 제거 → HealthComponent 만 붙으면 어떤 Actor 든 데미지 가능
## 어떻게 검증했는지
- [x] 빌드 성공 (Win64 / Development Editor)
- [x] PIE 1인 플레이 — 좀비 Actor 에 발사 → 데미지 적용 확인
- [x] 펠릿 산탄 5발 분기 확인 (디버그 LineTrace 시각화)
- [ ] 몽타주 히트 연결은 다음 PR
- 스크린샷: <attach>
이 양식이 작동하는 이유:
- 무엇을 만 있으면 리뷰어가 의도를 모름 → 코드만 보고 추측 → 비효율
- 왜 가 있어야 디자인 의사결정의 맥락이 전달됨 → 리뷰어가 “다른 방식이 더 낫지 않나?” 같은 의견을 정확히 줄 수 있음
- 어떻게 검증 이 있어야 머지 후 회귀가 발생해도 어디까지 검증된 상태였는지 추적 가능
자주 하는 실수 4가지
팀원이 처음 쓸 때 자주 만나는 함정.
| 실수 | 결과 | 예방 |
|---|---|---|
| main에 직접 push | 보호 규칙 없으면 발표 직전에 깨질 위험 | GitHub Settings → Branch protection 으로 main 보호 |
git pull 없이 작업 | 머지 시점에 충돌 다발 | 작업 시작 전 항상 git pull origin develop |
| 너무 큰 PR | 리뷰 부담 → 리뷰 안 됨 → 머지 정체 | 작업 단위 쪼개기. 1 PR = 1 기능 또는 1 fix |
| 커밋 메시지 일관성 부재 | git log 가독성 0, changelog 불가능 | Conventional Commits 강제. PR 머지 시 squash 메시지도 같은 형식 |
main 보호 규칙은 GitHub Settings에서:
1
2
3
4
5
Settings → Branches → Branch protection rules → Add rule
Branch name pattern: main
☑ Require a pull request before merging
☑ Require approvals (1명 이상)
☑ Dismiss stale PR approvals
실제 우리 팀 적용 사례 — 머지된 PR 3건
설명만이 아니라 실제 동작 중인 사례를 보여줘서 팀원이 직접 확인할 수 있게.
1
2
3
4
5
6
7
8
9
10
11
develop 브랜치 최근 머지 PR 3건:
#1 feat/combat-hit-damage-system ← 어제(05/06) 본인 작업
└─ Combat 모듈 (HealthComponent / WeaponComponent / WeaponConfig)
머지 방식: Merge pull request (머지 커밋 보존)
#2 feat/Player ← 다른 팀원
└─ Player 모듈
#3 feat/ZombieCharacter_ZombieAIController ← 또 다른 팀원
└─ AI 모듈 (Zombie 캐릭터 + 컨트롤러)
git log --oneline --graph 로 보면 develop 에 세 PR 머지 흔적이 보임. 팀원에게 “여기 이 머지 커밋이 PR이 들어온 흔적이고, 그 위로 갈래 친 가지가 작업 브랜치였던 거다” 라고 직접 화면 보면서 설명.
머지 방식: Merge pull request (merge commit 보존). 합의 사항:
- squash 도 가능하지만 PR 안에서 chore/fix/feat 가 섞인 경우 squash 하면 정보 손실
- merge commit 보존이 PR의 경계를 visual 하게 남김 —
--graph로 보기 쉬움 - 단점: 커밋 그래프가 갈래 많아짐 → develop 에서는 감수, main 에서는 release 단위 squash 검토
CLI 어려운 팀원용 도구
CLI 만으로 가르치면 진입 장벽이 너무 높아서 GUI 옵션도 같이 안내.
| 도구 | 비고 |
|---|---|
| GitHub Desktop | 가장 단순. add/commit/push/PR 까지 클릭으로 가능. 단 커스텀 워크플로 한계 |
| Source Tree | 그래프 시각화 강함. brackets 가 많아 처음에는 복잡 |
| VS Code Git 확장 | 에디터 안에서 stage/commit/push. branch 시각화는 GitLens 확장과 결합 |
| Rider Git 통합 | UE 작업 때 그대로 사용 가능 — 별도 도구 안 띄워도 됨 |
권장 진행:
- 처음 1주 — GUI(Desktop/Source Tree)로 익힘
- 그 다음 — 자주 쓰는 명령부터 CLI 로 전환 (
pull,push,checkout -b) - 그 후 —
rebase,cherry-pick,stash같은 고급 명령은 필요할 때
언급한 참고 자료:
- Conventional Commits 스펙 페이지(
conventionalcommits.org) git log --oneline --graph --all로 브랜치 시각화 자주 보기
.gitignore 컨벤션 — 어제 정리한 항목 공유
어제(05/06) 정리한 ignore 패턴을 팀원에게 공유. 새 클론 시점에 올바른 ignore 가 적용되도록.
1
2
3
4
5
6
7
8
9
10
11
12
# IDE 개인 설정
.idea/
*.DotSettings.user
# 마켓 에셋 (큼)
Content/_Fab/
# UE 자동 생성물 (Binaries / Intermediate / Saved 등)
Binaries/
Intermediate/
Saved/
DerivedDataCache/
각 항목의 이유는 어제 TIL 5월/2026-05-06.md 에 정리했고 그 링크를 팀원에게 공유. 핵심은 “자동 생성물 = ignore” 가 항상 맞는 건 아니다 — .uproject 의 AdditionalDependencies 같은 자동 주입 메타데이터는 커밋 대상.
오늘 배운 것 정리
UE5 모듈 구조의 정식 표준 =
Module/Public/{Category}/*.h+Module/Private/{Category}/*.cpp. 어제 회복한 flat 구조는 빌드는 되지만 API 경계가 흐려진다. 협업·확장성 관점에서는 모듈 루트의 단일 Public/Private + 카테고리 서브폴더가 정답. VoidUnreal·다수 표준 UE5 프로젝트가 같은 패턴이라 새 모듈 시작 시 바로 이 형태로 만드는 게 안전. 어제의 결론(flat) → 오늘의 결론(Public/Private 표준) 이 이어지는 두 단계 진화.UBT가 자동으로 추가하는 include path는 모듈의
Public/루트뿐이다.Public/AI/같은 서브폴더는 자동 추가되지 않는다.bLegacyPublicIncludePaths=true로 켜면 가능하지만 비권장. 결론: 같은 모듈 내부 헤더 참조도#include "Category/Foo.h"풀 경로 강제. 다른 모듈에서 가져갈 때도 같은 풀 경로 + Build.cs 의존성 추가. 풀 경로 한 가지 형식이 모듈 내·외부 양쪽에서 통한다는 점이 모던 UE5의 깔끔한 설계.bLegacyPublicIncludePaths미설정(=false)이 표준. legacy 모드는 짧은 경로를 허용하지만 (1) 빌드 시간 증가 (2) 헤더 충돌 가능성 ↑ (3) include 의도가 모호. 미설정 = 모던 모드에서 풀 경로 강제하면 의도 명확 + 빌드 빠름 + 충돌 방지. “기본값을 그대로 두는 것이 표준” 이 또 한 번 통하는 사례.git mv로 27개 파일 이동 = 히스토리 보존 + PR diff 명확. 단순mv+git add도 100% 유사도면 자동 rename 추적되긴 하지만, 명시적 rename 이 PR diff 가독성·git log --follow안정성 모두 우월. “동작은 같지만 신호가 다르다” — 도구 선택 시 결과만 같으면 OK 라고 끝내지 않는 디테일.OWNER.txt 같은 비코드 메타데이터도 카테고리 단위를 따라간다. 코드 파일이 아니어도 카테고리에 종속되는 정보(담당자/문서/메모)는 같은 폴더에 두는 게 자연스럽다. Public 쪽에 둔 이유는 외부에서 헤더 보러 들어왔을 때 같이 눈에 띄도록. “의미 단위 = 폴더 단위” 가 일관성 룰.
GitHub PR 워크플로우의 본질 = “1 작업 = 1 브랜치 = 1 PR” + “PR 본문 = 무엇/왜/어떻게 검증”. 이 두 가지만 지켜도 협업의 90%가 정상화된다. 도구·명령어보다 흐름의 이해가 우선. 팀원에게 단계별 명령을 외우게 하기보다 “왜 main 직접 push 가 위험한지” / “왜 PR 본문에 의도를 적어야 하는지” 의도를 먼저 설명. 의도가 잡히면 명령어는 검색해서 찾는다.
자주 하는 실수 4가지 = main 직접 push / pull 없이 작업 / 큰 PR / 커밋 메시지 불일관. 이 4가지가 GitHub 처음 쓰는 팀에서 거의 모든 충돌·정체 원인. 하나하나가 단순한 함정인데 한 번 빠지면 디버깅에 1시간 이상 들어감. 사전 예방 = main 보호 규칙 + Conventional Commits 강제 + PR 작업 단위 쪼개기 합의 세 가지로 해결 가능.
GUI 도구 안내가 진입 장벽 낮춤. CLI 만으로 가르치면 명령어 외우기에 막혀서 정작 흐름 자체를 못 익힘. GitHub Desktop / Source Tree / Rider Git 통합 같은 GUI 로 시작 → 익숙해지면 자주 쓰는 명령부터 CLI 전환. “개념 이해 → GUI → CLI” 순서가 진입 마찰 최소화 한다는 게 오늘 팀원 안내에서 다시 확인.
실제 적용 사례를 보여주는 게 추상적 설명보다 빠르다. 우리 팀 develop 브랜치의 머지된 PR 3건(
feat/combat-hit-damage-system/feat/Player/feat/ZombieCharacter_ZombieAIController) 을 직접 화면 보면서 “이 머지 커밋이 PR 흔적, 위로 갈래 친 게 작업 브랜치였다” 라고 설명하니 즉시 이해. 추상 → 구체 보다 구체(우리 사례) → 추상(룰) 으로 가는 게 학습 효율 높다.“하루 늦게 정리”도 회고 가치는 살아 있다. 이 TIL 자체가 05/08에 어제(05/07) 분을 정리하는 사례. 즉일 정리가 베스트지만 하루 안에라면 디테일 손실 적음. 회고는 안 하는 것보다 늦게라도 하는 게 압도적으로 낫다 — 배경 메모(스크럼/커밋 로그/회의 메모) 가 충실하면 하루 차이는 회복 가능. 이번에는 어제 스크럼·커밋 해시·VoidUnreal 참조 모두 살아 있어 정리 시간이 오히려 짧았다.