# [[Three.js 성능 최적화|Three.js 성능 최적화]]

## 📌 Brief Summary
Three.js 성능 최적화는 CPU와 GPU 간의 통신 병목 현상을 유발하는 드로우 콜(Draw Call)을 줄이고 렌더링 파이프라인의 효율을 극대화하여 높은 프레임 속도를 유지하는 과정이다 [1-3]. 주로 `InstancedMesh` 및 `BatchedMesh`를 활용한 인스턴싱/배칭 기법, 텍스처와 지오메트리 압축, 프러스텀 컬링(Frustum Culling) 및 LOD(Level of Detail) 기법이 핵심적으로 사용된다 [4-9]. 최근에는 WebGL의 구조적 한계를 극복하기 위해 WebGPU와 컴퓨트 셰이더를 기반으로 한 GPU 주도 렌더링(GPU-driven Rendering) 기술로 발전하고 있다 [10, 11].

## 📖 Core Content

*   **드로우 콜 최적화 (Draw Call Optimization)**
    *   드로우 콜은 CPU가 GPU에 렌더링 명령을 내리는 과정으로, 프레임당 100개 이하로 유지하는 것이 부하를 막는 핵심 규칙이다 [1, 2, 4]. 
    *   동일한 지오메트리와 재질을 여러 번 렌더링할 때는 `InstancedMesh`를 사용하여 단일 드로우 콜로 처리해야 한다 [4, 6]. 
    *   재질은 같지만 지오메트리가 다를 경우에는 여러 지오메트리를 하나의 렌더링 호출로 묶어주는 `BatchedMesh`를 사용하는 것이 효율적이다 [12-14]. 
    *   서로 독립적으로 움직일 필요가 없는 정적인 배경이나 환경 객체는 `BufferGeometryUtils`를 사용하여 로드 시점에 하나의 메쉬로 병합(Merge)하는 것이 좋다 [12, 15].

*   **에셋 및 메모리 관리 (Asset & Memory Management)**
    *   형상을 유지하며 폴리곤을 줄이는 데시메이션(Decimation) 작업을 거치고, Draco 확장을 통해 지오메트리 파일 크기를 최대 95%까지 압축할 수 있다 [16-18]. 
    *   텍스처의 경우, GPU 메모리에서 압축 상태를 유지하는 KTX2나 Basis Universal 포맷을 사용해 메모리 대역폭 점유율을 크게 낮춰야 한다 [16, 19].
    *   수백 개의 텍스처가 필요할 때는 바인딩 오버헤드를 막기 위해 텍스처 아틀라스(Texture Atlas)나 여러 텍스처 레이어를 인덱스로 접근할 수 있는 배열 텍스처(Data Array Textures)를 활용해야 한다 [7, 20, 21].
    *   Three.js는 GPU 자원을 자동으로 가비지 컬렉션하지 않으므로, 사용이 끝난 지오메트리, 재질, 텍스처는 반드시 `.dispose()`를 명시적으로 호출해 메모리 누수를 방지해야 한다 [22, 23].

*   **가시성 판단 및 LOD (Visibility & Level of Detail)**
    *   카메라와의 거리에 따라 고해상도 메쉬를 저해상도 메쉬나 임포스터(Impostor)로 교체하는 LOD 기법을 통해 폴리곤 렌더링 비용을 크게 절감할 수 있다 [8, 24-26].
    *   Three.js의 프러스텀 컬링(Frustum Culling)은 화면 밖의 객체를 렌더링에서 제외하지만, `InstancedMesh`의 경우 개별 인스턴스가 아닌 전체 바운딩 볼륨을 기준으로 컬링하기 때문에 보이지 않는 객체까지 GPU 정점 연산을 수행하는 낭비가 발생할 수 있다 [27]. 이를 보완하기 위해 BVH(Bounding Volume Hierarchy)와 같은 공간 분할 자료구조를 사용하거나 GPU 컴퓨트 셰이더 기반의 컬링 기법이 필요하다 [28, 29].

*   **WebGPU 전환 및 GPU 주도 렌더링 (WebGPU & Compute Shaders)**
    *   전통적인 `InstancedMesh`는 자동 정렬의 부재로 인해 깊이 오버드로우(Overdraw)가 발생하고 투명도 블렌딩 오류를 야기하며, 본(Bone) 기반 애니메이션 처리에 취약하다는 구조적 한계가 있다 [30-32].
    *   이러한 병목을 해소하기 위해 Three.js는 WebGPU 렌더러와 단일 코드로 관리되는 TSL(Three Shader Language)을 전면 도입했다 [33, 34].
    *   컴퓨트 셰이더를 활용하면 CPU에서 처리하던 충돌 감지, 지형 생성, 수백만 개의 파티클 업데이트 및 컬링을 GPU에서 병렬로 직접 수행할 수 있어 극적인 성능 향상을 이룰 수 있다 [35-37].

## 🔗 Knowledge Connections
- **Related Topics:** [[InstancedMesh|InstancedMesh]], [[BatchedMesh|BatchedMesh]], [[WebGPU|WebGPU]], 드로우 콜 (Draw Call), [[가변적 LOD(Level of Detail) 시스템|LOD (Level of Detail)]]
- **Projects/Contexts:** Utsubo의 WebGPU 도입 (Segments.ai 등), InstancedMesh2 라이브러리, Three.js r171 WebGPURenderer
- **Contradictions/Notes:** 드로우 콜을 줄이기 위해 `InstancedMesh`나 `BatchedMesh`를 도입하더라도 항상 성능이 향상되는 것은 아니다. `InstancedMesh`는 개별 컬링의 부재와 오버드로우로 인해 오히려 개별 렌더링보다 GPU FPS를 떨어뜨릴 수 있다는 점이 지적된다 [27, 30, 38]. 또한 `BatchedMesh`의 경우에도 천만 개 이상의 많은 폴리곤과 지오메트리를 처리할 때는 내부적인 다중 그리기(multi-draw) 버퍼 업로드 및 패킹 오버헤드로 인해 CPU 점유율이 40~60%까지 치솟고 프레임이 급감하는 현상이 보고되어, 상황에 따른 벤치마킹이 필수적이다 [39-43].

---
*Last updated: 2026-04-19*