본문 바로가기

패키징 및 빌드 설정

쿠킹·빌드·패키징 단계와 개발·테스트·출시 구성을 이해하고 대상 플랫폼 실행 파일과 오류를 검증합니다.

배포 전 점검을 마쳤다면 이제 실제로 실행 파일을 만드는 단계입니다. 패키징(packaging)은 에디터에서 돌아가던 프로젝트를 PC, 모바일, 콘솔 같은 대상 플랫폼에서 혼자 실행할 수 있는 형태로 바꾸는 과정으로, 이때 고른 옵션이 파일 크기와 로딩 속도, 성능, 데이터 보호 수준에 바로 영향을 줍니다. 그리고 패키징이 실패했을 때 어느 단계에서 실패했는지를 알아야 고칠 곳을 찾을 수 있습니다.

이 글에서는 패키징을 이루는 단계부터 나눠 보고, 빌드 구성과 빌드 타겟, 쿠킹과 패키징의 설정을 차례로 살펴봅니다. 그다음 플랫폼마다 필요한 설정과 패키징을 실행하는 방법, 자주 생기는 오류와 그것을 고치는 순서를 정리합니다. 목표 플랫폼에 맞는 빌드 설정을 고르는 기준을 세워 두면 출시하는 빌드의 품질을 안정적으로 지킬 수 있습니다.


패키징을 이루는 단계

패키징은 언리얼 엔진 프로젝트를 플레이어가 설치하고 실행할 수 있는 최종 파일, 예를 들어 Windows의 .exe나 Android의 .apk로 바꾸는 일련의 과정입니다. 이 과정은 네 단계로 나뉘며, 패키징이 실패하면 로그에서 어느 단계가 실패했는지부터 확인합니다.

첫 단계는 빌드(Build)로, 프로젝트와 플러그인의 코드를 컴파일하고 링크해 대상 플랫폼용 실행 바이너리를 만듭니다. 둘째는 쿠킹(Cook)으로, 에셋을 대상 플랫폼이 읽을 수 있는 형식으로 바꿉니다. 셋째는 스테이징(Stage)으로, 실행 파일과 쿠킹한 콘텐츠를 별도의 스테이징 폴더에 모읍니다. 마지막은 패키지(Package)로, 플랫폼마다 배포할 파일 묶음을 구성합니다. 여기서 만드는 .pak은 콘텐츠를 담는 컨테이너이며 실행 파일 자체와는 다릅니다. 만든 결과를 장치로 보내는 배포(Deploy)와 실행(Run)은 필요할 때 이어서 하는 별도의 작업입니다.


패키징 설정

패키징 설정은 툴바의 Platforms 메뉴에서 Packaging Settings를 고르거나, Edit 메뉴의 Project Settings에서 Project의 Packaging으로 들어가 조정합니다. 두 경로는 같은 설정 화면으로 이어지며, 여기서 정한 값은 프로젝트에 저장되어 이후의 패키징마다 적용됩니다. 아래 항목은 앞 절의 네 단계와 짝지어 읽으면 이해하기 쉽습니다. 빌드 구성과 빌드 타겟은 빌드 단계에서 어떤 실행 파일을 만들지를, 쿠킹 설정은 어떤 콘텐츠를 변환할지를, 묶기와 암호화는 패키지 단계에서 그 콘텐츠를 어떻게 담을지를 정합니다.

빌드 구성

빌드 구성(build configuration)은 가장 중요한 설정 가운데 하나로, 빌드의 목적과 그 안에 넣을 디버그 정보의 수준을 정합니다.

BUILD CONFIGURATION

빌드 구성은 최적화와 진단 범위를 정합니다

개발 목적에 맞는 구성을 선택합니다. 디버그 심볼의 생성·보관·배포 포함 여부는 별도로 정합니다.

구성별 코드 최적화와 용도
구성최적화·진단주요 용도
Debug엔진·게임 모두 최적화 없이 디버깅엔진까지 추적할 때
DebugGame엔진은 최적화, 게임 코드는 디버깅게임 모듈을 추적할 때
Development대부분의 최적화와 개발 진단 도구개발·기능·성능 분석
TestShipping에 일부 통계·프로파일 도구 유지출시 조건에 가까운 내부 시험
Shipping출시용 최적화, 기본 콘솔·통계 제한최종 사용자에게 배포
Debug
엔진·게임 모두 최적화 없이 디버깅 · 엔진까지 추적할 때
DebugGame
엔진은 최적화, 게임 코드는 디버깅 · 게임 모듈을 추적할 때
Development
대부분의 최적화와 개발 진단 도구 · 개발·기능·성능 분석
Test
Shipping에 일부 통계·프로파일 도구 유지 · 출시 조건에 가까운 내부 시험
Shipping
출시용 최적화, 기본 콘솔·통계 제한 · 최종 사용자에게 배포

