사전 쿠킹
개념

쿠킹

gabury1고친 사람 github-actions[bot]

쿠킹은 게임 엔진이 출시용 게임을 만들 때, 그림과 3D 모델(물체의 입체 모양) 같은 원본 파일을 출시할 기기가 바로 읽는 모양으로 미리 바꿔 두는 단계입니다. 원본은 사람이 고치기 편한 모양이라 게임이 그대로 읽기에는 크고 느립니다. 바꾸는 일은 게임을 만드는 쪽에서 한 번 해 둡니다. 게임은 바뀐 결과만 받습니다.

쉽고 빠른 이해

쿠킹은 게임 원본 파일을 게임용 파일로 미리 바꿔 두는 일입니다. 아티스트가 저장한 벽돌 그림 원본 하나가 PC용 압축 그림과 휴대폰용 압축 그림으로 각각 바뀝니다.

이 일을 게임이 켤 때마다 하면 로딩이 길어집니다. 기기마다 그래픽 카드가 읽을 수 있는 모양도 다릅니다. 그래서 만드는 쪽에서 한 번 바꿔 두고 결과만 내보냅니다.

어떻게 도나:

  1. 게임이 처음 여는 장면에서 출발해 실제로 쓰이는 원본만 고릅니다
  2. 고른 원본을 출시할 기기에 맞는 모양으로 바꿉니다
  3. 바꾼 파일을 실행 파일과 함께 게임 한 벌로 묶는 단계에 넘깁니다

대가는 시간과 용량입니다. 원본이 많으면 바꾸는 데 오래 걸립니다. 기기마다 결과를 한 벌씩 보관해야 합니다. 바뀐 파일은 되돌려 고칠 수 없어서 원본을 늘 남겨 둡니다.

에셋이 적은 작은 게임이나 시제품은 쿠킹 없이 게임이 원본을 바로 읽게 하기도 합니다. 파일과 내는 기기가 늘수록 쿠킹을 두는 쪽으로 옮겨 갑니다.

상세

이 절은 아티스트가 그린 벽돌 그림 한 장과 그 그림을 쓰는 게임 장면 하나를 놓고 쿠킹을 따라갑니다.

식당 주방은 손님이 오기 전에 재료를 손질해 둡니다. 채소를 썰고 육수를 끓여 두면 주문이 들어왔을 때 접시에 담기만 하면 됩니다. 주문을 받고 나서야 장을 보러 가면 음식이 한참 늦게 나갑니다.

쿠킹은 게임에 이 손질을 해 줍니다. 게임에 들어가는 그림·3D 모델·소리 같은 파일을 에셋이라고 합니다. 쿠킹은 에셋을 출시할 기기가 손대지 않고 바로 읽는 모양으로 바꿔 둡니다.

쿠킹이라는 이름은 원본을 날것(raw)에, 바꾼 결과를 익힌 것(cooked)에 빗댔습니다. 날재료를 바로 접시에 올릴 수 없듯이 원본도 게임이 바로 쓰지 못합니다.

부르는 이름은 엔진마다 다릅니다. 언리얼 엔진은 이 단계를 쿡(cook)이라 부릅니다. 이 일을 맡는 프로그램은 쿠커(cooker)입니다. 다른 엔진은 같은 일을 빌드나 변환이라는 이름 아래 합니다.

백엔드 개발에서 가장 닮은 것은 컴파일입니다. 컴파일은 사람이 읽는 소스 코드를 기계가 돌리는 모양으로 미리 바꿉니다. 쿠킹은 같은 일을 코드가 아닌 데이터에 합니다. 실행하는 쪽이 바뀐 결과만 받는다는 점도 같습니다.

원본 에셋과 쿡된 에셋

원본 에셋은 아티스트가 그림 편집 프로그램이나 3D 제작 프로그램으로 저장한 파일입니다. 나중에 다시 고치기 쉽게 만들어져 있습니다. 벽돌 그림 원본에는 벽돌 무늬와 이끼와 그림자가 레이어로 나뉘어 있어서, 이끼만 지우거나 그림자만 옅게 고칠 수 있습니다.

많은 게임 엔진은 원본을 먼저 자기만의 중간 모양으로 바꿔 들여옵니다. 이 단계가 임포트입니다. 중간 모양은 엔진이 다루기 편하게 정리한 모양입니다. 아직 출시할 기기에 맞춘 모양은 아닙니다.

개발하는 동안 이 중간 모양을 읽는 것은 엔진의 편집 도구입니다. 편집 도구는 개발자가 장면을 꾸미고 에셋을 놓아 보는 프로그램입니다. 원본은 아티스트의 제작 프로그램이 읽고, 중간 모양은 편집 도구가 읽는 셈입니다.

