Zenserver를 쿠킹된 출력 저장소로 사용하는 목적은 다음과 같습니다.
-
대규모 프로젝트에서 쿠킹 출력으로 백만 개 이상의 파일이 생성될 때 발생하는 파일 시스템 오버헤드를 줄임으로써 쿠킹 시간 효율성을 향상합니다.
-
향후 신뢰할 수 있는 점진적 쿠킹을 할 수 있습니다.
-
Zenserver에 쿠킹된 출력 저장소로 빌드하는 젠 스트리밍 기능을 사용하여 스테이징과 디플로이를 훨씬 빠르게 수행할 수 있습니다.
-
Zenserver에 쿠킹된 출력 저장소로 빌드하는 젠 스트리밍 기능을 사용하여 쿠킹된 상태를 쉽게 임포트할 수 있습니다.
-
앞으로 쿠킹된 출력 데이터에 포함된 파생 데이터를 더 효율적으로 표현할 수 있습니다.
-
중간에 대규모 데이터를 변환할 필요 없이 게임이 로드되는 동일한 스토리지에 쿠킹할 수 있어 앞으로 더욱 직접적이고 효율적이며 타깃이 명확한 워크플로를 이용할 수 있습니다.
쿠킹된 출력 이해하기
Zenserver의 쿠킹된 출력 스토리지 사용법을 이해하기 전에 먼저 쿠킹된 출력이 어떻게 처리되고 쿠킹된 출력이 언리얼 엔진의 데이터 쿠킹과 스테이징, 디플로이를 위한 더 넓은 파이프라인에 어떻게 들어맞는지를 알면 좋습니다.
다음은 언리얼 엔진 5.4에서 쿠킹, 스테이징, 디플로이용 파이프라인을 표현한 것입니다.
데이터의 수량은 가정한 수치이지만, 대규모 게임 프로젝트에 맞는 수준입니다.
왼쪽에서 오른쪽으로 흐름을 따라가 보면, 첫 번째 단계가 .uasset 파일과 파생 데이터 캐시(Derived Data Cache, DDC)에서 데이터를 로드하는 쿠킹 작업인 것을 알 수 있습니다. 언리얼 엔진 5.4부터 이 DDC 데이터는 Zenserver라는 별도의 프로세스로 저장되는데, 언리얼 에디터와 함께 실행되는 모습을 볼 수 있습니다. Zenserver는 이 데이터를 표현하는 방식과 디스크에 저장하는 방법을 내부적으로 정의합니다.
디폴트 환경설정에서 쿠킹된 출력 파일은 프로젝트의 Saved/Cooked/<Platform> 폴더에 필요한 만큼 별개의 파일로 기록됩니다. 이러한 파일은 매우 많아질 수 있으며, 여기에 사용되는 바이트 크기도 커질 수 있습니다.
이렇게 파일이 많아지면 파일 시스템에 퍼포먼스 병목 현상이 발생할 수 있습니다. 이는 다음과 같은 현상으로 나타납니다.
-
쿠킹된 출력을 삭제하는 데 시간이 오래 걸립니다(15분 이상). 비동기식으로 수행한다고 해도 여전히 파일 시스템 쓰기 캐시 플러시가 발생하여 다른 I/O 작업에 영향을 줍니다.
-
Windows Defender와 같은 엔드포인트 보안 소프트웨어가 각 파일의 열기/닫기 작업에 관여하면서 쿠킹이 느려집니다.
-
마지막 액세스 시간 트래킹 같은 파일 시스템 메타데이터가 파일 시스템 쓰기 캐시를 채워 디스크에 플러시하게 만드는 원인이 되므로 쿠킹이 느려집니다.
이러한 문제는 소규모 프로젝트에서는 시간을 많이 잡아먹지 않지만, 프로젝트 규모가 커질수록 문제가 심각해집니다.
Zenserver를 쿠킹된 출력 저장소로 대신 사용하면 쿠킹된 출력을 패킹되지 않은 파일로 저장하지 않고 Zenserver 안에 저장할 수 있습니다.
Zenserver는 쿠킹된 출력을 선택한 표현으로 디스크에 쓰는 작업을 담당합니다. 즉, 작은 데이터 조각이 환경설정된 크기 한계치보다 작으면 더 큰 블록 파일로 집계될 수 있습니다. 그래서 이 예시에서는 앞서와 마찬가지로 1,000,000개 데이터를 저장해도 파일 시스템에는 훨씬 적은 수의 파일만 보입니다.
Zenserver를 쿠킹된 출력 저장소로 활성화하기
언리얼 엔진 5.5부터 Zenserver는 쿠킹된 출력 스토리지로 사용하는 것은 디폴트값이 아닙니다. 이 부분은 향후 출시 때 바뀔 예정입니다. 현재는 언리얼 에디터를 실행하고 편집 >프로젝트 세팅 메뉴 아이템의 프로젝트 > 패키징 섹션에서 Zenserver를 쿠킹된 출력 저장소로 사용하도록 선택할 수 있습니다. 해당 섹션에서 Zenserver를 쿠킹된 출력 저장소로 사용(Use Zenserver as cooked output store) 이라는 세팅을 찾으면 해당 세팅이 디폴트로 비활성화되어 있을 것입니다.
그 세팅을 활성화하고 I/O 스토어 사용(Use Io Store) 도 활성화되어 있는지 확인(디폴트로 활성화되어 있음)합니다. 둘 다 활성화되었다면 세팅이 저장되었음을 알 수 있습니다.(소스 컨트롤을 사용하는 경우 세팅 변경사항을 저장하려면 파일을 체크아웃해야 할 수도 있습니다.) 그러면 이때부터 Zenserver를 쿠킹된 출력 저장소로 사용하게 됩니다.
Zenserver를 쿠킹된 출력 저장소로 사용할 때 쿠킹된 데이터의 위치
Zenserver를 쿠킹된 출력 저장소로 사용해도 엔진에서는 여전히 프로젝트의 Saved/Cooked/<Platform> 폴더에 일부 데이터를 생성하고 작성합니다. 다만 훨씬 적은 양만 작성하는데, 쿠킹된 에셋 데이터는 전부 Zenserver에 저장하기 때문입니다. Saved/Cooked/<Platform> 폴더에는 .uasset, .ubulk 또는 .uexp 파일이 더 이상 포함되지 않을 것입니다. 해당 폴더에는 쿠킹된 데이터의 저장 위치를 알려주는 작은 내부 디스크립터인 ue.projectstore 파일만 보일 것입니다. 이 파일은 엔진이 쿠킹된 데이터를 찾아 액세스하는 데 필요합니다.
그렇다면 쿠킹된 에셋 데이터는 어디에 저장될까요? Zenserver는 Zenserver용 데이터 디렉터리의 파일(일부는 집계된 파일)에 데이터를 보관합니다. 여기에는 로컬 DDC 데이터와 쿠킹된 출력 데이터 가 모두 포함됩니다.
Zenserver 데이터의 기본 위치는 다음과 같습니다.
-
Windows:
%LOCALAPPDATA%\UnrealEngine\Common\Zen\Data -
Mac:
~/Library/Application Support/Epic/UnrealEngine/Common/Zen/Data -
Linux:
~/.config/Epic/UnrealEngine/Common/Zen/Data
Zenserver는 로컬 DDC를 저장할 때에도 사용되므로 해당 데이터 스토리지 위치는 다음 DDC 환경설정 메커니즘에 따라 디폴트값을 오버라이드합니다.
-
언리얼 에디터 DDC 세팅에 설정된 글로벌 로컬 DDC 경로.
-
환경 변수(
UE-LocalDataCachePath)를 통해 로컬 DDC 경로 오버라이드. -
명령줄 실행인자(
-LocalDataCachePath=<path>)를 통해 로컬 DDC 경로 오버라이드.
마지막으로 디폴트 및 로컬 DDC 경로 환경설정 옵션을 모두 오버라이드하는 Zenserver 전용 경로 환경설정이 있습니다.
-
환경 변수(
UE-ZenDataPath)를 통해 Zenserver 경로 오버라이드. -
명령줄 실행인자(
-ZenDataPath=<path>)를 통해 Zenserver 경로 오버라이드.
편집 > 에디터 개인설정 메뉴 아이템을 사용하여 글로벌 로컬 DDC 경로를 세팅한 다음 일반(General) > 글로벌(Global) 섹션을 선택하여 Zenserver 데이터(DDC 및 쿠킹된 출력 모두)에 적합한 경로를 선택하는 것이 좋습니다.
다음과 같은 위치를 글로벌 로컬 DDC 경로(묵시적으로 Zenserver에도 적용)를 선택하는 것이 좋습니다.
-
빠른 로컬 드라이브.
-
네트워크 드라이브는 안 됨.
-
Google 드라이브 같은 가상 드라이브는 안 됨.
여러 개의 쿠킹된 출력 플랫폼, 프로젝트, 워크스페이스의 스토리지
Zenserver는 쿠킹된 플랫폼, 프로젝트, 워크스페이스 전부를 위한 단일 스토리지 서비스로 작동합니다. Zenserver는 서로 다른 플랫폼, 프로젝트, 워크스페이스를 위한 하나 또는 다수의 쿠킹된 출력 데이터를 저장하면서도 다른 플랫폼의 데이터를 덮어쓰는 일이 없도록 설계되었습니다. 내부적으로는 데이터를 저장할 때 중복 제거 이점이 있는 콘텐츠 어드레서블 스토리지를 사용합니다. 즉, 같은 데이터를 쿠킹하고 대상 플랫폼에 같은 출력 바이트를 생성하는 프로젝트 두 개를 진행하는 경우, Zenserver는 하드 드라이브에 그러한 바이트를 한 번만 저장하며, 각 프로젝트는 기본 콘텐츠 어드레서블 스토리지 레퍼런스에서 해당 블롭에 대한 레퍼런스를 가지게 됩니다.
데이터 삭제 및 클린업
Zenserver 내에서 쿠킹된 출력 데이터는 콘텐츠 어드레서블 스토리지 레이어에 대한 레퍼런스를 사용하여 저장됩니다. 데이터는 어디서든 해당 데이터를 참조하는 한 유지됩니다.
Zenserver는 주기적으로 가비지 컬렉션을 수행하면서 그 과정에서 더 이상 참조되지 않는 데이터를 발견하면 해당 데이터를 제거하므로, 데이터가 점유하던 디스크 공간을 회수할 수 있게 됩니다.
쿠킹된 출력 데이터의 경우, ue.projectstore 파일의 유무로 레퍼런스를 제어합니다. Zenstorage에 쿠킹한 경우, ue.projectstore 파일이 생성되며 이 파일은 쿠킹된 데이터에 대한 레퍼런스를 나타내는 마커로 사용됩니다. Zenserver 내에서 가비지 컬렉션을 수행했을 때,
-
ue.projectstore파일이 삭제된 경우 -
ue.projectstore파일 수정 시간이 14일을 초과한 경우
쿠킹된 데이터는 쿠킹된 해당 출력의 레퍼런스가 없는 것으로 간주됩니다. 데이터 한 개에 대한 레퍼런스가 쿠킹된 어떤 출력에도 포함되지 않은 경우, 해당 데이터는 가비지 컬렉션에 의해 제거되고 해당 데이터가 사용하던 공간은 회수됩니다.
검사 및 디버깅
Zenserver에 저장된 쿠킹된 출력 데이터는 디버깅하고 검사하는 데 제한이 있습니다.
그때까지는 언리얼 젠 대시보드(프로그램 이름 ZenDashboard)라는 작은 유틸리티 프로그램을 사용하여 Zenserver의 기본 통계를 검사하고 기본 컨트롤 명령을 내릴 수 있습니다. 에디터 오른쪽 하단의 파생 데이터(Derived Data) 버튼을 클릭하고 젠 대시보드 실행(Launch Zen Dashboard) 을 선택하여 이 유틸리티 프로그램을 사용할 수 있습니다.
Zenserver를 쿠킹된 출력 저장소로 활성화했다면, 패킹되지 않은 파일을 Zenserver에 저장하지 않고 파일 시스템에서 패킹되지 않은 파일에 쿠킹을 실행해야 하는 상황이 발생할 수 있습니다. 이를 위해서는 쿠킹 커맨드릿을 호출할 때 다음과 같은 실행인자를 전달할 수 있습니다.
커맨드릿 쿠킹
-skipzenstore
로우 레벨 디버깅 기능은 로컬 Zenserver와 상호작용하는 명령 프롬프트 유틸리티를 통해 이용할 수 있습니다. 해당 유틸리티는 젠 대시보드에서 툴(Tools) > 유틸리티 명령 프롬프트 실행(Launch Utility Command Prompt) 을 선택하여 이용할 수 있습니다.
이 유틸리티를 통해 로컬 Zenserver의 데이터와 상호작용하는 다양한 명령을 사용할 수 있습니다.
스테이징된 데이터에 대한 영향
콘텐츠 파이프라인에서 스테이징은 쿠킹의 다음 단계입니다. 스테이징은 언리얼 자동화 툴(Unreal Automation Tool, UAT)을 사용하여 직접 또는 에디터를 통해 호출됩니다. 이를 통해 다음 중 하나에 스테이징할 수 있습니다.
-
컨테이너 파일: 쿠킹된 출력 데이터는 집계되며, 필요에 따라 프로젝트의
Saved/StagedBuilds/<Platform>디렉터리에 소수의*.pak,*.utoc,*.ucas파일로 압축될 수 있습니다. -
패킹되지 않은 파일: 쿠킹된 출력 데이터는 프로젝트
Saved/StagedBuilds/<Platform>디렉터리의 하위 디렉터리에 일대일로 복사됩니다.
컨테이너나 패킹되지 않은 파일에 스테이징하는 작업은 언리얼 자동화 툴을 호출할 때 -pak 명령줄 실행인자의 유무로 제어할 수 있습니다. Zenserver를 쿠킹된 출력 저장소로 사용하면 쿠킹 단계의 출력에 영향을 주므로, 스테이징 단계도 아래 기술된 대로 조정해야 합니다.
컨테이너 파일에 스테이징하는 경우
Zenserver를 쿠킹된 출력 저장소로 사용할 때, 컨테이너 파일(*.pak, *.utoc, *.ucas)에 스테이징하면 언리얼 자동화 툴 및 툴이 스폰하는 UnrealPak 실행파일은 파일 시스템이 아니라 Zenserver에서 쿠킹된 출력 데이터를 가져옵니다.
해당 데이터를 가져오기 위해 Zenserver를 실행해야 하는 경우, 언리얼 자동화 툴과 UnrealPak은 모두 자동으로 Zenserver를 실행하는 기능이 있습니다. Zenserver에서 쿠킹된 출력 데이터를 가져올 때, 해당 데이터는 예전과 마찬가지로 집계되고 필요에 따라 압축할 수 있습니다. 즉, 스테이징의 출력은 Zenserver를 쿠킹된 출력 저장소로 활성화하기 전과 똑같이 작동합니다. 따라서 Zenserver를 쿠킹된 출력 저장소로 활성화하기 전과 마찬가지로, Saved/StagedBuilds/<Platform> 디렉터리에는 같은 파일(같은 *.pak, *.utoc, and *.ucas 파일 포함) 안에 같은 데이터가 포함됩니다.
특히, 스테이징된 빌드 디렉터리에는 ue.projectstore 파일이 포함되지 않습니다.
Zenserver를 쿠킹된 출력 저장소로 사용하면서 컨테이너 파일에 스테이징하는 경우, 전반적인 콘텐츠 파이프라인은 다음과 같습니다.
컨테이너 없이 패킹되지 않은 파일에 스테이징하는 경우
Zenserver를 쿠킹된 출력 저장소로 사용하는 경우, 패킹되지 않은 파일에 스테이징하는 동작이 현저하게 달라집니다.
스테이징된 빌드는 쿠킹된 출력 파일을 복사하지 않고 쿠킹된 출력 데이터를 전혀 포함하지 않으므로 스테이징 디렉터리와 타겟 플랫폼의 디플로이된 게임 크기가 크게 줄어듭니다. 대신, 스테이징된 빌드에는 ue.projectstore가 포함되며, 여기에는 쿠킹된 출력 데이터가 포함된 Zenserver에 대한 정보가 담겨 있습니다.
ue.projectstore 파일이 있으면 게임 런타임이 Zenserver에 연결하여 필요에 따라 쿠킹된 데이터를 스트리밍할 수 있습니다. 자세한 내용은 젠 스트리밍 문서를 참조하세요.
Zenserver 스트리밍 사용 시 전반적인 콘텐츠 파이프라인은 다음과 같습니다.