작성일 :

에셋 시스템을 먼저 이해해야 하는 이유

메모리 관리 (2) - 네이티브 메모리와 에셋에서 텍스처, 메쉬, 오디오 등의 에셋이 네이티브 메모리의 대부분을 차지한다는 점을 다루었고, 렌더링 기초 (2) - 텍스처와 압축에서는 텍스처의 압축 포맷과 메모리 계산 방법을 다루었습니다. 두 글 모두 에셋이 이미 엔진 내부에 로드된 상태를 전제로 설명하고 있습니다.

하지만 같은 PSD 파일이라도 임포트 설정에 따라 4MB 텍스처가 될 수도 있고, 40MB 텍스처가 될 수도 있습니다. 메모리 최적화의 출발점은 에셋이 메모리에 올라가기 전 단계 — 임포트 과정입니다.

프로젝트가 커지면서 에셋이 수백, 수천 개로 늘어나면 임포트 설정의 영향이 누적됩니다. 아티스트가 작업한 4096×4096 PSD 파일이 기본 설정 그대로 임포트되거나, 1분짜리 BGM이 무압축으로 약 10MB의 메모리를 차지하는 상황은 모바일 프로젝트에서 흔히 발생합니다.


Photoshop의 PSD 파일이나 Maya의 FBX 파일은 그 자체로는 Unity 엔진이 직접 사용할 수 없습니다. Asset Import Pipeline은 이 원본 파일을 엔진 내부 포맷으로 변환하고, 변환 결과물을 캐싱하는 전체 과정입니다. 변환 과정에서 어떤 설정을 적용하느냐에 따라 빌드 크기, 메모리 사용량, 로딩 속도가 달라집니다.

이 글에서는 소스 에셋과 임포트 에셋의 차이, Library 폴더의 역할, 텍스처·모델·오디오 각각의 임포트 과정, 그리고 Import Settings가 빌드에 미치는 영향을 살펴봅니다.


소스 에셋 vs 임포트 에셋

Unity 프로젝트의 에셋은 소스 에셋(Source Asset)임포트 에셋(Imported Asset) 두 형태로 관리됩니다. 소스 에셋은 작업 도구가 생성한 원본이고, 임포트 에셋은 그 원본을 엔진이 실제로 사용할 수 있는 포맷으로 변환한 결과물입니다.

소스 에셋은 Photoshop의 PSD, Maya/Blender의 FBX, Audacity의 WAV처럼 작업 도구에서 만든 원본 파일로, Unity 프로젝트의 Assets 폴더에 저장됩니다. 아티스트와 사운드 디자이너가 직접 수정하는 대상이므로 Git 등 버전 관리에 포함합니다.

앞서 살펴본 것처럼 PSD나 FBX는 런타임에서 그대로 사용할 수 없으므로, Unity는 PSD를 ASTC 같은 GPU 압축 텍스처로, FBX를 내부 메쉬 포맷으로 변환합니다. 이렇게 변환된 임포트 에셋이 엔진이 실제로 읽는 데이터입니다. 변환 결과물은 프로젝트의 Library 폴더에 캐싱됩니다.


소스 에셋과 임포트 에셋의 관계 Assets 폴더 (소스 에셋) character.psd character.fbx bgm.wav icon.png ※ 버전 관리 대상 ※ 원본 포맷 유지 Library 폴더 (임포트 에셋) 텍스처 (ASTC 압축) 메쉬 (Unity 포맷) 오디오 (Vorbis 압축) 스프라이트 데이터 ※ 버전 관리에서 제외 ※ 플랫폼별 변환 결과 import import import import


소스 에셋을 Assets 폴더에 넣으면 Unity 에디터가 자동으로 감지하여 임포트를 수행합니다. 이때 적용되는 설정이 에셋의 Import Settings입니다. Import Settings에는 최종 해상도(Max Size), 압축 포맷, 밉맵 생성 여부 등이 포함되며, 이 설정의 조합이 임포트 결과물의 메모리 크기와 품질을 결정합니다.

.meta 파일

소스 에셋마다 .meta 파일이 함께 생성됩니다. .meta 파일에는 해당 에셋의 GUID(Globally Unique Identifier)Import Settings가 저장됩니다. GUID는 프로젝트 전체에서 에셋을 유일하게 식별하는 문자열입니다.


.meta 파일의 역할 Assets/ 폴더 character.psd 소스 에셋 character.psd.meta GUID + Settings enemy.fbx 소스 에셋 enemy.fbx.meta GUID + Settings bgm.wav 소스 에셋 bgm.wav.meta GUID + Settings ※ .meta 파일은 반드시 버전 관리에 포함 ※ 소스 에셋과 항상 쌍으로 존재 .meta 파일 내용 guid: a1b2c3d4e5f6... 고유 식별자 TextureImporter: Import Settings maxTextureSize: 1024 textureCompression: 2 ... ※ Import Settings → 빌드 크기·메모리 결정


Unity는 에셋 간 참조를 파일 경로가 아니라 GUID로 관리합니다. 예를 들어 머티리얼이 텍스처를 참조할 때, 내부적으로는 텍스처의 GUID를 기록합니다. 파일 이름이나 경로를 변경해도 GUID가 유지되면 참조가 깨지지 않습니다.

