성능 최적화

KTX2 Basis Universal

한 줄 요약

3D 뷰어에서 텍스처가 많은 모델을 열 때마다 GPU 메모리가 75MB씩 점유됐다. KTX2 + Basis Universal(ETC1S 모드)로 변환한 결과, GPU 메모리 75MB → 20MB(73% 절감), 모델 로드 메모리 1.3GB → 0.4GB(69% 감소), 초기 로드 시간 28초 → 20초(28% 단축)를 달성했다.

텍스처가 GPU 메모리를 잡아먹고 있었다

3D 뷰어에서 텍스처가 많은 모델을 열 때마다 GPU 메모리가 급증했다. gpu-texture-formats 노드에서 다뤘듯, GPU는 JPEG을 직접 읽지 못한다. 브라우저가 JPEG을 받으면 CPU에서 비압축 RGBA로 디코딩한 뒤 GPU에 업로드한다. 2048×2048 텍스처 1장이 GPU에서 16MB를 차지한다.

드론 촬영 기반 Mesh 모델은 수천 장의 텍스처 타일을 가진다. 이 텍스처들이 GPU에서 16MB씩 차지하면 VRAM이 빠르게 소진된다.

KTX2 + Basis Universal의 해결 방식

KTX2는 GPU가 직접 읽을 수 있는 압축 포맷으로 텍스처를 저장하는 컨테이너 포맷이다 (Khronos KTX 2.0 Specification). Basis Universal은 그 안에서 사용되는 중간 압축 방식이다.

JPEG 방식:  서버(JPEG) → CPU 디코딩 → GPU에 16MB 업로드
KTX2 방식:  서버(KTX2) → CPU 트랜스코딩 → GPU에 4MB 업로드 (압축 유지)

GPU에 올라가는 시점이 핵심이다. JPEG은 비압축 상태로 올라가지만, KTX2는 GPU 네이티브 압축 포맷 그대로 올라간다.

ETC1S vs UASTC: 왜 ETC1S를 선택했는가

항목ETC1SUASTC
GPU 메모리4 bpp8 bpp
디스크 크기0.3~1.25 bpp2~6 bpp
품질중~저높음 (BC7에 준함)
적합한 용도대량 타일, 항공/드론 텍스처건축/제품, 노멀맵, 고품질 필수

ETC1S를 선택한 이유는 용량 절감이 최우선이었기 때문이다. 수천 개의 드론 촬영 텍스처 타일에서 UASTC를 사용하면 GPU 메모리가 2~4배 증가한다.

ETC1S의 품질 손실이 체감되는지 확인하기 위해, 동일 현장의 드론 촬영 모델을 ETC1S와 UASTC로 각각 변환한 뒤 Cesium 뷰어에서 비교했다. 항공 촬영 이미지는 카메라가 수십~수백 미터 상공에서 촬영하므로 텍스처 디테일이 원래 높지 않다. ETC1S의 압축 아티팩트가 육안으로 구분되지 않았다.

만약 의료 영상이나 문화재 복원처럼 텍스처 품질이 절대적인 도메인이라면, UASTC가 적합하다.

트랜스코딩: 하나의 파일로 모든 기기 대응

Basis Universal의 핵심 가치는 "서버에 하나의 파일만 저장하면 된다"는 것이다. 브라우저(CesiumJS)가 KTX2 파일을 로드하면, WebGL extension을 확인하여 GPU가 지원하는 포맷으로 자동 트랜스코딩한다:

  • 데스크탑 → BC7
  • iPhone/iPad, 최신 Android → ASTC
  • 구형 Android → ETC2
  • 지원 없음 → RGBA 폴백

트랜스코딩은 Basis Universal의 WebAssembly 트랜스코더가 수행한다. "압축 → 다른 압축"으로의 변환이므로 빠르다.

운영 프로젝트 실측 결과

수천 개의 드론 촬영 텍스처 타일(10GB 이상 모델)에 JPEG → KTX2(ETC1S) 변환을 적용한 결과:

지표변환 전 (JPEG)변환 후 (KTX2)개선
씬당 GPU 메모리75 MB20 MB73%↓
모델 로드 메모리1.3 GB0.4 GB69%↓
GPU VRAM 점유1.7 GB0.8 GB53%↓
화면 이동 시 메모리 변동폭0.9 GB0.3 GB66% 안정화
초기 로드 시간28초20초28%↓

메모리 변동폭이 안정화된 이유: GPU 압축 텍스처는 동일 해상도면 항상 같은 GPU 메모리를 차지한다. JPEG은 이미지마다 비압축 크기가 달라 변동이 크지만, KTX2는 일정하다.

변환 도구: gltf-transform CLI + KTX-Software (Khronos Group 공식). 변환 파이프라인의 상세는 aws-lambda-ec2 노드에서 다룬다.

이 경험에서 추출한 원칙

  1. 병목이 "네트워크"가 아니라 "GPU 메모리"일 수 있다. JPEG은 전송 크기가 작지만, GPU에서 비압축으로 부풀어 오른다.

  2. "하나의 파일로 모든 기기 대응"이 유지보수 비용을 결정한다. 기기별로 다른 텍스처를 준비하면 저장 비용, 파이프라인 복잡도, 캐시 관리가 배로 늘어난다.

현재 프로젝트의 텍스처를 gltf-transform inspect로 분석해 보라. RGBA 비압축 텍스처가 있다면 KTX2 적용 대상이다.