3D 모델은 왜 이렇게 클까?
당신의 모델이 몰래 살이 찌고 있다
GLB 파일을 하나 내보냈다. 10MB, 괜찮아 보인다. 그런데 휴대폰으로 옮겨 열어보니 — 하얀 화면, 버벅임, 심지어 바로 꺼져버렸다.
PC에서는 문제없는데, 휴대폰에서 터진다. 코드 탓이 아니다. 3D 모델에는 직관적이지 않은 특성이 있다: 디스크에 저장된 크기와 VRAM에서의 크기는 완전히 다르다.
JPG 이미지는 디스크에서 200KB에 불과할 수 있다. 하지만 GPU는 JPG를 모른다. GPU는 오직 원시 픽셀만 이해한다. 따라서 VRAM에 업로드되기 전에 이 이미지는 완전히 압축 해제된다. 2048x2048 텍스처 하나는 압축 해제 후 약 22MB의 VRAM을 잡아먹는다. 6개의 텍스처(albedo, normal, roughness, metallic, AO, emissive)를 사용했다면, 단일 재질 하나만으로 132MB를 소모한다.
휴대폰의 VRAM은 총 24GB 정도인데, 모델 하나의 텍스처가 36%를 차지한다. 씬에 10개의 모델이 있다면?
뜯어보자, 용량이 어디에 쓰이는지
전형적인 GLB 모델은 크게 세 부분으로 구성된다: 버텍스 데이터, 텍스처 맵, 그리고 메타데이터와 애니메이션.
실제 PBR 모델 하나를 살펴보자:
| 구성 요소 | 구체적인 내용 | 일반적인 비중 | 설명 |
|---|---|---|---|
| 텍스처 맵 | albedo, normal, roughness, metallic, AO 등 | 70-85% | 거의 항상 용량의 대부분 |
| 버텍스 데이터 | position, normal, UV, tangent, 색상 | 10-20% | 모델 복잡도에 따라 다름 |
| 애니메이션 데이터 | 본, 스킨, 키프레임 | 0-15% | 애니메이션이 있을 때만 |
| 기타 | 재질 정의, 씬 구조, 카메라 | < 2% | 무시 가능 |
텍스처 맵이 약 80%를 차지한다. 많은 경우 최적화해야 할 것이 버텍스라고 생각하지만, 실제로 공간을 많이 차지하는 것은 텍스처다.

"디스크에서 작다" ≠ "VRAM에서 작다"
3D 성능을 이해하는 데 가장 중요한 포인트일 것이다.
PNG와 JPG는 네트워크 전송을 위해 설계되었다 — 디스크에서 작고, 다운로드가 빠르다. 하지만 GPU는 이들을 직접 사용할 수 없으며, 반드시 먼저 원시 픽셀로 완전히 압축 해제해야 한다. 계산 방법은 다음과 같다:
VRAM 점유 = 너비 * 높이 * 4바이트(RGBA) * 1.333(밉맵 포함)
4096x4096 RGBA 텍스처 하나:
| 지표 | 값 |
|---|---|
| PNG 파일 크기 | ~8MB |
| JPG 파일 크기 | ~1.5MB |
| VRAM 점유 (밉맵 포함) | ~87MB |
1.5MB의 JPG가 VRAM에서 87MB가 된다.
밉맵이란? GPU는 텍스처의 점진적으로 축소된 버전(원본 크기부터 1x1 픽셀까지, 각 단계는 이전 단계의 절반)을 생성한다. 이를 통해 먼 물체를 더 빠르고 선명하게 렌더링할 수 있지만, VRAM을 약 33% 더 사용한다. 거의 모든 3D 애플리케이션이 밉맵을 사용하므로, 이 오버헤드는 기본이라고 볼 수 있다.
따라서 PNG/JPG는 여행용 압축 팩과 같다 — 압축하면 작아서 휴대하기 편하지만, 도착지에서 모두 펼쳐야 한다. 다운로드는 빨라졌지만 VRAM은 전혀 절약되지 않았다.