반대로, .meta 파일을 삭제하면 Unity가 새로운 GUID를 생성하므로 기존 참조가 모두 깨집니다. 에셋을 이동하거나 이름을 변경할 때는 반드시 Unity 에디터 안에서(Project 창에서) 수행해야 .meta 파일이 함께 갱신됩니다. OS의 파일 탐색기에서 직접 옮기면 .meta 파일이 분리될 수 있습니다. .meta 파일은 반드시 버전 관리에 포함해야 합니다.


Library 폴더 — 임포트 캐시

Library 폴더는 임포트 결과물이 저장되는 로컬 캐시입니다. Unity가 소스 에셋을 임포트할 때마다 변환 결과가 이 폴더에 기록됩니다.


Library 폴더의 구조 ProjectRoot/ Assets/ 소스 에셋 · 버전 관리 O Library/ 임포트 캐시 · 버전 관리 X Artifacts/ 임포트 결과물 (변환된 에셋 데이터) ArtifactDB 임포트 결과 데이터베이스 SourceAssetDB 소스 에셋 정보 데이터베이스 Packages/ ProjectSettings/


Library 폴더는 재생성이 가능합니다. Library 폴더를 삭제해도 Unity 에디터를 다시 열면 Assets 폴더의 소스 에셋과 .meta 파일을 기반으로 전체 임포트를 다시 수행합니다. 다만 프로젝트 규모에 따라 수 분에서 수십 분이 소요될 수 있습니다. 팀 환경에서는 Unity Accelerator(캐시 서버)로 이 재임포트 비용을 줄일 수 있습니다. Unity Accelerator는 팀원이 이미 생성한 임포트 결과물을 네트워크로 공유하여, 다른 팀원이 같은 에셋을 처음부터 임포트하지 않아도 되게 합니다.

이처럼 재생성이 가능하므로 Library 폴더는 버전 관리에서 제외합니다. .gitignoreLibrary/를 추가하는 것이 표준적인 관행입니다.

Library 폴더에는 플랫폼별 변환 결과가 저장됩니다. Android 플랫폼으로 전환하면 텍스처가 ASTC(Adaptive Scalable Texture Compression)나 ETC2(Ericsson Texture Compression 2) 같은 GPU 압축 포맷으로 변환되고, iOS 플랫폼으로 전환하면 ASTC로 변환됩니다. 플랫폼을 전환할 때마다 임포트 캐시가 갱신되며, 플랫폼 전환(Switch Platform)에 시간이 오래 걸리는 것은 이 재변환 때문입니다.

Artifact 구조와 Asset Pipeline v2

Artifact는 하나의 소스 에셋을 특정 Import Settings·Unity 버전·플랫폼 조합으로 임포트한 결과물입니다. 소스 에셋의 GUID, Import Settings, Unity 버전, 플랫폼 — 이 네 조건 중 하나라도 바뀌면 해당 Artifact가 다시 생성됩니다.


Artifact 생성 조건 소스 에셋 (GUID) Import Settings 플랫폼 Unity 버전 + + + Artifact (임포트 결과) ※ 위 조건 중 하나라도 바뀌면 Artifact 재생성


Unity 2019.3부터 도입된 Asset Pipeline v2는 이 Artifact 시스템을 개선하여, 변경된 에셋만 선택적으로 재임포트하고 임포트 결과를 결정론적(deterministic)으로 생성합니다. 소스 에셋과 Import Settings가 동일하면 어느 컴퓨터에서든 항상 같은 임포트 결과가 나오므로, 팀원들이 각자의 로컬 Library 폴더에서 독립적으로 임포트하더라도 동일한 빌드를 생성할 수 있습니다.


텍스처 임포트

텍스처는 Unity 프로젝트에서 가장 큰 용량을 차지하는 에셋 유형입니다. 임포트 과정에서 적용하는 설정이 메모리와 빌드 크기에 직접적인 영향을 미칩니다.

소스 포맷에서 엔진 포맷으로

PNG, PSD, TGA, EXR 등의 소스 파일은 임포트 과정에서 플랫폼별 GPU 압축 포맷으로 변환됩니다.


텍스처 임포트 과정 소스 파일 PNG (24bit) PSD (32bit) TGA (32bit) EXR (HDR) Import 플랫폼별 결과 Android: ASTC 6x6 iOS: ASTC 4x4 PC: BC7 Console: 플랫폼별 포맷 Import Settings에 따라 결정 Max Size · 압축 포맷 · Mipmap 생성 여부 sRGB / Linear · Read/Write Enabled


소스 파일의 포맷(PNG인지 PSD인지)은 임포트 결과에 영향을 주지 않습니다. Unity는 소스 파일에서 픽셀 데이터만 읽어 Import Settings에 따라 변환하며, PSD 파일의 레이어 구조처럼 픽셀 데이터 외의 정보는 무시합니다. 따라서 소스 파일의 포맷은 아티스트의 작업 편의성에 맞추면 됩니다.

텍스처 유형 설정

Import Settings의 Texture Type은 Unity가 텍스처를 어떤 용도로 사용할지 지정합니다. Texture Type에 따라 sRGB 감마 보정 적용 여부, 압축 포맷 선택, 픽셀 값의 해석 방식이 달라집니다.


주요 Texture Type