성능 순위로 읽지 않기

파일 크기와 실제 성능은 대상 빌드에서 측정합니다. Debug·Test의 가용성은 엔진 빌드와 Target에 따라 다릅니다.

위 그림은 다섯 가지 빌드 구성의 최적화와 진단 범위, 그리고 주된 용도를 표로 보여 줍니다. Debug는 엔진과 게임 코드 모두 최적화하지 않고 디버깅할 수 있는 구성으로, 엔진 내부까지 따라가야 할 때 씁니다. DebugGame은 엔진은 최적화하고 게임 코드만 디버깅할 수 있게 둔 구성으로, 게임 모듈을 따라갈 때 씁니다. Development는 대부분의 최적화를 하면서 개발용 진단 도구를 남겨 둔 구성으로, 개발과 기능 시험, 성능 분석에 씁니다.

나머지 두 구성은 출시에 가깝습니다. Test는 Shipping에 일부 통계와 프로파일링 도구를 남겨 둔 구성으로, 출시와 비슷한 조건에서 내부 시험을 할 때 씁니다. Shipping은 출시용으로 최적화하고 기본 콘솔과 통계를 제한한 구성으로, 최종 사용자에게 배포할 때 씁니다.

그림 아래의 카드가 짚듯이, 이 표를 성능의 순위로 읽지는 않습니다. 파일 크기와 실제 성능은 대상 빌드에서 직접 측정하며, Debug나 Test를 쓸 수 있는지는 엔진 빌드와 타겟에 따라 다릅니다. 또 디버그 심볼(symbol)은 Shipping에서도 만들어 보관할 수 있습니다. 심볼을 배포 파일에 넣을지와 내부의 심볼 서버에 보관할지는 따로 정하는 일이며, 빌드 구성만으로 파일 크기나 성능의 순위가 정해지지는 않습니다.

빌드 타겟

빌드 타겟(build target)은 어떤 종류의 실행 파일을 만들지 정하며, Platforms 메뉴의 대상 플랫폼 항목에서 고릅니다. Game은 일반적인 게임 실행 파일로, 대부분 이것을 씁니다. Client는 네트워크 게임에서 클라이언트 전용 실행 파일을 만들며, 그에 맞는 Client 타겟 설정이 필요합니다. Server는 네트워크 게임의 전용 서버 실행 파일을 만들며, Server 타겟 설정과 그것을 지원하는 엔진 빌드가 필요합니다.

쿠킹 설정

쿠킹은 최종 빌드에 넣을 콘텐츠를 효율적인 형식으로 만드는 과정이며, 무엇을 넣을지가 핵심입니다.

List of maps to include in a packaged build에서는 시작 맵과 플레이할 맵, 전환 맵이 쿠킹 대상에 들어가는지 확인합니다. 맵 목록은 넣을 것을 정하는 방법의 하나일 뿐이고, 명령행이나 에셋 매니저 같은 다른 규칙도 함께 영향을 줍니다.

Cook everything in the project content directory를 켜면 콘텐츠 폴더의 모든 에셋을 빌드에 넣으려고 합니다. 간편하지만 필요 없는 에셋까지 들어가 빌드가 커질 수 있습니다. 끄면 맵과 참조 관계, 에셋 매니저와 추가 쿠킹 규칙에 따라 넣을 것이 정해집니다. 빌드 크기를 줄이기에 유리하지만, 실행 중에 이름으로 불러오는 에셋이 빠질 수 있으므로 주의합니다.

Generate Chunks를 켜면 게임 데이터를 여러 청크(chunk)의 .pak 파일로 나눠 만듭니다. 큰 게임에서 일부 청크만 내려받게 하거나 패치를 쉽게 하려고 쓰는 고급 기능입니다. 어떤 에셋이 어떤 청크에 들어갈지는 Project Settings의 Game에 있는 Asset Manager의 Primary Asset Types to Scan과 청크 ID 설정으로 정합니다.