쿠킹이 받는 것도 이 중간 모양입니다. 쿠킹은 중간 모양을 출시할 기기가 바로 읽는 모양으로 바꿉니다. 원본에서 보면 임포트가 첫 번째 바꾸기이고 쿠킹이 두 번째 바꾸기입니다.

쿡된 에셋은 출시한 게임이 읽는 파일입니다. 레이어는 하나로 합쳐져 있습니다. 게임은 이 파일을 거의 손대지 않고 메모리에 올립니다. 그래서 로딩이 짧습니다.

쿡된 그림은 GPU(Graphics Processing Unit, 그래픽 처리 장치)가 압축을 풀지 않고 바로 읽는 형식으로 줄여 저장됩니다. GPU 는 화면을 그리는 계산을 맡는 칩입니다. 이 압축은 화질을 조금 버리는 대신 크기를 줄입니다. 방식은 아래 「에셋 종류마다 하는 일」 절에서 봅니다.

원본과 쿡된 에셋을 나란히 놓으면 이렇습니다.

원본 에셋 쿡된 에셋
읽는 쪽 아티스트의 제작 프로그램 출시한 게임
모양 고치기 쉬운 모양 기기가 바로 읽는 모양
몇 벌인가 한 벌로 모든 기기를 덮는다 기기마다 한 벌씩
다시 고치기 된다 안 된다. 원본을 고쳐 다시 쿠킹한다

표의 마지막 줄처럼 쿠킹은 한쪽으로만 갑니다. 압축하며 버린 화질과 합쳐 버린 레이어는 쿡된 파일에서 되살릴 수 없습니다. 원본은 버전 관리 저장소에 계속 남겨 둡니다. 쿡된 파일은 언제든 다시 만들 수 있는 결과물로 다룹니다.

쿠킹 없이 원본을 게임에 넣으면 게임이 켤 때마다 이 바꾸는 일을 해야 합니다. 에셋이 적은 작은 게임이나 시제품은 그렇게 하기도 합니다. 쿠킹 단계를 꾸리는 수고가 조금 긴 로딩보다 크기 때문입니다. 에셋과 내는 기기가 늘수록 쿠킹을 두는 쪽으로 옮겨 갑니다.

에셋 종류마다 하는 일

쿠킹이 에셋에 하는 일은 종류마다 다릅니다. 공통점은 하나입니다. 게임이 실행 중에 할 계산을 미리 해 둡니다.

에셋 쿠킹이 하는 일
텍스처 · 물체 겉면에 입히는 그림 레이어를 합치고 GPU 전용 압축 모양으로 줄인다. 멀리서 볼 때 쓸 작은 그림도 미리 만든다
메시 · 3D 모델의 입체 모양을 이루는 점과 면 꼭짓점 좌표를 GPU 가 바로 읽는 배열로 늘어놓는다
셰이더 · GPU 에서 도는 작은 프로그램 기기가 알아듣는 코드로 컴파일한다
사운드 · 효과음과 배경 음악 기기가 빨리 푸는 압축 방식으로 바꾼다
레벨 · 게임 속 장면 하나 장면에 놓인 물건이 쓰는 에셋 목록을 정리한다

텍스처 줄의 압축은 텍스처 압축이라는 기법입니다. 흔한 그림 파일은 그리기 전에 원래 크기로 다 풀어야 합니다. 텍스처 압축은 GPU 가 줄인 채로 읽게 해 주므로 그래픽 메모리를 덜 씁니다.

대신 압축하는 쪽은 품이 많이 듭니다. 그림을 작은 칸으로 나누어 칸마다 원래 색에 가장 가까운 압축 값을 골라야 합니다. 이 고르는 계산이 오래 걸려서 미리 해 두기에 알맞습니다.

멀리서 볼 때 쓸 작은 그림이 밉맵입니다. 원본 그림을 가로세로 절반씩 줄인 그림을 여러 장 더 만들어 둡니다. 멀리 있는 물체는 작은 그림으로 그려서 계산을 덜고 화면이 지글거리는 것을 막습니다.

셰이더 줄을 보기 전에 게임이 GPU 에 일을 시키는 길부터 봅니다. 게임은 그래픽스 API(Application Programming Interface, 응용 프로그램 인터페이스)라는 함수 묶음을 거쳐 GPU 에 일을 시킵니다. DirectX 12 · Vulkan · Metal 이 그 예이고, 기기와 운영체제마다 쓰는 그래픽스 API 가 다릅니다.