Texture Type 특성
Default 일반 색상 텍스처. Diffuse, Albedo, Emission 등에 사용. sRGB 감마 보정 기본 적용.
Normal Map 법선 맵 전용. 픽셀 값을 방향 벡터로 해석. sRGB 끔. 압축 시 전용 포맷 사용.
Sprite (2D/UI) 2D 스프라이트 및 UI용. Sprite Editor에서 슬라이싱 가능. 아틀라스 패킹 대상.
Single Channel 마스크, 하이트맵 등 1채널 데이터 전용. R 또는 Alpha 채널만 사용하여 메모리 절약.

이 밖에 Cursor(커서 이미지), Cookie(라이트 쿠키), Lightmap(HDR 인코딩 라이트맵) 등 특수 용도 타입이 있습니다.


Texture Type을 잘못 설정하면 렌더링이 왜곡되거나 메모리가 낭비됩니다. Normal Map용 텍스처를 Default로 임포트하면 sRGB 감마 보정이 적용되어, 방향 벡터로 해석해야 할 수치 데이터에 감마 디코딩이 가해지므로 법선 방향이 왜곡됩니다. 마스크 텍스처에 Single Channel 대신 Default를 사용하면 불필요한 RGB 채널까지 저장되어 메모리가 낭비됩니다. UI 텍스처는 Sprite (2D/UI) 타입으로 지정해야 슬라이싱과 아틀라스 패킹을 사용할 수 있습니다.

Max Size — 메모리와 품질의 핵심 설정

Max Size는 임포트 결과 텍스처의 최대 해상도를 제한합니다. 소스 파일이 4096x4096이더라도 Max Size를 1024로 설정하면, 임포트 결과는 1024x1024가 됩니다.


Max Size에 따른 메모리 변화 (ASTC 6x6 기준, 밉맵 포함, 소스: 4096 x 4096)

Max Size 해상도 메모리 (약)
4096 4096 x 4096 9.5 MB
2048 2048 x 2048 2.37 MB
1024 1024 x 1024 0.59 MB
512 512 x 512 0.15 MB
256 256 x 256 0.04 MB

Max Size를 한 단계 낮출 때마다 가로·세로 해상도가 각각 절반이 되어 전체 픽셀 수가 1/4로 줄고, 메모리도 약 1/4로 감소합니다.


모바일 프로젝트에서는 텍스처의 시각적 중요도에 따라 Max Size를 다르게 설정합니다. 화면에 크게 보이는 캐릭터 텍스처는 2048, 먼 배경 오브젝트는 512, UI 아이콘은 256과 같은 식으로 차등 적용합니다. Max Size를 시각적 중요도에 맞게 차등 관리하면 텍스처 메모리를 크게 줄일 수 있습니다.

sRGB vs Linear

사람의 눈은 어두운 영역의 밝기 변화에 민감한 반면, 밝은 영역에서는 둔감합니다. 8비트(256단계)로 밝기를 표현할 때, 이 단계를 물리적 밝기에 균등하게 대응시키면 눈이 민감한 어두운 영역에서 단계 간 차이가 두드러져 색 띠(banding)가 나타납니다. sRGB는 어두운 영역에 더 많은 단계를 할당하는 비선형 변환(감마 인코딩)을 적용하여 이 문제를 줄이는 색상 공간이며, 디지털 이미지 대부분이 이 방식으로 저장됩니다.


sRGB가 저장에 효율적인 반면, 셰이더의 조명 연산은 선형(Linear) 공간에서 수행해야 합니다. 물리 세계에서 빛의 세기는 선형적으로 합산되므로, 감마 인코딩된 값으로 조명을 계산하면 결과가 왜곡됩니다. sRGB를 켜면 GPU가 텍스처 샘플링 시 감마 인코딩된 값을 선형 공간으로 자동 변환하여 셰이더에 전달합니다.

색상 정보를 담는 텍스처(Diffuse, Albedo)는 감마 인코딩된 상태로 저장되어 있으므로, sRGB를 켜서 선형 공간으로 변환한 뒤 셰이더에 전달해야 합니다. 수치 데이터를 담는 텍스처(Normal Map, Mask, Height Map)는 sRGB를 꺼야 합니다. 이 텍스처들은 색상이 아니라 방향 벡터나 높이 같은 수치를 저장하고 있으므로, 감마 디코딩을 적용하면 값이 왜곡됩니다.

Read/Write Enabled의 비용

Read/Write Enabled를 켜면 텍스처 데이터를 CPU에서 읽고 쓸 수 있게 됩니다. Texture2D.GetPixel(), Texture2D.SetPixel() 같은 API를 사용하려면 이 옵션이 필요합니다.


Read/Write Enabled의 메모리 영향 Read/Write 꺼짐 GPU 메모리에만 존재 텍스처 1장 분량 Read/Write 켜짐 GPU 메모리 (렌더링) CPU 메모리 (사본) 메모리 사용량이 2배


Read/Write Enabled가 켜져 있으면, Unity는 GPU에 업로드한 텍스처 데이터의 사본을 CPU 메모리에도 유지합니다. 2048x2048 RGBA32 텍스처라면 16MB가 GPU와 CPU에 각각 올라가 총 32MB를 차지합니다. CPU에서 텍스처 픽셀을 읽거나 수정할 필요가 없다면, 반드시 이 옵션을 꺼야 합니다.