묶기와 암호화

Use Pak File을 켜면 쿠킹한 콘텐츠를 하나 이상의 .pak 아카이브로 묶으며, 아이오 스토어를 켜면 .utoc와 .ucas를 쓰는지도 확인합니다. 파일을 묶어 관리하기 쉬워지지만, 압축과 암호화, 서명은 별도의 설정이고 실제 크기와 로딩 성능은 측정해야 합니다. 이런 컨테이너를 쓰지 않으면 쿠킹한 파일이 하나하나 따로 놓이는데, 이것이 에디터의 원본 에셋을 그대로 배포한다는 뜻은 아닙니다.

For Distribution은 앱 스토어에 제출하는 것 같은 플랫폼의 배포용 구성을 고르는 옵션입니다. 압축과 암호화, 서명 키는 각각 따로 정하며, 대상 플랫폼과 스토어의 제출 지침에 맞춰 적용합니다.

데이터를 암호화하는 설정은 Project Settings의 Crypto 항목에 있습니다. Encrypt Pak Ini Files, Encrypt Pak Index, Encrypt UAsset Files 같은 옵션을 켜면 게임 데이터를 암호화해 꺼내기 어렵게 만들며, 이를 위해 같은 곳에서 암호화 키를 설정해야 합니다. 같은 항목의 pak 서명(signing)은 데이터가 바뀌지 않았는지 확인하는 기능으로, 암호화와는 목적이 다릅니다. 그리고 클라이언트 쪽의 암호화만으로 데이터를 완전히 보호할 수는 없다는 점도 기억합니다.


플랫폼별 설정

대상 플랫폼마다 추가로 필요한 설정이 있습니다.

Windows는 Project Settings의 Platforms에 있는 Windows에서 정합니다. Targeted RHIs 항목에서는 이 빌드가 대상으로 삼을 렌더링 API를 체크박스로 고르고, 그 안의 Default RHI에서는 기본으로 쓸 렌더링 API를 DirectX 11, DirectX 12, Vulkan 가운데에서 고릅니다. Default RHI로 고른 API는 Targeted RHIs에서도 켜 두어야 하므로, 지원할 장치와 기능에 맞춰 두 설정을 함께 확인합니다. Packaging 항목에서는 Visual C++ 재배포 패키지 같은 필수 런타임(Prerequisites)을 설치 프로그램에 넣을지 정합니다.

Android는 Platforms의 Android에서 정합니다. APK Packaging에서는 Android 패키지 이름과 Store Version, Minimum SDK Version과 Target SDK Version 같은 항목을 확인합니다. 빌드 구성은 이 항목에 없으므로, 앞에서 본 Project의 Packaging에 있는 Build Configuration이나 툴바 Platforms 메뉴의 Binary Configuration에서 Shipping으로 정합니다. 앱 번들은 App Bundles의 Generate Bundle (AAB)로 만들며, Google Play의 제출 요구사항도 확인합니다. 텍스처 압축 형식은 ETC2, DXT, ASTC 같은 선택지가 있으며, 기기 호환성과 파일 크기에 큰 영향을 줍니다. 모든 기기를 지원하려면 여러 형식을 함께 넣어야 할 수 있습니다. 패키징할 아키텍처로는 ARM64를 켭니다. 서명에는 출시용으로 따로 만들어 관리하는 키스토어 파일로 이름과 별칭, 비밀번호 같은 서명 정보를 설정합니다.

iOS는 Platforms의 iOS에서 번들 식별자와 버전 번호, 빌드 번호를 정하고, 서명에는 Apple 개발자 계정에서 발급받은 인증서와 프로비저닝 프로필을 설정합니다. 세로와 가로 화면을 지원할지도 정합니다.

콘솔은 Sony, Microsoft, Nintendo 같은 각 제조사의 개발자 프로그램에 등록하고, 그 SDK가 설치된 환경에서 언리얼 엔진의 전용 빌드 과정을 써야 합니다. 설정은 콘솔마다 다릅니다.


패키징 실행하고 오류 고치기

패키징 실행