셰이더 줄의 일은 셰이더 컴파일입니다. 같은 셰이더 소스라도 그래픽스 API 가 다르면 다른 코드로 바뀝니다. 이 컴파일을 게임이 도는 중에 하면 화면이 잠깐씩 멈춥니다. 쿠킹이 미리 해 두는 까닭입니다.

쓰이는 에셋만 고르기

프로젝트 폴더에는 게임에 안 들어갈 에셋도 많이 쌓입니다. 시험 삼아 그린 그림, 버린 캐릭터, 예전 판 3D 모델 같은 파일입니다. 이것까지 다 쿠킹하면 시간이 듭니다. 게임 용량도 불어납니다.

쿠킹은 흔히 게임이 처음 여는 레벨에서 출발해 참조를 따라갑니다. 참조는 한 에셋이 다른 에셋을 쓴다고 적어 둔 연결입니다. 레벨은 거기 놓인 캐릭터를, 캐릭터는 자기 메시와 텍스처를 가리킵니다. 이 연결을 끝까지 따라가 닿은 에셋만 쿠킹합니다.

flowchart TD
    L["시작 레벨"] --> C["캐릭터"]
    L --> W["벽돌 벽"]
    C --> CM["캐릭터 메시"]
    C --> CT["캐릭터 텍스처"]
    W --> WT["벽돌 텍스처"]
    X["시험용 그림"]

그림에서 시작 레벨과 거기서 화살표로 닿는 다섯 개가 쿠킹 대상입니다. 어디서도 가리키지 않는 시험용 그림은 쿠킹하지 않습니다. 가비지 컬렉션이 루트에서 닿는 객체만 살려 두는 방식과 닮았습니다.

이 방식에는 함정이 있습니다. 코드가 실행 중에 이름 문자열로 에셋을 찾아 부르면, 그 연결은 참조로 적혀 있지 않습니다. 쿠킹은 그 에셋을 못 보고 빠뜨립니다.

원본이 다 있는 편집 도구에서는 멀쩡하다가 출시용 게임에서만 에셋이 없다는 오류가 납니다. 이런 에셋은 쿠킹 설정에 직접 적어 넣어야 합니다.

기기마다 다른 결과

쿠킹을 시작할 때는 결과를 받을 기기를 정합니다. 이렇게 정한 기기가 대상 플랫폼입니다. 같은 원본이라도 대상 플랫폼이 다르면 다른 결과가 나옵니다.

까닭은 기기마다 GPU 가 읽는 모양이 달라서입니다. 데스크톱 GPU 는 BC(Block Compression) 계열 텍스처 압축을 읽습니다. 휴대폰 GPU 는 주로 ASTC(Adaptive Scalable Texture Compression)나 ETC2(Ericsson Texture Compression 2)를 읽습니다.

셰이더도 기기의 그래픽스 API 마다 한 번씩 컴파일해야 합니다. 메모리가 작은 기기에는 그림을 더 작게 줄여 보내기도 합니다.

원본은 한 벌만 둡니다. 기기별 결과는 쿠킹이 원본에서 다시 만들어 냅니다. 아티스트는 원본만 고치면 됩니다. 기기별 파일을 손으로 맞출 일이 없습니다.

같은 C 소스로 리눅스용과 윈도우용 실행 파일을 하나씩 컴파일하는 크로스 컴파일과 닮았습니다. 소스는 하나이고 결과는 대상마다 나옵니다.

대가는 저장 공간입니다. 내는 기기가 셋이면 쿡된 결과도 세 벌이 생깁니다. 그 세 벌을 모두 보관하고 각각 시험해야 합니다.

미리 하는 쿠킹과 요청받아 하는 쿠킹

출시용 게임은 쓰이는 에셋을 전부 미리 쿠킹합니다. 쿠킹을 다 마친 뒤에 패키징이 이어집니다. 패키징은 쿡된 파일들을 실행 파일과 함께 게임 한 벌로 묶는 단계입니다.

개발 중에는 이 방식이 느립니다. 휴대폰에서 장면 하나를 확인하려고 게임 전체를 쿠킹하면 한참 기다려야 합니다. 이때는 쿠커를 서버처럼 띄워 두고, 기기 위의 게임이 에셋을 요청할 때마다 그것만 쿠킹해 보내는 방식도 씁니다. 언리얼 엔진은 이것을 쿡 온 더 플라이(cook on the fly)라고 부릅니다.

두 방식은 기다리는 때가 다릅니다. 미리 쿠킹하면 처음에 오래 걸리지만 게임을 켠 뒤에는 기다림이 없습니다. 요청받아 쿠킹하면 바로 시작하지만 처음 보는 에셋이 나올 때마다 잠깐씩 멈춥니다.