Mipmap 생성

Generate Mip Maps를 켜면 원본 텍스처를 절반씩 축소한 여러 단계의 이미지 체인이 생성됩니다. 밉맵(Mipmap)의 MIP는 라틴어 “multum in parvo(작은 공간에 많은 것)”의 약자입니다.


밉맵 체인 1024×1024 Level 0 (원본) 512×512 Level 1 Level 2 Level N 밉맵을 포함하면 메모리가 약 33% 증가 (1 + 1/4 + 1/16 + 1/64 + … ≈ 1.33배)


3D 오브젝트에 사용하는 텍스처에는 밉맵을 켜는 것이 일반적입니다. 카메라에서 멀리 있는 오브젝트는 화면에서 작은 영역을 차지합니다. 예를 들어 1024×1024 텍스처가 화면에서 4×4 픽셀로 표시되는 경우, 밉맵이 없으면 GPU는 원본의 약 100만 텍셀(texel, 텍스처를 구성하는 개별 픽셀)을 읽어 단 16픽셀로 축소해야 하므로 메모리 대역폭이 낭비됩니다. 밉맵이 있으면 GPU가 화면 크기에 맞는 축소된 밉 레벨을 선택하여 읽어야 할 데이터량을 줄입니다.

밉맵은 앨리어싱 방지에도 필요합니다. 원본 텍스처에 체크무늬나 격자처럼 픽셀이 빠르게 바뀌는 세밀한 패턴(고주파 디테일)이 포함되어 있을 때, 이를 극단적으로 축소하면서 필터링하지 않으면 화면에서 깜빡임(aliasing)이 발생합니다. 밉맵은 각 레벨을 미리 다운샘플링하여 고주파 성분을 사전에 걸러내므로 깜빡임이 줄어듭니다.

UI 텍스처에는 밉맵을 끄는 것이 원칙입니다. UI 요소는 항상 고정된 크기로 렌더링되므로 축소된 밉 레벨이 필요 없고, 밉맵 분량만큼 메모리가 낭비됩니다.


3D 오브젝트 텍스처에서 밉맵을 켜면 메모리가 33% 증가하지만, Unity 2018.2부터 도입된 Texture Streaming(Mipmap Streaming)을 활용하면 이 비용을 줄일 수 있습니다. Texture Streaming은 카메라와의 거리에 따라 필요한 밉 레벨만 메모리에 올리고, 불필요한 고해상도 밉 레벨은 내리는 기능입니다.

Quality Settings의 Texture Streaming 항목에서 기능을 활성화한 뒤, 텍스처 Import Settings의 Streaming Mipmaps 체크박스를 개별 텍스처마다 켜야 적용됩니다. 메모리 예산(Memory Budget)을 설정하면 Unity가 전체 텍스처의 밉 레벨을 예산 내에서 자동 조절합니다. 3D 오브젝트 텍스처가 많은 프로젝트에서는 밉맵의 렌더링 이점을 유지하면서 메모리 비용을 줄일 수 있습니다.


모델 임포트

메쉬 데이터는 텍스처와 함께 3D 게임의 시각적 기반을 이룹니다. FBX, OBJ 같은 3D 모델 파일은 임포트 과정에서 Unity의 내부 메쉬 포맷으로 변환됩니다.

좌표축 변환과 Scale Factor

3D 작업 도구마다 좌표 체계가 다릅니다. Maya는 오른손 좌표계, Y-up에 센티미터 단위를 사용하고, Blender는 오른손 좌표계, Z-up에 미터 단위, 3ds Max는 오른손 좌표계, Z-up에 인치 또는 센티미터 단위를 사용합니다. Unity는 왼손 좌표계, Y-up에 미터 단위를 사용합니다.


좌표계 차이 Maya (오른손, Y-up) Y X Z (화면 밖으로) Unity (왼손, Y-up) Y X Z (화면 안으로) 임포트 시 좌표축 변환 자동 수행 · Scale Factor로 단위 변환 (FBX의 기본값: 0.01)


FBX 파일의 기본 단위는 센티미터이므로, Unity는 기본 Scale Factor 0.01을 적용하여 미터 단위로 변환합니다. Maya에서 키가 180인 캐릭터를 만들었다면(180cm), Unity에서는 1.8 유닛(1.8m)이 됩니다. Scale Factor를 잘못 설정하면 오브젝트가 100배 크거나 작게 보이는 문제가 발생합니다.

Mesh Compression

Mesh Compression 옵션은 메쉬 데이터를 빌드 파일에 저장할 때의 압축 수준을 설정합니다. Off, Low, Medium, High 네 단계로 나뉘며, 압축 수준이 높을수록 빌드 파일 크기가 줄어듭니다.

다만 압축 수준이 높아지면 정점 좌표의 양자화(quantization) 정밀도가 낮아집니다. 양자화는 연속적인 좌표 값(예: 0.123456)을 제한된 수의 이산 값(예: 0.12)으로 근사하는 처리이며, 이산 값의 간격이 넓을수록 정점 위치가 원래 좌표에서 크게 벗어납니다. 크기가 작은 오브젝트나 정밀한 형태가 중요한 오브젝트에서는 시각적 아티팩트(메쉬 표면이 울퉁불퉁해지거나 가장자리가 어긋나는 현상)가 나타날 수 있으므로, 압축 적용 후 반드시 시각적 변화를 확인합니다.