VRAM이 부족하면 어떻게 될까
"VRAM 부족"이라는 안내창이 뜨지 않는다. 실제 상황은 더 나쁘다:
- 모바일: 페이지가 하얗게 되거나, 시스템이 탭을 강제 종료한다.
- VR 헤드셋: 프레임 드롭. VR에서 프레임 드롭은 "약간 버벅임"이 아니라 어지러움을 유발한다.
- 데스크톱: 텍스처 깜빡임, 품질 저하, 렌더링 속도 저하.
네이버 카페에서 한 개발자가 WebXR 갤러리를 만들며 Quest에 60장의 스테레오 이미지를 넣었다. 처음에는 정상이었지만, 점점 불안정해지다가 결국 충돌했다. 그는 며칠 동안 코드를 디버깅했지만, VRAM을 전혀 고려하지 않았다는 것을 깨달았다 — 계속 GPU에 JPG를 밀어넣고 있었던 것이다.
압축의 두 가지 길
3D 모델 압축은 크게 두 방향으로 나뉜다:
버텍스 압축 — 버텍스 좌표, 법선, UV 등 기하 데이터를 더 콤팩트하게 저장한다. 예를 들어 32비트 부동소수점을 16비트 정수로 바꾸는 것(이를 양자화(quantization)라고 한다). 대표적인 방식: Draco, MeshOpt, KHR_mesh_quantization.
텍스처 압축 — 텍스처가 VRAM에서도 압축된 상태를 유지하도록 한다. GPU는 샘플링 시 실시간으로 단일 픽셀을 디코딩하며, 성능 오버헤드가 거의 없다. 대표적인 방식: KTX2 + Basis Universal.
| 버텍스 압축 | 텍스처 압축 | |
|---|---|---|
| 줄이는 것 | 기하 데이터 | 텍스처 |
| 일반적인 효과 | 50-90% 축소 | 디스크 50-70% 축소, VRAM 75% 축소 |
| 손실 있음? | 예, 정밀도 저하 | 예, 화질 저하 |
| 적용 대상 | 버텍스가 많은 모델 | 거의 모든 PBR 모델 |
| 자세한 내용 | 2편 참고 | 3, 4편 참고 |
흔한 오해: Draco로 버텍스를 압축하면 모든 문제가 해결된다고 생각하는 것이다. 하지만 텍스처가 모델 용량의 80%를 차지하는데, 버텍스를 절반으로 줄여도 전체는 10% 정도밖에 줄지 않는다. 양쪽 모두 관리해야 한다.
모든 상황에 통하는 단 하나의 방법은 없다
이것이 이 시리즈의 핵심 주장이다:
플랫폼, 기기, 사용 방식에 따라 다른 압축 전략이 필요하다.
| 시나리오 | 주요 병목 | 집중해야 할 부분 |
|---|---|---|
| 데스크톱 웹 전시 | 다운로드 속도 | 파일 크기 |
| 모바일 브라우저 | VRAM | 텍스처 압축 |
| VR 헤드셋 | VRAM + 프레임률 | 텍스처 압축 + 버텍스 단순화 |
| 카카오톡 미니앱 | 패키지 크기 + 호환성 | 가벼운 방식 (MeshOpt) |
| 대규모 씬 | VRAM + 드로우 콜 | 전방위 압축 + LOD |
앞으로의 각 편은 "X를 쓰면 된다"고만 말하지 않는다. 대신, X가 어떤 상황에 적합한지, 언제 오히려 역효과를 내는지, 어떤 경우에 Y를 써야 하는지 명확히 설명할 것이다.
다음 단계
이번 편에서 문제를 파악했다. 다음 편에서는 직접 실습한다 — 버텍스 압축의 세 가지 도구(양자화, MeshOpt, Draco)를 알아보자.