다시 쿠킹하지 않으려는 장치

에셋이 많은 게임은 처음부터 전부 쿠킹하면 오래 걸립니다. 아티스트가 그림 한 장을 고칠 때마다 전부 다시 쿠킹할 수는 없습니다. 이럴 때 바뀐 것만 다시 쿠킹하는 증분 빌드를 씁니다.

증분 빌드를 하려면 지난 결과가 남아 있어야 합니다. 쿠킹은 지난 결과를 캐시에 넣어 두고 다시 씁니다. 캐시는 한 번 만든 결과를 다시 쓰려고 모아 두는 저장 공간입니다.

무엇이 바뀌었는지는 해시로 가립니다. 원본 파일 내용, 쿠킹 설정, 쿠킹 도구의 버전을 한데 넣어 해시 값 하나를 만듭니다. 입력이 하나라도 바뀌면 이 값도 바뀝니다.

이 해시 값이 캐시 키입니다. 캐시 키는 캐시에 넣은 결과를 다시 찾을 때 쓰는 값입니다. 다음에 같은 키가 나오면 다시 쿠킹하지 않고 캐시에 든 결과를 꺼냅니다.

키에 넣을 입력을 하나라도 빠뜨리면 낡은 결과가 나옵니다. 압축 설정을 바꿨다고 해 봅시다. 그 설정이 키에 없으면 쿠킹은 바뀐 것이 없다고 보아 옛 결과를 내줍니다. 원본에서는 고쳐진 그림이 게임에서는 옛 모습으로 남습니다.

이 캐시를 팀 전체가 나눠 쓰기도 합니다. 한 사람이 쿠킹한 결과를 다른 사람이 받아 쓰면 같은 그림을 여럿이 거듭 쿠킹하지 않습니다. 코드 빌드에서 쓰는 빌드 캐시도 같은 방식입니다.

쿠킹과 헷갈리는 이름

쿠킹은 에셋 파이프라인의 한 단계입니다. 에셋 파이프라인은 원본을 저장하는 데서 게임이 불러오는 데까지 전체 길을 가리킵니다. 쿠킹은 그 가운데 기기별 모양으로 바꾸는 단계를 가리킵니다.

패키징과도 다릅니다. 쿠킹은 에셋 하나하나를 바꿉니다. 패키징은 쿡된 에셋을 큰 아카이브 파일에 이어 붙이고 실행 파일과 함께 게임 한 벌로 묶습니다.

게임 개발에는 베이킹(baking, 굽기)이라는 이웃 낱말도 있습니다. 조명이 물체에 드리우는 밝기처럼 계산이 오래 걸리는 결과를 미리 구해 그림에 담아 두는 일입니다.

미리 계산한다는 점은 쿠킹과 같습니다. 쿠킹은 있는 에셋의 모양을 바꿉니다. 베이킹은 없던 데이터를 새로 계산해 만듭니다.

터미널의 쿡드 모드(cooked mode)는 이름만 닮았습니다. 터미널이 입력을 줄 단위로 모아 지우기 같은 편집을 마친 뒤 프로그램에 넘기는 방식입니다. 정규 모드라고도 합니다. 게임의 쿠킹과는 관계가 없습니다.

관련 항목

쿠킹이 속하는 상위 흐름

게임 개발 · 에셋 파이프라인 · 게임 엔진 · 빌드 · 빌드 파이프라인

쿠킹이 받아서 바꾸는 에셋 종류

에셋 · 텍스처 · 메시 · 3D 모델 · 셰이더 · 사운드 · 레벨 · 애니메이션

쿠킹을 앞뒤로 둔 처리 단계

임포트 · 텍스처 압축 · 밉맵 · 셰이더 컴파일 · 패키징 · 아카이브 · 청킹

쿠킹이 다시 하지 않으려고 쓰는 장치

증분 빌드 · 캐시 · 빌드 캐시 · 캐시 키 · 해시 · 캐시 무효화 · 파생 데이터 캐시

쿠킹 결과를 읽는 실행 환경

대상 플랫폼 · GPU · 그래픽스 API · 에셋 매니저 · 텍스처 스트리밍

쿠킹을 갖춘 게임 엔진

Unreal Engine · Unity · Godot

쿠킹과 닮은 소프트웨어 기법

컴파일 · AOT 컴파일 · JIT 컴파일 · 크로스 컴파일 · 가비지 컬렉션

쿠킹과 헷갈리는 이웃

베이킹 · 라이트맵 · 정규 모드 · 터미널

다른 이름: cooking · 쿡 · cook · 에셋 쿠킹 · 콘텐츠 쿠킹