Mesh Compression의 영향 범위 줄이는 것 디스크(빌드 파일)에서의 크기 빌드 용량 절감 줄이지 않는 것 런타임 메모리 사용량 로드 시 압축 해제하여 원본 크기로 메모리에 배치


런타임 메모리를 줄이려면 정점 수 자체를 줄이거나 LOD(Level of Detail)를 적용해야 합니다. LOD를 적용하면 카메라와의 거리에 따라 정점 수가 적은 간략화된 메쉬로 자동 교체되므로, 먼 오브젝트에 고해상도 메쉬를 사용하는 낭비를 방지할 수 있습니다.

Read/Write Enabled (메쉬)

텍스처와 마찬가지로, 메쉬에도 Read/Write Enabled 옵션이 있습니다. 이 옵션이 켜져 있으면 메쉬 데이터의 사본이 CPU 메모리에 유지되어 메모리 사용량이 2배가 됩니다. 런타임에 메쉬 정점을 수정하거나(예: 절차적 지형 생성, 피격 시 메쉬 변형), Mesh.vertices로 정점 데이터를 읽어야 하는 경우에만 이 옵션을 켭니다. 대부분의 정적 메쉬(배경, 건물, 소품 등)는 런타임 수정이 필요하지 않으므로 반드시 꺼야 합니다.

Optimize Mesh

Optimize Mesh 옵션은 정점(Vertex)과 인덱스(Index)의 순서를 재정렬하여 GPU 캐시 효율을 높입니다.

메쉬는 정점 목록(Vertex Buffer)과 각 삼각형이 어느 정점을 사용하는지 기록한 인덱스 목록(Index Buffer)으로 구성됩니다. 여러 삼각형이 같은 정점을 공유하기 때문에, 같은 정점이 여러 삼각형의 인덱스에서 반복 참조됩니다.

GPU는 정점 셰이더에서 정점을 순차적으로 처리하며, 이미 처리한 정점 결과를 재사용하기 위해 post-transform cache라는 내부 버퍼를 유지합니다. 이 버퍼에 결과가 남아 있으면 같은 정점을 다시 처리하지 않아도 됩니다. 하지만 삼각형을 구성하는 정점들이 메모리상에서 멀리 떨어져 있으면 버퍼에서 결과를 찾지 못해 캐시 누락이 빈번해집니다.

Optimize Mesh를 켜면 Unity가 임포트 시점에 정점 순서를 재배열하여, 공간적으로 가까운 정점이 메모리에서도 인접하게 배치됩니다. 캐시 히트율이 높아져 렌더링 성능이 향상되며, 임포트 시에만 처리 비용이 발생할 뿐 런타임 비용은 없습니다.

다만 정점 인덱스가 재배열되므로, Read/Write Enabled를 켜고 런타임에 Mesh.vertices[i]처럼 특정 인덱스로 정점에 접근하는 코드가 있다면 원본 모델과 인덱스 순서가 달라질 수 있습니다. 이런 경우가 아니라면 항상 켜 둡니다.

Animation 임포트

FBX 파일에 애니메이션 데이터가 포함되어 있으면, Import Settings에 Rig 탭과 Animation 탭이 나타납니다.


Animation 임포트 설정 Rig 탭 Animation Type None 애니메이션 사용 안 함 Legacy 구버전 시스템 (비권장) Generic 범용 — 프롭, 동물, 메카닉 등에 적합 Humanoid 인간형 리깅 — 리타겟팅 가능 Animation 탭 Clip 분리 하나의 FBX에 포함된 연속 애니메이션을 시작/종료 프레임으로 잘라서 개별 Clip으로 분리 예: Idle (0~30) Walk (31~60) Run (61~90)


Humanoid 타입은 Unity의 Avatar 시스템을 사용합니다. Avatar 시스템은 인간형 캐릭터의 뼈대 구조를 Unity 내부의 표준 뼈대에 매핑합니다. 이 매핑 덕분에 한 캐릭터용으로 제작된 애니메이션을 다른 캐릭터에게 적용하는 리타겟팅(Retargeting)이 가능해집니다. 예를 들어 주인공의 걷기 애니메이션을 NPC에게도 그대로 적용할 수 있습니다.

다만 런타임에 표준 뼈대의 포즈를 캐릭터 고유 뼈대로 변환하는 연산이 매 프레임 발생하여, Generic 대비 CPU 비용이 높습니다. Generic 타입은 리타겟팅이 불가능하지만 매핑 과정이 없어 처리 비용이 낮습니다. 인간형 캐릭터가 아닌 오브젝트(문, 차량, 소품 등)에는 Generic을 사용합니다.


오디오 임포트

텍스처와 모델이 시각적 에셋이라면, 오디오는 청각적 에셋에 해당합니다. 오디오 에셋은 임포트 설정에 따라 메모리 사용량과 CPU 디코딩 비용이 크게 달라집니다. 메모리를 아끼려면 압축률을 높여야 하지만, 그만큼 재생 시 CPU 디코딩 부하가 늘어나므로 코덱과 Load Type 선택이 중요합니다.

