--- id: wiki-2026-0508-threejs title: Three.js category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Three.js, three, 3D web, WebGL library] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [3d, webgl, webgpu, graphics, threejs] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: typescript framework: three.js-r170 --- # Three.js ## 매 한 줄 > **"매 web 의 de-facto 3D library — WebGL/WebGPU 의 high-level wrapper"**. 매 scene graph + materials + lights + cameras + loaders. 2026 r170+ — WebGPURenderer stable, TSL (Three Shading Language), node-based materials. React 통합은 `@react-three/fiber`. ## 매 핵심 ### 매 core entities - **Scene**: 매 graph root. - **Camera**: Perspective / Orthographic. - **Renderer**: WebGLRenderer / WebGPURenderer. - **Mesh** = Geometry + Material. - **Light**: Ambient / Directional / Point / Spot. ### 매 render loop - `requestAnimationFrame` → update → renderer.render(scene, camera). - 매 r3f 는 자동 loop. ### 매 응용 1. Product configurator (3D customization). 2. Data visualization (graph, scatter). 3. WebXR (VR/AR). 4. Game / interactive art. ## 💻 패턴 ### Vanilla minimal ```typescript import * as THREE from 'three'; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000, ); camera.position.z = 5; const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement); const geo = new THREE.BoxGeometry(1, 1, 1); const mat = new THREE.MeshStandardMaterial({ color: 0x6699ff }); const cube = new THREE.Mesh(geo, mat); scene.add(cube); scene.add(new THREE.AmbientLight(0xffffff, 0.4)); const dir = new THREE.DirectionalLight(0xffffff, 1); dir.position.set(5, 5, 5); scene.add(dir); renderer.setAnimationLoop(() => { cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render(scene, camera); }); ``` ### WebGPU renderer (r170+) ```typescript import * as THREE from 'three/webgpu'; import { color, normalLocal } from 'three/tsl'; const renderer = new THREE.WebGPURenderer({ antialias: true }); await renderer.init(); const mat = new THREE.MeshBasicNodeMaterial(); mat.colorNode = color('#6699ff').mul(normalLocal.length()); ``` ### React Three Fiber ```tsx import { Canvas, useFrame } from '@react-three/fiber'; import { OrbitControls, Environment } from '@react-three/drei'; import { useRef } from 'react'; import type { Mesh } from 'three'; function Box() { const ref = useRef(null); useFrame((_, dt) => { if (ref.current) ref.current.rotation.y += dt; }); return ( ); } export default function App() { return ( ); } ``` ### GLTF model loading ```typescript import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'; const draco = new DRACOLoader(); draco.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/'); const loader = new GLTFLoader(); loader.setDRACOLoader(draco); const gltf = await loader.loadAsync('/model.glb'); scene.add(gltf.scene); ``` ```tsx // r3f import { useGLTF } from '@react-three/drei'; function Model() { const { scene } = useGLTF('/model.glb'); return ; } ``` ### Postprocessing ```typescript import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js'; const composer = new EffectComposer(renderer); composer.addPass(new RenderPass(scene, camera)); composer.addPass(new UnrealBloomPass( new THREE.Vector2(window.innerWidth, window.innerHeight), 0.8, 0.4, 0.85, )); renderer.setAnimationLoop(() => composer.render()); ``` ### Instanced rendering (10k+ objects) ```typescript const count = 10_000; const mesh = new THREE.InstancedMesh(geo, mat, count); const dummy = new THREE.Object3D(); for (let i = 0; i < count; i++) { dummy.position.set( (Math.random() - 0.5) * 100, (Math.random() - 0.5) * 100, (Math.random() - 0.5) * 100, ); dummy.updateMatrix(); mesh.setMatrixAt(i, dummy.matrix); } scene.add(mesh); ``` ### Disposal (memory) ```typescript function dispose(obj: THREE.Object3D) { obj.traverse((child) => { if ((child as THREE.Mesh).isMesh) { const m = child as THREE.Mesh; m.geometry.dispose(); const mats = Array.isArray(m.material) ? m.material : [m.material]; mats.forEach((mat) => mat.dispose()); } }); } ``` ### WebXR (VR) ```typescript renderer.xr.enabled = true; import { VRButton } from 'three/addons/webxr/VRButton.js'; document.body.appendChild(VRButton.createButton(renderer)); ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | 매 React app | `@react-three/fiber` + drei | | 매 vanilla / lib | three.js direct | | 매 GPU compute / advanced shader | WebGPURenderer + TSL | | 매 game | Babylon.js / PlayCanvas (more game-oriented) | | 매 declarative UI integration | r3f (preferred) | **기본값**: 매 React → r3f + drei. 매 그 외 → three.js + addons. ## 🔗 Graph - 부모: [[3D_Web]] · [[WebGL]] - 변형: [[Babylon_js]] - 응용: [[React_Three_Fiber]] · [[drei]] · [[WebXR]] - Adjacent: [[Shader]] · [[WebGPU]] ## 🤖 LLM 활용 **언제**: 매 scene scaffold, 매 shader translate, 매 r3f component generation. **언제 X**: 매 production shader optimization — 매 hand-tune 필요. ## ❌ 안티패턴 - **Forgetting dispose**: 매 GPU memory leak. - **`new THREE.X` in render loop**: 매 GC pressure. - **No `setPixelRatio`**: 매 retina blurry. - **Many individual meshes**: 매 instancing 의 사용. - **Direct DOM rerender on every frame**: 매 r3f 의 자동 loop 무시. ## 🧪 검증 / 중복 - Verified (three.js r170 docs, react-three/fiber docs, mrdoob, 2026). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — Three.js r170 with WebGPU, TSL, r3f, instancing |