본문 바로가기
Frontend2026년 3월 15일8분 읽기

Three.js 입문 — 브라우저에서 3D 그래픽 시작하기

YS
김영삼
조회 491

Three.js 기초

Three.js는 WebGL을 쉽게 사용할 수 있게 해주는 JavaScript 3D 라이브러리입니다. 복잡한 WebGL API를 추상화하여 직관적인 API로 3D 그래픽을 구현할 수 있습니다.

기본 구성 요소

import * as THREE from 'three';

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1a1a2e);

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.set(0, 2, 5);

const renderer = new THREE.WebGLRenderer({
  antialias: true,
  alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);

3D 객체 생성

const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
const boxMaterial = new THREE.MeshStandardMaterial({
  color: 0x00ff88,
  metalness: 0.3,
  roughness: 0.4
});
const box = new THREE.Mesh(boxGeometry, boxMaterial);
box.position.set(-2, 0.5, 0);
box.castShadow = true;
scene.add(box);

const sphereGeometry = new THREE.SphereGeometry(0.7, 32, 32);
const sphereMaterial = new THREE.MeshStandardMaterial({
  color: 0xff6b6b,
  metalness: 0.7,
  roughness: 0.2
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(0, 0.7, 0);
sphere.castShadow = true;
scene.add(sphere);

const torusGeometry = new THREE.TorusGeometry(0.5, 0.2, 16, 32);
const torusMaterial = new THREE.MeshStandardMaterial({ color: 0x4ecdc4 });
const torus = new THREE.Mesh(torusGeometry, torusMaterial);
torus.position.set(2, 0.7, 0);
torus.castShadow = true;
scene.add(torus);

const planeGeometry = new THREE.PlaneGeometry(10, 10);
const planeMaterial = new THREE.MeshStandardMaterial({
  color: 0x333333,
  side: THREE.DoubleSide
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
scene.add(plane);

조명 설정

const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 10, 5);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
scene.add(directionalLight);

const pointLight = new THREE.PointLight(0xff9900, 1, 10);
pointLight.position.set(0, 3, 0);
scene.add(pointLight);

애니메이션 루프

const clock = new THREE.Clock();

function animate() {
  requestAnimationFrame(animate);
  const elapsed = clock.getElapsedTime();

  box.rotation.y = elapsed * 0.5;
  box.rotation.x = elapsed * 0.3;

  sphere.position.y = 0.7 + Math.sin(elapsed * 2) * 0.3;

  torus.rotation.x = elapsed;
  torus.rotation.z = elapsed * 0.5;

  renderer.render(scene, camera);
}

animate();

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

카메라 제어 (OrbitControls)

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.minDistance = 2;
controls.maxDistance = 20;
controls.maxPolarAngle = Math.PI / 2;

function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
}

성능 최적화 팁

기법설명
지오메트리 병합BufferGeometryUtils.mergeGeometries로 드로우콜 감소
LOD거리에 따라 디테일 수준 변경
Frustum Culling카메라 밖 객체 자동 제외 (기본 활성)
텍스처 압축KTX2 / Basis 텍스처 포맷 사용
인스턴싱InstancedMesh로 동일 객체 대량 렌더링
  • Three.js는 초보자도 쉽게 3D를 시작할 수 있는 최고의 라이브러리
  • React에서는 React Three Fiber(@react-three/fiber)로 선언적 사용 가능
  • GLTF/GLB 포맷으로 Blender 등에서 만든 3D 모델 임포트 가능
  • WebGPU 지원이 추가되어 차세대 그래픽 API 활용 가능
  • drei(@react-three/drei) 라이브러리로 유용한 헬퍼 컴포넌트 활용

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록