소스 포맷과 코덱 변환

WAV, MP3, OGG 등의 소스 파일은 임포트 과정에서 Import Settings에서 선택한 코덱으로 변환됩니다.


오디오 임포트 과정 WAV (PCM) MP3 OGG Import Vorbis 손실 압축, 품질 조절 가능 ADPCM 중간 압축, 빠른 디코딩 PCM 무압축, 최고 품질 ※ 소스 포맷과 무관하게, 임포트 후 코덱은 Import Settings로 결정


Unity에서 사용하는 주요 코덱은 세 가지입니다. Vorbis는 손실 압축 코덱으로, 높은 압축률에서도 음질 열화가 적어 배경 음악과 긴 효과음에 폭넓게 사용됩니다. ADPCM(Adaptive Differential PCM)은 16비트 샘플을 4비트로 인코딩하여 원본 대비 약 3.5~4배 압축하면서도 디코딩 속도가 빠릅니다. 빈번하게 재생되는 짧은 효과음에 적합합니다. PCM은 무압축 원본 그대로이며, 음질 손실이 없는 대신 파일 크기가 커서 제한적으로 사용합니다.

소스 파일로는 무손실 WAV를 사용하는 것이 일반적입니다. MP3를 소스로 사용하면, MP3의 손실 압축으로 이미 품질이 떨어진 데이터에 Unity가 Vorbis 등의 손실 압축을 다시 적용하므로 품질이 이중으로 저하됩니다.

Load Type — 메모리와 CPU의 트레이드오프

오디오의 Load Type은 런타임에서 오디오 데이터를 어떻게 메모리에 올리는지 결정합니다.


Load Type 비교

Load Type 메모리 CPU 비용 지연시간
Decompress On Load (로드 시 전부 압축 해제) 높음 (PCM 크기) 낮음 (재생 즉시) 로딩 시 큼
Compressed In Memory (압축 상태로 메모리 보관) 낮음 (압축 크기) 중간 (실시간 디코딩) 재생 시 약간
Streaming (디스크에서 실시간 읽기) 최소 (버퍼만) 높음 (디스크 + 디코딩) 재생 시 약간


Decompress On Load는 오디오를 메모리에 로드하는 시점에 전체를 PCM(Pulse Code Modulation)으로 압축 해제합니다. PCM은 오디오 파형을 그대로 샘플 값으로 저장한 무압축 형태입니다. 재생 시 CPU가 디코딩할 필요가 없어 지연이 없지만, 비압축 PCM 크기만큼 메모리를 차지합니다. 1분짜리 스테레오 44.1kHz 16비트 오디오 기준으로 약 10MB입니다(44,100 x 2채널 x 2바이트 x 60초). 짧은 효과음(발소리, 타격음, 버튼 클릭 등)에 적합합니다.

Compressed In Memory는 압축된 상태로 메모리에 보관하고, 재생 시 실시간으로 디코딩합니다. 메모리를 절약하지만, 재생할 때마다 CPU에서 디코딩 연산이 발생하며, 동시에 재생되는 사운드가 많으면 CPU 부하도 높아집니다. 중간 길이의 음성(대사, 내레이션)이나 자주 재생되지 않는 효과음에 적합합니다.

Streaming은 오디오 데이터를 메모리에 올리지 않고, 재생 시점에 디스크에서 조금씩 읽어옵니다. 메모리 사용량이 가장 적지만(작은 버퍼만 사용), 디스크 I/O와 CPU 디코딩 비용이 모두 발생합니다. 동시에 스트리밍하는 오디오 수가 늘어나면 디스크 I/O 경합이 심해지므로, 모바일에서는 동시 스트리밍 수를 1~2개로 제한하는 것이 일반적입니다. BGM이나 환경음처럼 긴 오디오에 사용합니다.

Preload Audio Data

Preload Audio Data를 켜면, 오디오가 포함된 씬이 로드될 때 오디오 데이터도 함께 로드됩니다. 끄면 첫 재생 시점에 로드되며, 그때 로딩 지연이 발생할 수 있습니다. 즉시 재생해야 하는 효과음은 Preload를 켭니다. 나중에 재생되는 BGM이나 컷씬 음성은 꺼서 초기 로딩 시간을 줄입니다.

모바일에서의 권장 설정

모바일 환경에서는 메모리와 CPU 모두 제한적이므로, 오디오 유형별로 Load Type과 코덱을 다르게 적용합니다.


모바일 오디오 권장 설정

오디오 유형 Load Type 코덱
짧은 효과음 (< 1초) Decompress On Load ADPCM 또는 PCM
중간 효과음/음성 (1~10초) Compressed In Memory Vorbis (Quality 70%)
BGM/환경음 (> 10초) Streaming Vorbis (Quality 50~70%)

Load Type과 코덱 외에 두 가지 설정을 추가로 조정합니다. Force Mono를 켜면 스테레오 오디오가 모노로 변환되어 채널 수가 절반이 되므로 메모리도 절반으로 줄어듭니다. 모바일 스피커에서는 스테레오 효과가 미미한 효과음이 많아, 이런 효과음에 적용하면 효과적입니다. Sample Rate를 44,100Hz에서 22,050Hz로 낮추면 초당 샘플 수가 절반이 되어 데이터량도 절반으로 줄어듭니다. 짧은 효과음에는 22,050Hz로 충분한 경우가 많습니다. 다만 BGM처럼 품질이 중요한 오디오에는 원본 스테레오와 44,100Hz를 유지합니다.