툴바의 Platforms 메뉴에서 대상 플랫폼을 고르고 Package Project를 누릅니다. 패키징이 시작되면 출력 로그(Output Log)에서 진행 상황을 볼 수 있고, 성공적으로 끝나면 지정한 출력 폴더에 실행할 수 있는 게임 파일이 생깁니다.

자주 생기는 오류

쿠킹 실패(Cook Failed)는 콘텐츠에 잘못된 참조나 빠진 에셋, 컴파일 오류가 있는 블루프린트가 있을 때 생깁니다. 출력 로그를 자세히 읽어 어떤 에셋이나 블루프린트에서 오류가 났는지 찾아 고치고, 콘텐츠 브라우저에서 폴더의 리디렉터를 주기적으로 정리해 리디렉터 때문에 생기는 오류를 줄입니다. 리디렉터는 에셋 브라우저와 폴더 구조에서 다뤘습니다.

링크 실패(Linking Failed)는 빌드 단계의 오류로, 컴파일 단계의 오류와 구분해 정의되지 않은 심볼이나 빠진 라이브러리, 모듈 사이의 종속성을 확인합니다. Visual Studio에서 C++ 프로젝트를 먼저 빌드해 오류를 해결합니다.

서명 실패(Signing Failed)는 주로 모바일에서 생기며, Android의 키스토어 정보가 잘못되었거나 iOS의 인증서나 프로비저닝 프로필이 만료되었거나 잘못 설정되었을 때 생깁니다. Platforms의 Android나 iOS에서 서명 설정을 다시 확인하고 유효한 서명 정보를 씁니다.

맵을 찾지 못하는 오류(Map Not Found)는 Packaging의 List of maps to include in a packaged build에 필요한 맵이 빠졌을 때 생기므로, 그 맵을 목록에 더합니다.

패키징한 빌드를 실행하다 크래시가 생기면, 그 Shipping 빌드와 정확히 같은 심볼과 크래시 덤프를 보관해 분석합니다. Development나 DebugGame에서도 재현해 볼 수 있지만, Shipping에서만 생기는 오류는 원래의 구성에서 확인해야 합니다.

오류를 읽는 방법

오류 로그는 마지막의 실패 요약만이 아니라, 그 실패를 일으킨 앞쪽의 오류까지 함께 읽습니다. 마지막 줄에는 보통 "패키징 실패" 같은 결과만 적혀 있고, 실제 원인은 그보다 앞에 있기 때문입니다. 스테이징 단계에서 실패했다면 복사할 경로와 권한, 디스크의 여유 공간도 확인하고, 로그와 결과물은 빌드 번호와 연결해 보관합니다.

배포 직전의 확인 순서

배포 직전에는 다음 순서로 확인합니다. 먼저 Development 빌드에서 기능의 회귀를 없앱니다. 그다음 같은 커밋으로 Shipping을 만들고, 그 구성에서 쓸 수 있는 플랫폼 도구나 프로젝트의 계측으로 로딩 시간과 FPS, 메모리를 측정합니다. 인증과 로그인, 저장처럼 상태를 저장하는 기능이 패키징한 뒤에도 똑같이 동작하는지 확인하고, 앞으로의 패치를 생각해 빌드 결과물의 버전과 넣은 맵의 목록을 다시 점검합니다. 마지막으로 출시 후보 빌드를 새 PC나 새 계정처럼 깨끗한 환경에서 최종 확인합니다.

이때 다음을 함께 점검합니다. 쿠킹 실패의 원인이 된 에셋을 로그로 정확히 찾았는지, Android와 iOS의 서명이 만료되거나 권한 문제가 없는지 미리 확인했는지, 맵 목록에서 빠져 실행할 수 없는 맵이 생기지 않았는지, Shipping 빌드에서만 생기는 크래시를 따로 시험했는지, 그리고 실행 파일과 DLC나 패치 파일, 버전 문서 같은 배포 결과물이 서로 맞는지입니다.


