3.0 KiB
Three.js에서 자원 해제(Dispose)가 필수적인 이유 웹 브라우저의 자바스크립트 엔진은 힙(Heap) 메모리에 대해 가비지 컬렉션(GC)을 수행하지만, Three.js가 사용하는 GPU 자원(VRAM에 업로드된 기하구조, 재질, 텍스처 등)은 자동으로 가비지 컬렉션되지 않습니다. 따라서 사용이 끝난 3D 객체와 관련 자원을 명시적으로 해제하지 않으면 런타임 내내 메모리에 남아 심각한 메모리 누수(Memory Leak)를 유발하게 됩니다.
효율적인 메모리 관리를 위해 반드시 해제해야 하는 자원과 그 방법은 다음과 같습니다.
1. 기본 자원 해제 (Geometries, Materials, Textures)
객체를 씬(Scene)에서 제거하는 것(scene.remove(mesh))만으로는 GPU 메모리가 비워지지 않습니다. 사용이 끝난 메시(Mesh)를 처리할 때는 구성 요소 각각에 대해 .dispose() 메서드를 명시적으로 호출해야 합니다.
mesh.geometry.dispose()material.dispose()(배열 형태의 다중 재질인 경우 순회하며 개별적으로 해제해야 합니다)texture.dispose()
단일 4K 텍스처 하나가 64MB 이상의 VRAM을 낭비할 수 있으므로, 텍스처 자원은 더 이상 필요하지 않을 때 즉시 해제하는 것이 매우 중요합니다.
2. GLTF/GLB 모델의 ImageBitmap 특수 처리
일반적인 텍스처와 달리, GLTF 모델을 통해 로드된 텍스처는 내부적으로 ImageBitmap 형태로 메모리에 올라갑니다. 이 경우 .dispose()만으로는 완전히 해제되지 않으므로, 반드시 .close() 메서드를 명시적으로 호출하여 누수를 막아야 합니다.
texture.source.data.close?.();
texture.dispose();
3. 렌더 타겟 (Render Targets) 해제
포스트 프로세싱(Post-processing)이나 동적 텍스처 생성을 위해 사용하는 렌더 타겟 역시 자체적으로 프레임버퍼 메모리를 할당받습니다. 효과 적용이 끝났거나 더 이상 사용하지 않는 렌더 타겟도 잊지 말고 renderTarget.dispose()를 호출해 해제해야 합니다.
4. React Three Fiber (R3F) 환경에서의 클린업
React 환경인 R3F에서 개발할 때는, 3D 객체를 렌더링하는 컴포넌트가 화면에서 사라질 때(Unmount) 자원이 해제될 수 있도록 useEffect의 클린업(Cleanup) 함수 내부에서 dispose를 처리해야 합니다.
useEffect(() => {
return () => {
geometry.dispose();
material.dispose();
texture.dispose();
};
}, []);
5. 누수 모니터링 방법
Three.js가 제공하는 renderer.info.memory 객체를 콘솔에 출력하거나 감시하면 현재 GPU에 올라간 지오메트리(geometries)와 텍스처(textures)의 개수를 실시간으로 확인할 수 있습니다. 이 숫자가 일정하게 유지되지 않고 씬 전환 시마다 계속 증가한다면 메모리 누수가 발생하고 있다는 확실한 증거이므로 누수 지점을 찾아 디버깅해야 합니다.