Import Settings가 빌드 크기와 메모리에 미치는 영향

텍스처, 모델, 오디오의 Import Settings는 빌드 결과물과 런타임 메모리에 직접적인 차이를 만듭니다. 이 중 텍스처는 에셋 유형 중 빌드 크기와 런타임 메모리 비중이 가장 큽니다. 원본 이미지 데이터 자체가 크기 때문에, 같은 해상도라도 압축 포맷 설정 하나로 메모리 사용량이 수 배씩 달라집니다. 일반적인 모바일 게임에서 텍스처가 빌드 크기의 50~70%를 차지하는 경우가 흔하며, Import Settings의 작은 차이 하나가 수십 MB의 빌드 크기 변화로 이어질 수 있습니다.

텍스처 압축 포맷 비교

같은 텍스처라도 압축 포맷에 따라 메모리 사용량이 크게 달라집니다. 포맷별 메모리를 비교할 때 기준이 되는 수치는 bpp(bits per pixel), 한 픽셀당 차지하는 비트 수입니다.


ASTC 포맷의 숫자(4x4, 6x6, 8x8)는 하나의 압축 블록이 커버하는 픽셀 영역을 뜻합니다. 블록 크기와 관계없이 하나의 블록은 항상 128비트(16바이트)로 인코딩되므로, 4x4 블록은 16픽셀을 128비트로, 6x6 블록은 36픽셀을 같은 128비트로 표현합니다. 블록이 클수록 같은 128비트로 더 많은 픽셀을 커버하여 bpp가 낮아지고 용량이 줄지만, 블록 안에서 표현할 수 있는 색상 정보가 제한되어 품질은 떨어집니다.

2048x2048 텍스처 한 장을 기준으로 포맷별 메모리를 비교하면 다음과 같습니다.

2048 x 2048 텍스처 — 포맷별 메모리 비교

포맷 bpp 메모리 (밉맵 제외) 메모리 (밉맵 포함)
RGBA32 32 16 MB 21.3 MB
RGBA16 16 8 MB 10.6 MB
BC7 (PC) 8 4 MB 5.3 MB
ASTC 4x4 8 4 MB 5.3 MB
ASTC 6x6 3.56 1.78 MB 2.37 MB
ASTC 8x8 2 1 MB 1.33 MB
ETC2 (RGB / RGBA) 4 / 8 2 / 4 MB 2.7 / 5.3 MB

ETC2는 알파 채널 유무에 따라 bpp가 달라집니다. RGB만 사용하면 4bpp, 알파 채널을 포함하면 8bpp입니다. RGBA32 대비 ASTC 6x6는 약 1/9 크기이며, 어떤 포맷이든 밉맵을 켜면 메모리가 약 33% 추가됩니다.


2048x2048 텍스처 100장이 있는 프로젝트에서 모두 RGBA32를 사용하면 밉맵 제외 기준으로 약 1.6GB가 필요하지만, ASTC 6x6으로 변환하면 약 178MB로 줄어듭니다. 모바일 기기에서 이 차이는 앱이 정상 실행되느냐, OOM(Out Of Memory)으로 강제 종료되느냐를 가를 수 있습니다.

Max Size와 밉맵 유무의 영향

2048x2048 ASTC 6x6 텍스처 한 장을 기준으로, Max Size와 밉맵 설정에 따른 메모리 변화입니다.


Max Size와 밉맵 조합별 메모리 (ASTC 6x6 기준)

Max Size 밉맵 OFF 밉맵 ON
2048 1.78 MB 2.37 MB
1024 0.44 MB 0.59 MB
512 0.11 MB 0.15 MB
256 0.03 MB 0.04 MB

Max Size를 2048에서 1024로 낮추면 해상도가 가로·세로 각각 절반이 되어 픽셀 수가 1/4로 줄고, 메모리가 약 75% 감소합니다.


텍스처 최적화에서 가장 효과적인 두 가지 수단은 압축 포맷Max Size입니다. 밉맵은 메모리를 약 33% 더 소비하지만, 3D 오브젝트처럼 카메라 거리에 따라 크기가 변하는 텍스처에서 밉맵을 끄면 오히려 계단 현상(앨리어싱)이 발생합니다. 반면, UI처럼 화면 고정 크기로 표시되는 텍스처는 밉맵이 불필요하므로 끄는 것이 맞습니다. 프로젝트의 텍스처 목록을 메모리 소비 순으로 정렬하고, 상위 항목부터 포맷과 Max Size를 점검하면 적은 작업으로 큰 절약 효과를 얻습니다.


AssetPostprocessor

앞에서 본 Import Settings의 효과를 알고 있어도, 에셋마다 수동으로 설정하면 번거롭고 실수가 발생하기 쉽습니다. 팀 프로젝트에서는 팀원마다 설정이 달라지는 문제도 생깁니다. Unity는 이 문제를 해결하기 위해 AssetPostprocessor를 제공합니다.