정리

  • 패키징은 빌드, 쿠킹, 스테이징, 패키지의 네 단계로 나뉘며, 실패하면 어느 단계에서 실패했는지부터 확인합니다.
  • 빌드 구성은 Debug, DebugGame, Development, Test, Shipping이 최적화와 진단 범위를 정하며, 성능의 순위가 아니고, 심볼의 보관은 따로 정합니다.
  • 빌드 타겟은 Game, Client, Server 가운데 고르며, Client와 Server에는 그에 맞는 타겟 설정이 필요합니다.
  • 쿠킹은 맵 목록과 참조, 에셋 매니저 규칙으로 넣을 것을 정하고, 모든 콘텐츠를 쿠킹하지 않을 때는 실행 중에 불러오는 에셋이 빠지지 않게 합니다.
  • .pak과 아이오 스토어는 묶는 방식이고, 압축과 암호화, 서명은 따로 설정하며, 암호화 키와 pak 서명은 Crypto 항목에서 정합니다.
  • 오류는 마지막 요약이 아니라 앞쪽의 실제 원인을 찾아 고치고, Development로 기능을 확인한 뒤 같은 커밋의 Shipping으로 측정하고 깨끗한 환경에서 최종 확인합니다.

연습 문제

1. 실패한 단계로 다음 행동 고르기

같은 프로젝트를 세 번 패키징했는데 각각 다른 이유로 멈췄습니다. A는 게임 모듈에 정의되지 않은 심볼이 있다는 오류, B는 쿠킹할 에셋의 잘못된 참조, C는 스테이징 폴더의 여유 공간 부족입니다. 각각 어느 단계의 기록을 먼저 살펴봐야 할까요? 세 경우 모두 시작 맵을 다시 지정하거나 Shipping으로 바꾸면 해결될까요?

해설 보기

A는 빌드 단계의 링크 오류이므로, 그 심볼을 정의한 모듈이나 라이브러리와 타겟 설정을 조사합니다. B는 쿠킹 단계의 에셋 참조 오류이므로, 어떤 에셋의 참조가 잘못되었는지 찾습니다. C는 스테이징 단계의 문제이므로, 복사할 대상 폴더와 디스크의 여유 공간을 확인합니다.

시작 맵을 바꾸거나 구성을 바꾸는 것이 모든 원인의 해결책은 아닙니다. 마지막의 실패 요약에서 거슬러 올라가 실제 앞쪽의 오류와 그 단계를 찾고, 원인 하나를 바꾼 뒤 새 로그로 결과를 확인합니다.

2. Shipping에서만 나는 크래시

Development 패키지에서는 문제가 없는데, Shipping 패키지에서만 특정 레벨에 들어가면 크래시가 납니다. Development로 다시 재현해 보려 했지만 재현되지 않습니다. 어떻게 분석해야 할까요?

해설 보기

Shipping에서만 생기는 오류는 최적화나 개발용 코드의 차이 때문일 수 있어서, 다른 구성에서는 재현되지 않을 수 있습니다. 그래서 원래의 Shipping 구성에서 확인해야 합니다.

그 Shipping 빌드를 만들 때 정확히 같은 심볼을 함께 만들어 보관하고, 크래시 덤프를 그 심볼로 분석합니다. 심볼은 배포 파일에 넣지 않고 내부에 보관할 수 있으므로, 출시 빌드마다 심볼을 빌드 번호와 함께 보관해 두는 것이 중요합니다.

3. 모든 콘텐츠를 쿠킹하지 않았더니

빌드 크기를 줄이려고 Cook everything in the project content directory를 껐습니다. 패키지는 잘 만들어졌는데, 실행 중에 데이터 테이블에 적힌 경로로 불러오는 무기 메시 몇 개가 보이지 않습니다. 무엇이 문제이고 어떻게 고칠까요?

해설 보기

모든 콘텐츠를 쿠킹하지 않으면 맵과 참조 관계, 에셋 매니저 규칙을 따라 넣을 것이 정해지는데, 데이터 테이블에 문자열 경로로만 적힌 에셋은 그 참조를 따라가지 못해 쿠킹에서 빠질 수 있습니다.

그 무기 메시들이 쿠킹 대상에 들어가도록 에셋 매니저의 규칙이나 추가 쿠킹 목록에 명시하거나, 데이터 테이블에서 소프트 참조로 가리키게 해 엔진이 참조를 알 수 있게 합니다. 고친 뒤에는 그 메시가 실제로 패키지에 들어갔는지 확인합니다.

빌드 구성과 패키징 과정은 Epic의 빌드 작업 안내에서 확인할 수 있습니다.

다음 글 배포 후 환경 유지보수에서는 게임을 배포한 뒤 엔진과 플랫폼의 변화에 맞춰 환경 설정과 빌드를 계속 관리하는 방법을 다룹니다.