본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 29. · 2 Views
Blender 내보내기 최적화 완벽 가이드
Blender에서 Three.js로 3D 모델을 내보낼 때 반드시 알아야 할 최적화 기법을 다룹니다. 노멀 수정부터 경량화, 포맷 선택까지 실무에서 바로 쓸 수 있는 체크리스트를 제공합니다.
목차
1. 노멀 확인 및 수정
3D 웹 프로젝트를 처음 맡은 김개발 씨는 Blender에서 만든 모델을 Three.js로 가져왔습니다. 그런데 화면에 나타난 모델의 표면이 이상하게 울퉁불퉁하고 빛 반사가 제대로 되지 않았습니다.
선배 박시니어 씨가 다가와 한마디 했습니다. "노멀 벡터를 확인해봤어요?"
노멀 벡터는 3D 모델 표면의 방향을 결정하는 수학적 벡터입니다. 마치 거울에 빛이 어느 방향으로 반사될지 결정하는 각도와 같습니다.
노멀이 올바르게 설정되어야 Three.js에서 조명과 쉐이딩이 자연스럽게 표현됩니다. 잘못된 노멀은 모델이 어둡게 보이거나 면이 뒤집혀 보이는 원인이 됩니다.
다음 코드를 살펴봅시다.
// Blender에서 노멀 확인 및 수정
// 1. Edit Mode로 전환 (Tab 키)
// 2. 메뉴: Mesh > Normals > Recalculate Outside (Shift+N)
// Three.js에서 노멀 확인하기
const geometry = model.geometry;
geometry.computeVertexNormals(); // 노멀 재계산
geometry.normalizeNormals(); // 노멀 정규화
// 노멀 헬퍼로 시각화
const helper = new THREE.VertexNormalsHelper(model, 0.5, 0x00ff00);
scene.add(helper);
김개발 씨는 회사에서 처음으로 3D 웹 프로젝트를 맡았습니다. 디자이너가 Blender로 공들여 만든 제품 모델을 웹사이트에 띄우는 임무였습니다.
설렘 반 긴장 반으로 모델 파일을 Three.js에 로드했습니다. 그런데 이게 웬일입니까.
화면에 나타난 모델이 뭔가 이상했습니다. 어떤 부분은 너무 어둡고, 어떤 부분은 빛이 이상하게 반사되었습니다.
분명 Blender에서는 멀쩡해 보였는데 말이죠. 박시니어 씨가 김개발 씨의 모니터를 들여다보더니 단번에 문제를 짚어냈습니다.
"아, 노멀 벡터 문제네요. Blender에서 확인해보셨어요?" 노멀 벡터란 정확히 무엇일까요?
쉽게 비유하자면, 노멀 벡터는 3D 모델의 각 면이 "어느 방향을 바라보고 있는지" 알려주는 화살표입니다. 마치 거울을 벽에 걸 때 거울이 어느 방향을 향하는지에 따라 빛의 반사 방향이 달라지는 것과 같습니다.
3D 그래픽에서 조명 계산은 전적으로 이 노멀 벡터에 의존합니다. 노멀 벡터가 제대로 설정되지 않으면 어떤 일이 벌어질까요?
가장 흔한 문제는 면이 뒤집혀 보이는 현상입니다. 노멀이 안쪽을 향하면 그 면은 어두워지거나 아예 보이지 않을 수 있습니다.
또 다른 문제는 부드러운 쉐이딩이 깨지는 것입니다. 노멀이 일관되지 않으면 매끄러워야 할 표면이 각져 보이거나 얼룩덜룩해집니다.
Blender에서 작업할 때는 이런 문제가 잘 보이지 않을 수 있습니다. 하지만 glTF로 내보내서 Three.js에 로드하면 갑자기 드러나는 경우가 많습니다.
왜냐하면 두 프로그램의 조명 시스템과 렌더링 방식이 다르기 때문입니다. 어떻게 해결할까요?
Blender에서는 매우 간단합니다. 모델을 선택하고 Edit Mode로 들어간 뒤, 메뉴에서 Mesh > Normals > Recalculate Outside를 선택하면 됩니다.
단축키는 Shift+N입니다. 이 명령은 모든 면의 노멀을 바깥쪽으로 통일합니다.
하지만 이것만으로 부족할 때가 있습니다. 특히 복잡한 모델이나 여러 소스에서 가져온 메시를 합친 경우에는 수동으로 확인해야 합니다.
Blender의 Viewport Overlays 설정에서 Face Orientation을 켜면 파란색은 정상, 빨간색은 뒤집힌 면을 표시해줍니다. Three.js에서도 노멀을 다룰 수 있습니다.
위의 코드를 보면 computeVertexNormals() 메서드가 있습니다. 이것은 지오메트리의 버텍스 노멀을 자동으로 재계산합니다.
그 다음 normalizeNormals()로 노멀 벡터의 길이를 1로 만들어줍니다. 수학적으로 정규화된 벡터가 조명 계산에 필수적이기 때문입니다.
디버깅할 때는 VertexNormalsHelper가 유용합니다. 이 헬퍼는 각 버텍스의 노멀을 초록색 선으로 시각화해줍니다.
노멀이 모델 표면에서 바깥쪽으로 튀어나와 있는지 확인할 수 있습니다. 실무에서 어떻게 활용할까요?
예를 들어 전자제품 쇼룸 웹사이트를 만든다고 가정해봅시다. 수십 개의 제품 모델을 각기 다른 디자이너가 만들었습니다.
통일성이 없기 때문에 노멀 문제가 속출할 수 있습니다. 이럴 때는 내보내기 전에 Blender 스크립트로 모든 모델의 노멀을 일괄 재계산하는 것이 효율적입니다.
하지만 주의할 점도 있습니다. 노멀을 자동으로 재계산하면 하드 엣지가 사라질 수 있습니다.
예를 들어 큐브의 모서리는 날카로워야 하는데, 노멀을 스무스하게 하면 둥글게 보일 수 있습니다. 이럴 때는 Blender에서 Edge Split Modifier를 사용하거나, 특정 엣지를 Sharp로 표시해야 합니다.
다시 김개발 씨의 이야기로 돌아가봅시다. 박시니어 씨의 조언을 듣고 Blender를 다시 열어 Shift+N을 눌렀습니다.
Face Orientation을 켜보니 정말로 몇몇 면이 빨간색으로 표시되었습니다. 노멀을 수정하고 다시 내보내니 Three.js에서 완벽하게 렌더링되었습니다.
노멀 벡터는 3D 그래픽의 기초 중의 기초입니다. 이것을 제대로 이해하고 관리하면 훨씬 더 자연스럽고 아름다운 3D 웹 경험을 만들 수 있습니다.
실전 팁
💡 - Blender에서 Shift+N으로 노멀을 외부로 통일하세요
- Face Orientation 오버레이로 뒤집힌 면을 시각적으로 확인하세요
- Three.js에서 VertexNormalsHelper로 노멀 방향을 디버깅하세요
2. 불필요한 면 삭제
김개발 씨는 노멀 문제를 해결하고 나서 뿌듯해했습니다. 하지만 웹페이지를 테스트해보니 로딩이 너무 느렸습니다.
3D 모델 파일 크기가 무려 15MB나 되었습니다. 박시니어 씨가 Blender 파일을 열어보더니 한숨을 쉬었습니다.
"이 모델, 안 보이는 면도 다 있네요. 최적화가 필요해요."
불필요한 면은 사용자가 절대 볼 수 없는 폴리곤을 의미합니다. 마치 건물 내부에 숨겨진 벽처럼 렌더링되지만 보이지 않는 부분입니다.
이런 면들을 삭제하면 파일 크기가 줄고 렌더링 성능이 향상됩니다. 특히 웹 환경에서는 다운로드 시간과 GPU 부하를 크게 줄일 수 있습니다.
다음 코드를 살펴봅시다.
// Blender에서 불필요한 면 삭제
// 1. Edit Mode에서 전체 선택 (A 키)
// 2. Mesh > Clean Up > Delete Loose
// 3. 내부 면 선택: Select > Select All by Trait > Interior Faces
// 4. X 키 > Faces로 삭제
// Three.js에서 폴리곤 수 확인
console.log('Vertices:', geometry.attributes.position.count);
console.log('Triangles:', geometry.index ? geometry.index.count / 3 : 0);
// 바운딩 박스로 숨겨진 오브젝트 제거
scene.traverse((object) => {
if (object.isMesh && !isVisible(object)) {
object.parent.remove(object);
}
});
김개발 씨는 디자이너에게 받은 3D 모델을 웹에 올렸습니다. 완성도 높은 제품 모델이었고, 렌더링도 완벽했습니다.
그런데 문제가 있었습니다. 페이지 로딩이 너무 느렸던 것입니다.
크롬 개발자 도구의 네트워크 탭을 열어보니 3D 모델 파일이 15MB나 되었습니다. 모바일에서는 거의 10초 가까이 기다려야 했습니다.
이건 사용자 경험 측면에서 재앙이었습니다. 박시니어 씨가 Blender 파일을 열어 모델을 분석했습니다.
"여기 보세요. 이 노트북 모델 안쪽에 완전한 내부 구조가 다 있어요.
키보드 밑에도 회로 기판 모델링이 되어 있네요. 멋지긴 한데, 웹에서는 절대 볼 수 없는 부분이에요." 불필요한 면이란 무엇일까요?
쉽게 비유하자면, 불필요한 면은 집을 지을 때 벽 안쪽에 숨겨진 장식과 같습니다. 아무도 보지 못하지만 자재비는 들어갑니다.
3D 모델도 마찬가지입니다. 렌더링은 되지만 카메라가 절대 볼 수 없는 면들이 파일 크기와 성능을 잡아먹습니다.
웹 3D에서 왜 이게 특히 문제일까요? 데스크톱 3D 소프트웨어나 게임과 달리, 웹은 네트워크를 통해 모델을 다운로드해야 합니다.
15MB짜리 파일은 데스크톱에서는 순식간이지만, 모바일 LTE에서는 수 초가 걸립니다. 게다가 브라우저의 WebGL은 데스크톱 GPU만큼 강력하지 않습니다.
불필요한 폴리곤은 프레임 레이트를 떨어뜨립니다. 어떤 면들이 불필요할까요?
첫째, 완전히 가려진 내부 면입니다. 닫힌 상자 안쪽 면처럼 절대 보이지 않는 부분입니다.
둘째, 겹쳐진 폴리곤입니다. 같은 위치에 여러 면이 중복되어 있는 경우입니다.
셋째, 용도 없는 로스 지오메트리입니다. 어디에도 연결되지 않은 떠도는 버텍스나 엣지입니다.
Blender에서 어떻게 정리할까요? 가장 기본적인 방법은 Clean Up 메뉴입니다.
Edit Mode에서 Mesh > Clean Up > Delete Loose를 실행하면 연결되지 않은 지오메트리가 삭제됩니다. 그 다음 Select > Select All by Trait > Interior Faces로 내부 면을 선택할 수 있습니다.
선택된 면들을 X 키로 삭제하면 됩니다. 하지만 주의하세요.
자동 선택이 완벽하지 않을 수 있습니다. 복잡한 모델에서는 수동으로 확인해야 합니다.
Wireframe View로 전환하고 모델을 돌려가며 의심스러운 부분을 찾아보세요. 또 다른 방법은 Modifier 활용입니다.
Decimate Modifier는 폴리곤 수를 줄여줍니다. 하지만 이것은 단순히 면 개수를 줄이는 것이지, 숨겨진 면을 찾아주지는 않습니다.
용도가 다릅니다. 실무에서는 어떻게 적용할까요?
제품 시각화 프로젝트를 예로 들어봅시다. CAD에서 가져온 모델은 보통 내부 구조가 다 포함되어 있습니다.
엔지니어링 목적으로는 필요하지만 웹 시각화에는 불필요합니다. 이럴 때는 Boolean Modifier로 보이는 부분만 잘라내거나, 수동으로 내부를 삭제합니다.
캐릭터 모델의 경우도 마찬가지입니다. 옷 안쪽의 몸체 폴리곤은 보이지 않습니다.
옷과 겹치는 부분의 몸체 메시를 삭제하면 상당한 최적화 효과를 얻습니다. Three.js에서도 확인할 수 있습니다.
위 코드처럼 geometry.attributes.position.count로 버텍스 개수를 확인할 수 있습니다. 삼각형 개수는 geometry.index.count / 3으로 계산합니다.
최적화 전후를 비교하면 얼마나 줄었는지 알 수 있습니다. 런타임에 숨겨진 오브젝트를 제거하는 방법도 있습니다.
카메라의 프러스텀 컬링은 자동으로 해주지만, 씬에 로드된 메모리는 그대로입니다. 정말 필요 없는 오브젝트는 아예 씬에서 제거하는 것이 좋습니다.
김개발 씨는 박시니어 씨의 도움으로 모델 내부의 불필요한 부분을 전부 삭제했습니다. 파일 크기가 15MB에서 3MB로 줄었습니다.
로딩 시간이 1초대로 개선되었고, 모바일에서도 부드럽게 돌아갔습니다. 불필요한 면 제거는 3D 웹 최적화의 첫걸음입니다.
이것만 제대로 해도 성능이 극적으로 좋아집니다.
실전 팁
💡 - Blender의 Clean Up 메뉴로 떠도는 지오메트리를 일괄 삭제하세요
- Wireframe View에서 모델 내부를 확인하며 수동으로 정리하세요
- Three.js에서 폴리곤 수를 로그로 확인하며 최적화 효과를 측정하세요
3. 모델 경량화 기법
불필요한 면을 삭제하고 나니 파일 크기가 많이 줄었습니다. 하지만 김개발 씨는 더 나은 방법이 있는지 궁금했습니다.
박시니어 씨가 말했습니다. "이제 본격적인 경량화를 해볼까요?
Decimate와 텍스처 압축을 배워보세요."
모델 경량화는 시각적 품질을 유지하면서 폴리곤과 텍스처 크기를 줄이는 기법입니다. 마치 이미지를 JPEG으로 압축하듯, 3D 모델도 똑똑하게 압축할 수 있습니다.
Decimate Modifier로 폴리곤을 줄이고, 텍스처를 최적화하며, 인스턴싱으로 중복을 제거하면 웹에서도 고품질 3D를 구현할 수 있습니다.
다음 코드를 살펴봅시다.
// Blender Python Script: 폴리곤 수 줄이기
import bpy
obj = bpy.context.active_object
mod = obj.modifiers.new(name="Decimate", type='DECIMATE')
mod.ratio = 0.5 # 50%로 줄이기
bpy.ops.object.modifier_apply(modifier="Decimate")
// Three.js: 텍스처 압축 및 인스턴싱
const texture = textureLoader.load('model.jpg');
texture.encoding = THREE.sRGBEncoding;
texture.minFilter = THREE.LinearMipmapLinearFilter;
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
// 동일 모델 인스턴싱으로 메모리 절약
const instancedMesh = new THREE.InstancedMesh(geometry, material, 100);
김개발 씨는 불필요한 면 제거로 첫 번째 최적화에 성공했습니다. 하지만 여전히 궁금한 점이 있었습니다.
"선배님, 모델이 너무 복잡하면 아예 폴리곤을 줄일 수는 없나요?" 박시니어 씨가 고개를 끄덕였습니다. "물론이죠.
그게 바로 모델 경량화입니다. 눈에 띄지 않게 디테일을 줄이는 기술이에요." 모델 경량화란 정확히 무엇일까요?
쉽게 비유하자면, 경량화는 사진을 리사이징하는 것과 비슷합니다. 4K 이미지를 Full HD로 줄여도 스마트폰에서는 차이를 못 느낍니다.
3D 모델도 마찬가지입니다. 멀리서 보거나 작게 표시될 모델은 디테일을 줄여도 괜찮습니다.
웹 환경에서 왜 경량화가 중요할까요? 모바일 디바이스는 데스크톱보다 GPU 성능이 약합니다.
수십만 폴리곤짜리 모델을 실시간으로 렌더링하기 어렵습니다. 또한 네트워크 대역폭도 제한적입니다.
파일 크기가 클수록 로딩이 느려지고 사용자가 이탈할 확률이 높아집니다. 첫 번째 기법은 Decimate Modifier입니다.
Blender의 Decimate는 폴리곤 수를 지능적으로 줄여줍니다. 세 가지 모드가 있습니다.
Collapse 모드는 전체적으로 균등하게 줄입니다. Un-Subdivide는 서브디비전을 역으로 되돌립니다.
Planar는 평평한 면의 디테일을 줄입니다. 실무에서는 주로 Collapse 모드를 씁니다.
Ratio를 0.5로 설정하면 폴리곤이 절반으로 줄어듭니다. 하지만 무작정 줄이면 안 됩니다.
실시간 프리뷰로 품질을 확인하며 적절한 값을 찾아야 합니다. 두 번째 기법은 텍스처 최적화입니다.
고해상도 텍스처는 파일 크기의 주범입니다. 4K 텍스처는 아름답지만 웹에는 과합니다.
대부분의 경우 1K나 2K면 충분합니다. Photoshop이나 온라인 도구로 리사이징하세요.
텍스처 포맷도 중요합니다. PNG는 무손실이지만 용량이 큽니다.
JPEG는 작지만 투명도를 지원하지 않습니다. WebP는 둘 다 지원하며 압축률도 좋습니다.
최신 브라우저는 모두 WebP를 지원하므로 적극 활용하세요. 세 번째 기법은 **LOD(Level of Detail)**입니다.
LOD는 카메라 거리에 따라 다른 품질의 모델을 사용하는 기법입니다. 가까이 있을 때는 고품질, 멀리 있을 때는 저품질 모델을 표시합니다.
Three.js의 LOD 클래스가 이를 자동으로 처리해줍니다. Blender에서 같은 모델의 여러 버전을 만들어야 합니다.
원본, 50% Decimate, 25% Decimate 이렇게 세 단계로 만들면 됩니다. Three.js에서 LOD 객체에 각각 추가하면 끝입니다.
네 번째 기법은 인스턴싱입니다. 같은 모델이 여러 개 필요할 때 인스턴싱을 쓰면 메모리를 크게 절약할 수 있습니다.
예를 들어 숲을 만들 때 나무 모델을 100개 로드하는 대신, 하나의 지오메트리를 100번 인스턴싱하면 됩니다. 위 코드의 InstancedMesh가 바로 그것입니다.
지오메트리와 머티리얼을 공유하고, 각 인스턴스의 위치와 회전만 다르게 설정합니다. GPU는 한 번의 드로우 콜로 모든 인스턴스를 렌더링합니다.
실전 사례를 봅시다. 가구 쇼룸 웹사이트를 만든다고 가정해봅시다.
의자 모델이 원래 5만 폴리곤이었습니다. Decimate로 2만으로 줄였습니다.
텍스처를 4K에서 1K로 낮추고 WebP로 변환했습니다. 파일 크기가 8MB에서 1.5MB로 줄었고, 모바일에서도 60fps로 돌아갔습니다.
하지만 주의할 점이 있습니다. 과도한 Decimate는 모델을 망칩니다.
특히 곡선이나 실루엣이 중요한 부분은 폴리곤을 많이 유지해야 합니다. Vertex Group을 활용해 특정 영역만 보호할 수 있습니다.
김개발 씨는 이 모든 기법을 적용해봤습니다. 원래 15MB였던 모델이 최종적으로 2MB 미만으로 줄었습니다.
놀라운 것은 시각적 품질이 거의 그대로라는 점이었습니다. "최적화가 이렇게 효과적인 줄 몰랐어요!" 경량화는 기술이자 예술입니다.
품질과 성능 사이의 균형을 찾는 것이 핵심입니다.
실전 팁
💡 - Decimate Modifier의 Ratio를 0.3~0.7 사이에서 조절하며 품질을 확인하세요
- 텍스처는 WebP 포맷으로 변환하고 1K~2K 해상도를 유지하세요
- 같은 모델이 여러 개 필요하면 InstancedMesh로 메모리를 절약하세요
4. glTF/GLB 포맷 이해하기
김개발 씨는 최적화된 모델을 내보낼 준비가 되었습니다. 하지만 Blender의 Export 메뉴에는 FBX, OBJ, Collada 등 수많은 포맷이 있었습니다.
어떤 것을 선택해야 할까요? 박시니어 씨가 단호하게 말했습니다.
"웹에는 glTF만 쓰세요. 다른 건 고려하지 마세요."
glTF는 웹과 모바일을 위해 설계된 현대적인 3D 포맷입니다. 마치 이미지의 JPEG나 비디오의 MP4처럼, 3D의 표준 포맷입니다.
효율적인 압축, 빠른 로딩, 그리고 PBR 머티리얼 완벽 지원이 특징입니다. GLB는 glTF의 바이너리 버전으로 단일 파일로 배포하기 편리합니다.
다음 코드를 살펴봅시다.
// Blender에서 glTF 내보내기 (Python Script)
import bpy
bpy.ops.export_scene.gltf(
filepath="/path/to/model.glb",
export_format='GLB', # 또는 'GLTF_SEPARATE'
export_textures=True,
export_normals=True,
export_draco_mesh_compression_enable=True,
export_draco_mesh_compression_level=6
)
// Three.js에서 glTF 로드
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
const loader = new GLTFLoader();
loader.load('model.glb', (gltf) => {
scene.add(gltf.scene);
console.log('Loaded:', gltf);
});
김개발 씨는 드디어 모델을 내보낼 시간이 되었습니다. Blender의 File > Export 메뉴를 열었습니다.
그런데 선택지가 너무 많았습니다. FBX, OBJ, Collada, STL, glTF...
어떤 것을 써야 할까요? 박시니어 씨가 단호하게 말했습니다.
"웹 프로젝트면 무조건 glTF입니다. 다른 포맷은 고민할 필요도 없어요." glTF란 정확히 무엇일까요?
glTF는 GL Transmission Format의 약자입니다. Khronos Group이라는 표준화 기구에서 만들었습니다.
OpenGL과 WebGL을 만든 바로 그 단체입니다. glTF의 목표는 명확합니다.
웹과 모바일에서 3D 콘텐츠를 효율적으로 전송하고 렌더링하는 것입니다. 왜 다른 포맷이 아닌 glTF를 써야 할까요?
FBX는 오토데스크의 독점 포맷입니다. 파일이 크고 파싱이 복잡하며 웹에 최적화되어 있지 않습니다.
OBJ는 오래된 포맷으로 텍스처와 애니메이션 지원이 약합니다. Collada는 XML 기반이라 파싱이 느립니다.
반면 glTF는 JSON 기반으로 파싱이 빠릅니다. 바이너리 데이터는 별도로 저장되어 효율적입니다.
PBR 머티리얼을 표준으로 지원합니다. 무엇보다 Three.js, Babylon.js 등 모든 웹 3D 라이브러리가 완벽하게 지원합니다.
glTF에는 두 가지 형태가 있습니다. 첫째는 glTF 분리형입니다.
.gltf 파일(JSON)과 .bin 파일(바이너리 데이터), 그리고 텍스처 이미지들이 따로 저장됩니다. 개발 단계에서 편리합니다.
파일을 열어 JSON을 직접 확인할 수 있기 때문입니다. 둘째는 GLB입니다.
모든 데이터가 하나의 바이너리 파일로 묶입니다. 배포할 때는 GLB가 훨씬 편리합니다.
파일이 하나뿐이므로 관리가 쉽고, HTTP 요청도 한 번만 발생합니다. glTF의 강력한 기능 중 하나는 Draco 압축입니다.
Draco는 구글이 개발한 3D 메시 압축 알고리즘입니다. 지오메트리 데이터를 90% 이상 압축할 수 있습니다.
예를 들어 10MB짜리 모델이 1MB로 줄어듭니다. 압축 레벨을 높일수록 파일이 작아지지만, 디코딩 시간이 길어집니다.
위 코드의 export_draco_mesh_compression_level이 바로 그것입니다. 레벨 6 정도가 압축률과 속도의 균형점입니다.
레벨 10으로 올리면 더 작아지지만 로딩이 느려질 수 있습니다. Three.js에서 Draco를 쓰려면 디코더를 로드해야 합니다.
Three.js는 Draco 디코더를 WebAssembly로 제공합니다. DRACOLoader를 설정하고 GLTFLoader와 연결하면 됩니다.
브라우저가 자동으로 디코딩해줍니다. 실무에서 어떻게 선택할까요?
개발 중에는 glTF 분리형을 쓰는 것이 좋습니다. 텍스처를 교체하거나 JSON을 수정할 일이 자주 있기 때문입니다.
배포할 때는 GLB + Draco로 최종 내보내기를 합니다. 파일 크기와 로딩 속도가 최적화됩니다.
대용량 모델의 경우 스트리밍도 고려할 수 있습니다. glTF는 progressive loading을 지원합니다.
기본 형태를 먼저 보여주고 디테일을 나중에 로드하는 방식입니다. 하지만 주의할 점도 있습니다.
Draco 압축은 디코딩에 CPU 시간이 필요합니다. 저사양 모바일에서는 오히려 로딩이 느려질 수 있습니다.
따라서 모델 크기가 크지 않다면 Draco를 끄는 것이 나을 수도 있습니다. 또한 Blender의 glTF 익스포터가 모든 기능을 지원하는 것은 아닙니다.
Custom Shaders는 내보내지지 않습니다. Blender의 노드 트리가 복잡하면 Three.js에서 의도한 대로 나오지 않을 수 있습니다.
가능한 Principled BSDF만 사용하세요. 김개발 씨는 GLB로 내보내기를 했습니다.
Draco 압축 레벨을 6으로 설정했습니다. 결과는 놀라웠습니다.
원래 2MB였던 파일이 400KB로 줄어들었습니다. Three.js에서 로드해보니 완벽하게 작동했습니다.
glTF는 웹 3D의 미래입니다. 이 포맷을 마스터하면 어떤 플랫폼에서든 3D 콘텐츠를 효율적으로 전달할 수 있습니다.
실전 팁
💡 - 배포 시에는 GLB 포맷과 Draco 압축을 사용하세요
- 개발 중에는 glTF 분리형으로 작업하면 편리합니다
- Blender에서는 Principled BSDF 노드만 사용해 호환성을 보장하세요
5. Three.js용 최적 내보내기 설정
김개발 씨는 glTF 포맷에 대해 배웠지만, Blender의 익스포트 창에는 수많은 옵션이 있었습니다. Normals, Tangents, Vertex Colors, Animations...
체크박스가 너무 많았습니다. 박시니어 씨가 옆에서 말했습니다.
"웹용 설정은 따로 있어요. 제가 베스트 프랙티스를 알려드릴게요."
Three.js용 내보내기는 성능과 호환성을 모두 고려해야 합니다. 불필요한 데이터를 제거하고, 좌표계를 맞추며, 압축 옵션을 최적화하는 것이 핵심입니다.
Blender의 익스포트 설정을 제대로 이해하면 파일 크기를 줄이고 로딩 시간을 단축하며 렌더링 품질을 보장할 수 있습니다.
다음 코드를 살펴봅시다.
# Blender glTF Export - Three.js 최적 설정
{
"export_format": "GLB",
"export_copyright": "Your Company",
"export_image_format": "AUTO", # JPEG 자동 변환
"export_texture_dir": "",
"export_texcoords": True,
"export_normals": True,
"export_draco_mesh_compression_enable": True,
"export_draco_mesh_compression_level": 6,
"export_draco_position_quantization": 14,
"export_draco_normal_quantization": 10,
"export_draco_texcoord_quantization": 12,
"export_tangents": False, # Three.js에서 자동 생성
"export_materials": "EXPORT",
"export_colors": True,
"export_cameras": False, # Three.js에서 직접 설정
"export_lights": False,
"export_yup": True # Y-up 좌표계 (Three.js 호환)
}
김개발 씨는 glTF를 선택했지만, 익스포트 창의 옵션들이 혼란스러웠습니다. 무엇을 켜고 끄야 할까요?
잘못 설정하면 Three.js에서 제대로 안 나올 수도 있습니다. 박시니어 씨가 Blender를 열고 익스포트 설정을 하나씩 짚어줬습니다.
"이건 웹 프로젝트에서 수백 번 검증된 설정이에요. 따라만 하면 됩니다." 첫 번째로 중요한 것은 포맷 선택입니다.
glTF Separate와 glTF Embedded, 그리고 GLB 중 하나를 고를 수 있습니다. 배포용이라면 무조건 GLB입니다.
단일 파일이므로 CDN 캐싱도 쉽고 관리도 편합니다. 두 번째는 이미지 포맷입니다.
Image Format을 AUTO로 설정하면 Blender가 자동으로 최적의 포맷을 선택합니다. 투명도가 없는 텍스처는 JPEG으로, 있는 텍스처는 PNG로 저장됩니다.
수동으로 JPEG를 강제할 수도 있지만, AUTO가 안전합니다. 세 번째는 Draco 압축입니다.
위에서 설명했듯이 Draco는 필수입니다. Compression Level은 6이 적당합니다.
하지만 추가 옵션도 있습니다. Position Quantization, Normal Quantization, Texcoord Quantization입니다.
이것들은 각 데이터의 정밀도를 조절합니다. 높을수록 품질이 좋지만 파일이 커집니다.
위치는 14bit, 노멀은 10bit, UV는 12bit가 대부분의 웹 프로젝트에서 충분합니다. 정밀한 CAD 모델이 아니라면 말이죠.
네 번째는 Tangents입니다. 노멀 맵을 쓸 때 탄젠트 벡터가 필요합니다.
하지만 Blender에서 내보낼 필요는 없습니다. Three.js가 자동으로 생성하기 때문입니다.
오히려 익스포트하면 파일 크기만 커집니다. Export Tangents는 꺼두세요. 다섯 번째는 Cameras와 Lights입니다.
Blender의 카메라와 조명을 내보낼 수 있습니다. 하지만 Three.js에서는 보통 코드로 직접 설정합니다.
특별한 이유가 없다면 둘 다 끄는 것이 좋습니다. 불필요한 데이터를 줄이고 코드 제어를 명확히 할 수 있습니다. 여섯 번째는 좌표계입니다.
Blender는 Z-up 좌표계를 씁니다. 하지만 Three.js는 Y-up입니다.
익스포트 시 +Y Up 옵션을 켜면 자동으로 변환해줍니다. 이것을 끄면 Three.js에서 모델이 눕거나 뒤집혀 보입니다.
일곱 번째는 Vertex Colors입니다. 모델에 버텍스 컬러를 칠했다면 Export Vertex Colors를 켜야 합니다.
끄면 색상 정보가 사라집니다. 하지만 대부분의 모델은 텍스처를 쓰므로 필요 없을 수 있습니다.
여덟 번째는 Animations입니다. 애니메이션이 포함된 캐릭터나 오브젝트라면 Export Animations를 켜야 합니다.
하지만 정적인 제품 모델이라면 끄는 것이 좋습니다. 애니메이션 데이터가 꽤 용량을 차지하기 때문입니다.
실무 팁을 알려드립니다. 익스포트 설정을 매번 다시 하기 귀찮다면 Operator Presets를 활용하세요.
설정을 저장해두면 다음부터 원클릭으로 불러올 수 있습니다. 회사나 프로젝트 전체에서 통일된 설정을 쓸 때 유용합니다.
또한 Batch Export 스크립트를 만들 수도 있습니다. Python으로 Blender를 자동화해서 여러 모델을 한 번에 내보낼 수 있습니다.
위의 코드가 바로 그 예시입니다. Three.js에서 확인하는 방법도 있습니다.
로드한 glTF 객체를 콘솔에 찍어보세요. gltf.scene, gltf.animations, gltf.cameras 등을 확인할 수 있습니다.
의도하지 않은 데이터가 포함되어 있다면 익스포트 설정을 다시 점검하세요. 흔한 실수 하나를 짚어봅시다.
Apply Modifiers를 까먹는 경우가 많습니다. Blender에서 Modifier를 적용하지 않고 내보내면 Three.js에서 원본 메시가 나옵니다.
Decimate나 Subdivision을 적용했다면 반드시 Object > Apply > All Modifiers를 먼저 실행하세요. 김개발 씨는 박시니어 씨가 알려준 설정대로 익스포트했습니다.
GLB 포맷, Draco 압축 레벨 6, Tangents 끄기, Y-up 켜기. 결과물을 Three.js에 로드하니 완벽했습니다.
좌표도 맞고, 노멀 맵도 제대로 작동했습니다. 올바른 익스포트 설정은 시행착오를 줄여줍니다.
한 번 제대로 배워두면 모든 프로젝트에서 써먹을 수 있습니다.
실전 팁
💡 - GLB 포맷에 Draco 레벨 6, Tangents 끄기가 기본입니다
- +Y Up 옵션을 켜서 Three.js 좌표계에 맞추세요
- Operator Presets로 설정을 저장해 재사용하세요
6. 내보내기 체크리스트
김개발 씨는 모든 최적화 기법을 배웠습니다. 하지만 실전에서는 뭔가 하나씩 빠뜨리기 쉽습니다.
박시니어 씨가 A4 용지 한 장을 건넸습니다. "이건 제가 몇 년간 정리한 체크리스트예요.
내보내기 전에 항상 확인하세요. 실수를 줄여줄 거예요."
내보내기 체크리스트는 실수를 방지하고 품질을 보장하는 최종 점검표입니다. 마치 비행기 조종사가 이륙 전 체크리스트를 확인하듯, 3D 아티스트도 익스포트 전에 필수 항목을 점검해야 합니다.
노멀, 스케일, UV, 머티리얼, 최적화, 포맷까지 모든 것을 빠짐없이 확인하면 실전에서 문제가 발생하지 않습니다.
다음 코드를 살펴봅시다.
# Blender Python: 자동 체크리스트 스크립트
import bpy
def pre_export_check():
issues = []
# 1. 스케일 체크
for obj in bpy.context.selected_objects:
if obj.scale != (1, 1, 1):
issues.append(f"{obj.name}: Scale not applied")
# 2. 노멀 체크
for obj in bpy.context.selected_objects:
if obj.type == 'MESH':
mesh = obj.data
if not mesh.has_custom_normals:
issues.append(f"{obj.name}: No custom normals")
# 3. UV 체크
for obj in bpy.context.selected_objects:
if obj.type == 'MESH' and not obj.data.uv_layers:
issues.append(f"{obj.name}: No UV map")
# 4. 폴리곤 수 체크
total_tris = sum(len(obj.data.polygons) for obj in bpy.context.selected_objects if obj.type == 'MESH')
if total_tris > 50000:
issues.append(f"Total triangles: {total_tris} (consider optimization)")
return issues
print(pre_export_check())
김개발 씨는 처음 몇 번의 익스포트에서 실수를 많이 했습니다. 스케일을 적용하지 않아서 Three.js에서 모델이 거대하게 나온 적도 있고, UV가 없어서 텍스처가 안 나온 적도 있었습니다.
박시니어 씨가 정리해둔 체크리스트를 보니 정말 유용했습니다. "이거 하나만 따라해도 실수가 90% 줄어요." 체크리스트가 왜 중요할까요?
사람은 실수하는 존재입니다. 특히 반복 작업에서는 습관적으로 단계를 건너뛰기 쉽습니다.
체크리스트는 이를 방지합니다. 마치 의사가 수술 전 체크리스트를 확인하듯, 3D 아티스트도 익스포트 전에 점검표를 따라야 합니다.
첫 번째 체크 항목은 노멀 방향입니다. 모든 면의 노멀이 외부를 향하는지 확인하세요.
Blender에서 Face Orientation 오버레이를 켜고 빨간색 면이 없는지 점검합니다. 있다면 Shift+N으로 수정합니다.
두 번째는 스케일 적용입니다. Object Mode에서 Ctrl+A > Scale을 눌러 스케일을 적용하세요.
적용하지 않으면 Three.js에서 모델 크기가 의도와 다르게 나올 수 있습니다. 스케일이 (1, 1, 1)인지 확인하세요.
세 번째는 회전과 위치입니다. 모델의 원점이 올바른 위치에 있는지 확인하세요.
바닥에 놓일 오브젝트라면 원점이 바닥 중앙에 있어야 합니다. Object > Set Origin > Origin to Geometry로 조정할 수 있습니다.
네 번째는 UV 맵입니다. 텍스처를 사용하는 모델이라면 UV 맵이 필수입니다.
UV Editor를 열어 언래핑이 제대로 되어 있는지 확인하세요. 겹치는 부분이나 늘어진 부분이 없는지 점검합니다.
다섯 번째는 텍스처 경로입니다. Blender에서 텍스처가 로컬 경로로 연결되어 있다면 익스포트할 때 문제가 생길 수 있습니다.
File > External Data > Pack All into .blend로 텍스처를 내장하거나, 상대 경로로 바꾸세요. 여섯 번째는 머티리얼 설정입니다.
Principled BSDF만 사용했는지 확인하세요. Custom Shader Nodes는 glTF로 내보내지지 않습니다.
Metallic, Roughness, Normal Map 등이 올바르게 연결되어 있는지 점검합니다. 일곱 번째는 폴리곤 수입니다.
총 삼각형 개수를 확인하세요. Blender 우측 상단의 Statistics를 켜면 보입니다.
웹용이라면 5만 폴리곤 이하가 이상적입니다. 넘으면 Decimate를 고려하세요.
여덟 번째는 불필요한 데이터 제거입니다. 숨겨진 오브젝트, 사용하지 않는 버텍스 그룹, 빈 머티리얼 슬롯 등을 정리하세요.
Outliner에서 사용하지 않는 것들을 삭제합니다. 아홉 번째는 좌표계 확인입니다.
익스포트 설정에서 +Y Up이 켜져 있는지 확인하세요. Three.js는 Y-up 좌표계를 사용합니다.
열 번째는 Draco 압축입니다. 파일 크기가 1MB를 넘는다면 Draco 압축을 켜세요.
레벨은 6으로 설정합니다. 열한 번째는 애니메이션입니다.
애니메이션이 필요한 모델이라면 NLA Editor에서 모든 애니메이션이 트랙에 정리되어 있는지 확인하세요. 필요 없다면 익스포트 옵션에서 애니메이션을 끄세요.
열두 번째는 테스트 로드입니다. 익스포트 후 반드시 Three.js에서 로드해보세요.
예상대로 나오는지, 텍스처가 제대로 적용되는지, 스케일이 맞는지 확인합니다. 문제가 있다면 Blender로 돌아가 수정합니다.
실무에서는 어떻게 관리할까요? 팀 프로젝트라면 체크리스트를 문서화하세요.
Notion이나 Confluence에 정리해두고 모든 팀원이 따르도록 합니다. 또한 위의 Python 스크립트처럼 자동화할 수 있는 부분은 자동화하세요.
CI/CD 파이프라인에 통합할 수도 있습니다. Git에 커밋되면 자동으로 Blender 스크립트가 실행되어 체크리스트를 검증하고, 문제가 있으면 경고를 보내는 식입니다.
김개발 씨는 이 체크리스트를 프린트해서 모니터 옆에 붙여뒀습니다. 내보내기 전에 하나씩 체크하며 확인했습니다.
그 후로 Three.js에서 "왜 안 나오지?" 하는 일이 사라졌습니다. 체크리스트는 단순하지만 강력합니다.
복잡한 과정을 체계적으로 관리하는 도구입니다.
실전 팁
💡 - 체크리스트를 프린트해서 책상에 붙여두세요
- Python 스크립트로 자동 검증을 구현하세요
- 익스포트 후 반드시 Three.js에서 테스트 로드하세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Three.js Raycaster 상호작용 구현 완벽 가이드
Three.js의 Raycaster를 활용하여 3D 객체와의 상호작용을 구현하는 방법을 초급자 눈높이에서 설명합니다. 마우스 클릭, 터치 이벤트, 하이라이트 효과까지 실전 예제와 함께 배워봅니다.
GSAP 애니메이션 라이브러리 완벽 가이드
웹 애니메이션의 표준, GSAP를 처음부터 제대로 배워봅니다. 기본 사용법부터 Timeline, Easing, Three.js 통합까지 실무에서 바로 쓸 수 있는 핵심 내용을 다룹니다.
Three.js 카메라 및 조명 설정 완벽 가이드
3D 웹 개발에서 가장 중요한 카메라와 조명 설정을 실무 중심으로 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.
Three.js 모델 불러오기 완벽 가이드
Blender에서 만든 3D 모델을 웹 브라우저로 불러오는 방법을 배웁니다. GLTFLoader 사용법부터 텍스처 처리, 성능 최적화까지 실무에서 바로 쓸 수 있는 완전한 가이드입니다.
Blender 텍스처링 완벽 가이드
3D 모델에 생명을 불어넣는 텍스처링 기법을 처음부터 차근차근 배워봅니다. 이미지 준비부터 UV 매핑, Shader Editor 활용까지 실무에 바로 적용할 수 있는 내용으로 구성했습니다.