AssetPostprocessor는 에셋이 임포트될 때 자동으로 실행되는 콜백을 정의하는 클래스입니다. OnPreprocessTexture, OnPreprocessModel, OnPreprocessAudio 같은 메서드를 오버라이드하면, 임포트 직전에 설정을 코드로 강제할 수 있습니다. 임포트 엔진이 변환을 마친 뒤에는 OnPostprocessTexture, OnPostprocessModel 등의 후처리 콜백도 호출되므로, 변환 결과를 검증하거나 추가 가공하는 것도 가능합니다.


AssetPostprocessor 동작 흐름 에셋 임포트 시작 OnPreprocessXXX 호출 Import Settings를 코드로 설정 Unity 임포트 엔진이 변환 수행 OnPostprocessXXX 호출 임포트 결과를 후처리 임포트 완료, Library에 캐싱


다음은 팀 단위로 임포트 규칙을 강제하는 예시입니다. 특정 폴더에 있는 텍스처에 자동으로 Max Size와 압축 포맷을 적용합니다.

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
using UnityEditor;
using UnityEngine;

public class TextureImportRule : AssetPostprocessor
{
    void OnPreprocessTexture()
    {
        var importer = (TextureImporter)assetImporter;

        if (assetPath.Contains("Assets/Art/UI/"))
        {
            importer.maxTextureSize = 512;
            importer.textureCompression = TextureImporterCompression.Compressed;
            importer.mipmapEnabled = false; // UI는 밉맵 불필요
        }
        else if (assetPath.Contains("Assets/Art/Characters/"))
        {
            importer.maxTextureSize = 1024;
            importer.textureCompression = TextureImporterCompression.Compressed;
            importer.mipmapEnabled = true;
        }
        else if (assetPath.Contains("Assets/Art/Background/"))
        {
            importer.maxTextureSize = 512;
            importer.textureCompression = TextureImporterCompression.Compressed;
            importer.mipmapEnabled = true;
        }
    }
}


이 스크립트는 Editor 폴더에 넣어야 합니다. AssetPostprocessor는 에디터 전용 기능이므로, Editor 폴더 바깥에 두면 빌드에 포함되어 컴파일 오류가 발생합니다. Editor 폴더에 넣으면 해당 폴더에 텍스처를 추가하거나 재임포트할 때마다 자동으로 규칙이 적용되며, 아티스트가 Import Settings를 직접 건드리지 않아도 폴더 구조에 따라 일관된 설정이 보장됩니다.


AssetPostprocessor는 텍스처뿐 아니라 모델, 오디오 등 모든 에셋 유형에 대해 콜백을 제공합니다. 모델에 대해 Read/Write Enabled를 강제로 끄거나, 오디오에 대해 Load Type을 자동 설정하는 것도 가능합니다. 여러 AssetPostprocessor 스크립트가 존재할 때는 GetPostprocessOrder() 메서드를 오버라이드하여 실행 순서를 제어할 수 있습니다.


마무리

  • Asset Import Pipeline은 소스 에셋을 엔진 내부 포맷으로 변환하며, Import Settings가 빌드 크기와 런타임 메모리를 결정합니다.
  • Library 폴더는 재생성 가능하므로 버전 관리에서 제외하고, .meta 파일은 GUID를 보관하므로 반드시 포함해야 합니다. .meta 파일 삭제 시 GUID가 바뀌어 모든 참조가 깨집니다.
  • 텍스처에서는 압축 포맷과 Max Size가 메모리에 가장 큰 영향을 미치며, Read/Write Enabled는 메모리를 2배로 만듭니다.
  • 모델에서는 Mesh Compression이 런타임 메모리에 효과가 없다는 점, Optimize Mesh를 항상 켜야 한다는 점을 점검합니다. Animation Type은 용도에 맞게 Generic 또는 Humanoid를 선택합니다.
  • 오디오는 Load Type에 따라 메모리-CPU 트레이드오프가 발생합니다. 짧은 효과음은 Decompress On Load, 중간 음성은 Compressed In Memory, BGM은 Streaming이 기본 기준입니다.
  • AssetPostprocessor를 활용하면 Import Settings를 코드로 강제하여, 팀 단위의 일관된 설정을 자동으로 보장할 수 있습니다.

에셋 임포트의 모든 설정은 빌드 크기, 메모리 사용량, 품질 사이의 균형점을 결정합니다. 팀 규모가 커질수록 이 균형점을 수동으로 유지하기 어려우므로, AssetPostprocessor를 통한 자동화의 가치도 커집니다.


이 글에서는 소스 에셋이 임포트 에셋으로 변환되는 과정과, Import Settings가 빌드 크기와 메모리에 미치는 영향을 살펴봤습니다. 임포트된 에셋은 디스크에 직렬화(Serialization)되어 저장되고, 런타임에 역직렬화되어 메모리에 올라갑니다. 이 직렬화-역직렬화 과정은 에셋의 로딩 속도와 메모리 배치에 직접 영향을 줍니다.

Part 2에서는 Unity의 직렬화 시스템과 Instantiate의 내부 동작을 살펴봅니다. 에셋 메모리의 실질적인 관리 방법은 메모리 관리 (2) - 네이티브 메모리와 에셋에서 확인할 수 있습니다.



관련 글

시리즈

전체 시리즈

Tags: Import, Pipeline, Unity, 모바일, 에셋

Categories: ,