UAT 패키징 실패와 Steam 세션 디버깅
에디터에서 되던 프로젝트가 쿡 단계에서 멈춘 이유
패키징 단계에서 처음으로 빌드가 멈췄고, 고쳐서 실행 파일을 뽑아도 Steam 세션이 붙지 않았다. 에디터에서 실행 파일까지 가는 길을 뚫고, 그 사이 어긋난 팀 브랜치를 되돌린 기록.
에디터에서 잘 돌아가던 프로젝트가 패키징 단계에서 처음으로 멈춰 섰다. 쿡 단계에서 빌드가 실패하고, 고쳐서 실행 파일을 뽑아도 이번엔 Steam 세션이 붙지 않았다. 이 글에서는 에디터에서 실행 파일까지 가는 길을 뚫은 과정을 이야기하려 한다 — 패키징 오류 원인과 수정, Steam 멀티플레이어 세션 흐름 검증, 그리고 그 사이에 어긋난 팀 브랜치를 되돌린 롤백까지다.
트러블슈팅 1 — 쿡 단계에서 빌드가 실패한다
문제: exit code 25
UAT(UnrealAutomationTool)의 쿡(Cook, 에셋을 대상 플랫폼용 포맷으로 변환하는 단계)에서 exit code 25로 빌드가 실패했다. UAT는 쿠킹 로그에서 LogLevel: Error가 하나라도 보이면 빌드 실패로 판정한다.
1
2
3
4
5
// S_MainMenu.cpp — 수정 전 (빌드 실패 원인)
UE_LOG(LogTemp, Error, TEXT("...")); // 4군데
// 수정 후
UE_LOG(LogTemp, Log, TEXT("...")); // Error → Log
런타임 의미상 에러가 아닌 상황인데 Error 레벨을 관용적으로 쓴 게 UAT 판정을 트리거했다. 실제 예외 상황이 아니라면 Warning 이하를 쓰는 습관이 필요하다.
DefaultGame.ini 쿠킹 대상 교체
쿠킹 대상 맵이 NetTest로 지정돼 있었는데, 이 맵에서 참조하는 BP의 부모 클래스가 누락된 상태였다. 대상을 Prototype 맵으로 교체해서 해결했다.
1
2
3
; DefaultGame.ini
[/Script/UnrealEd.ProjectPackagingSettings]
MapsToCook=(FilePath="/Game/Maps/Prototype")
트러블슈팅 2 — Steam 세션이 붙지 않는다
Steam_Find가 0개 반환하는 문제
세션을 찾지 못하는 원인은 순서 문제였다. 호스트가 세션을 완전히 생성하기 전에 클라이언트가 검색을 날려 0개를 받은 것.
올바른 워크플로우:
1
2
3
4
1. 호스트: Steam_Host 블루프린트 실행
2. 호스트: CreateSession 완료 콜백(OnSuccess) 수신 확인
3. 클라이언트: 그 다음에 Steam_Find 실행
4. 클라이언트: 검색 결과에서 Steam_Join 실행
CreateSession이 끝나기 전에 FindSessions를 하면 당연히 빈 결과다. 비동기 완료 이벤트를 기다리는 순서가 핵심이었다.
환경 설정
- Steam OSS(OnlineSubsystem Steam, 언리얼 온라인 기능의 Steam 구현) AppID: 480(Spacewar) — 개발용 공개 AppID, 친구 관계 없이 공개 로비 검색 가능
DefaultEngine.ini에 P2P 정리 타임아웃 추가 (세션 종료 후 소켓 정리 지연 경고 제거)
1
2
[SocketSubsystemSteamIP]
P2PCleanupTimeout=120
Steam_Host → Steam_Find → Steam_Join 순서로 실제 멀티 접속 성공 확인.
트러블슈팅 3 — 팀 브랜치를 되돌리기
팀원이 PR 없이 develop에 직접 커밋 2개를 머지한 것을 발견했다. 팀 협업 규칙 위반이라 롤백이 필요했다.
1
2
git reset --hard <정상커밋> # develop을 정상 커밋으로 되돌림
git push --force origin develop # 원격에도 강제 반영
force push 이후 팀원 전파 필수:
1
2
3
# 팀원 전원이 실행해야 함
git fetch origin
git reset --hard origin/develop
force push는 히스토리를 재작성하므로 팀원의 로컬 브랜치가 원격과 달라진다. 팀 채널에 즉시 공지가 필수.
4. PR 생성 및 base 브랜치 수정
feat/furniture-prototype → develop PR을 생성했는데 --base 옵션을 빠뜨려 main에 걸렸다.
1
2
3
4
5
# 잘못 생성된 상태 (base: main)
gh pr create --title "feat: furniture prototype"
# base 브랜치 수정
gh pr edit 13 --base develop
gh pr create 시 저장소의 기본 브랜치(main)로 base가 설정된다. develop 운영 저장소에서는 항상 --base develop을 명시해야 한다.
결과 — 패키징 빌드 성공
UAT BuildCookRun으로 Development 구성 패키징 완료.
1
출력: Packaged/Windows/TeamCarry.exe
로그 레벨 수정 + 쿠킹 대상 교체 두 가지로 exit code 25가 사라졌다.
정리 — 패키징에서 남은 것
- UAT는
UE_LOG Error를 빌드 실패로 판정한다. 쿠킹 로그에 Error 레벨이 보이면 exit code 25로 종료. 런타임 에러가 아닌 일반 출력은Log/Warning을 쓰자. - Steam 세션은 순서가 전부다.
CreateSessionOnSuccess 콜백 이후에FindSessions를 해야 한다. 완료를 기다리지 않으면 항상 0개. - force push 후엔 팀 공지가 세트.
git reset --hard origin/<branch>를 팀원이 직접 실행해야 로컬이 맞춰진다. 자동으로 되지 않는다. gh pr create의 default base는 저장소 기본 브랜치.develop운영 시--base develop명시가 필수. PR 생성 후gh pr edit <num> --base <branch>로 수정 가능.- 쿠킹 대상 맵의 BP 의존성도 빌드 결과에 영향. 맵을 바꿀 때 그 맵의 BP 부모 클래스가 모두 빌드에 포함돼 있는지 확인해야 한다.
핵심 요약 — UAT는 쿠킹 로그에 Error 레벨 로그가 하나라도 있으면 exit code 25로 빌드를 실패시키므로, 실제 예외가 아닌 출력에
UE_LOG Error를 쓰면 안 된다. Steam 세션은 CreateSession 완료 콜백을 받은 뒤에 FindSessions를 해야 검색이 된다는 비동기 순서도 직접 확인했다.