ν‹°μŠ€ν† λ¦¬ λ·°

λ°˜μ‘ν˜•

πŸ“Œ Three.jsμ—μ„œ μ„±λŠ₯ μ΅œμ ν™” & λ‘œλ”© 속도 κ°œμ„ ν•˜κΈ°

μ§€κΈˆκΉŒμ§€ μš°λ¦¬λŠ” 3D λͺ¨λΈμ„ 뢈러였고, μ• λ‹ˆλ©”μ΄μ…˜κ³Ό μ‘°λͺ…을 μ μš©ν•˜μ—¬ ν˜„μ‹€μ μΈ 3D 씬을 κ΅¬μΆ•ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€.
ν•˜μ§€λ§Œ μ‹€μ œ μ„œλΉ„μŠ€μ— μ μš©ν•˜λ €λ©΄ μ„±λŠ₯ μ΅œμ ν™”κ°€ λ°˜λ“œμ‹œ ν•„μš”ν•©λ‹ˆλ‹€.
이번 κΈ€μ—μ„œλŠ” Three.js ν”„λ‘œμ νŠΈμ˜ μ„±λŠ₯을 ν–₯μƒμ‹œν‚€κ³  λ‘œλ”© 속도λ₯Ό κ°œμ„ ν•˜λŠ” 핡심 μ „λž΅λ“€μ„ μ†Œκ°œν•©λ‹ˆλ‹€.


πŸš€ 1. μ™œ μ„±λŠ₯ μ΅œμ ν™”κ°€ μ€‘μš”ν•œκ°€?

3DλŠ” λΈŒλΌμš°μ €μ—μ„œ λ§Žμ€ GPU λ¦¬μ†ŒμŠ€λ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ—,
μ΅œμ ν™”λ₯Ό ν•˜μ§€ μ•ŠμœΌλ©΄ λ‹€μŒκ³Ό 같은 λ¬Έμ œκ°€ λ°œμƒν•©λ‹ˆλ‹€:

문제 원인

❌ 느린 초기 λ‘œλ”© GLB/GLTF 파일이 λ„ˆλ¬΄ 큼
❌ ν”„λ ˆμž„ λ“œλž λ‹€κ°ν˜• 수(poly count)κ°€ λ„ˆλ¬΄ 많음
❌ μ‘°μž‘ μ§€μ—° 그림자, μ‘°λͺ…, μ• λ‹ˆλ©”μ΄μ…˜ κ³ΌλΆ€ν•˜
❌ λͺ¨λ°”일 ν™˜κ²½μ—μ„œ μž‘λ™ λΆˆκ°€ ν•˜λ“œμ›¨μ–΄ 사양 미지원

🧠 2. μ„±λŠ₯ μ΅œμ ν™”λ₯Ό μœ„ν•œ 핡심 μ „λž΅ 7κ°€μ§€


βœ… 1) GLB λͺ¨λΈ μ••μΆ• (Draco Compression)

  • GLB/GLTF λͺ¨λΈμ˜ μš©λŸ‰μ„ μ΅œλŒ€ 90%κΉŒμ§€ 쀄일 수 μžˆλŠ” μ••μΆ• 방식
  • @react-three/dreiμ—μ„œ useGLTFλŠ” μžλ™μœΌλ‘œ Dracoλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.

πŸ“Œ μ••μΆ• λͺ¨λΈ μ‚¬μš© μ˜ˆμ‹œ

const { scene } = useGLTF('/models/robot_draco.glb', true);  // draco: true

πŸ“Œ Draco 압좕은 Blenderμ—μ„œ κ°€λŠ₯ν•˜λ©°, glTF-Pipeline CLIλ‘œλ„ μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


βœ… 2) Lazy Loading (Suspense + dynamic import)

λ°˜μ‘ν˜•
  • 초기 화면에 ν•„μš”ν•˜μ§€ μ•Šμ€ λ¦¬μ†ŒμŠ€λŠ” λ‚˜μ€‘μ— λ‘œλ“œν•˜λŠ” 방식
  • React.lazy와 Suspenseλ₯Ό μ‚¬μš©

πŸ“Œ μ˜ˆμ‹œ μ½”λ“œ

import { Suspense, lazy } from 'react';

const HeavyModel = lazy(() => import('./HeavyModel'));

function Scene() {
  return (
    <Suspense fallback={<span>Loading...</span>}>
      <HeavyModel />
    </Suspense>
  );
}

βœ… 3) μ‘°λͺ… & 그림자 μ΅œμ ν™”

  • 그림자λ₯Ό μ‚¬μš©ν•  경우 μ„±λŠ₯이 κΈ‰κ²©νžˆ λ–¨μ–΄μ§ˆ 수 있음
  • ν•„μš”ν•œ κ²½μš°μ—λ§Œ castShadow, receiveShadow 적용
  • mapSize 쀄이고 distance μ œν•œν•˜κΈ°

πŸ“Œ 그림자 mapSize 쀄이기

<directionalLight
  castShadow
  shadow-mapSize-width={1024}
  shadow-mapSize-height={1024}
/>

βœ… 4) λͺ¨λΈ λ‹¨μˆœν™” (Low-Poly μ‚¬μš©)

  • High-poly λͺ¨λΈμ€ 수천 개의 μ‚Όκ°ν˜• → GPU λΆ€ν•˜
  • Blender, Sketchfab λ“±μ—μ„œ Low-Poly λͺ¨λΈ μ‚¬μš© ꢌμž₯

βœ… 5) Postprocessing μ΅œμ†Œν™” λ˜λŠ” 쑰건뢀 적용

  • Bloom, SSR, Outline 등은 맀우 λ¦¬μ†ŒμŠ€λ₯Ό 많이 μ‚¬μš©
  • UIμ—μ„œ On/Off 토글을 두어 쑰건뢀 μ‚¬μš©

βœ… 6) Renderer μ˜΅μ…˜ 쑰절

  • physicallyCorrectLights, toneMapping, antialias 등은 κΊΌλ‘κ±°λ‚˜ 쑰절 κ°€λŠ₯

πŸ“Œ Canvas μ„€μ • μ΅œμ ν™” μ˜ˆμ‹œ

<Canvas
  shadows
  dpr={window.devicePixelRatio}
  gl={{ antialias: false, physicallyCorrectLights: false }}
  camera={{ position: [0, 3, 5], fov: 50 }}
>

βœ… 7) FPS & μ„±λŠ₯ λͺ¨λ‹ˆν„°λ§ 도ꡬ ν™œμš©

  • @react-three/drei의 <Stats /> μ»΄ν¬λ„ŒνŠΈλ₯Ό ν™œμš©ν•˜μ—¬ FPS 및 λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰ 확인

πŸ“Œ μ˜ˆμ‹œ

import { Stats } from '@react-three/drei';

function Scene() {
  return (
    <>
      <Canvas>{/* ... */}</Canvas>
      <Stats />
    </>
  );
}

πŸ›  3. μ‹€μ „ 적용 μ˜ˆμ‹œ: μ΅œμ ν™” μ μš©ν•œ Viewer

import { Canvas } from '@react-three/fiber';
import { OrbitControls, useGLTF, Stats } from '@react-three/drei';
import { Suspense } from 'react';

function OptimizedModel() {
  const { scene } = useGLTF('/models/robot_draco.glb', true);
  return <primitive object={scene} scale={1.5} />;
}

export default function OptimizedViewer() {
  return (
    <>
      <Canvas
        shadows
        dpr={1.5}
        gl={{ antialias: false }}
        camera={{ position: [0, 2, 5], fov: 50 }}
      >
        <ambientLight intensity={0.3} />
        <directionalLight castShadow position={[5, 5, 5]} intensity={1} />
        <Suspense fallback={<span>λͺ¨λΈ λ‘œλ”© 쀑...</span>}>
          <OptimizedModel />
        </Suspense>
        <OrbitControls />
      </Canvas>
      <Stats />
    </>
  );
}

βœ… 4. μ΅œμ ν™” ν›„ κΈ°λŒ€ 효과

ν•­λͺ© μ΅œμ ν™” μ „ μ΅œμ ν™” ν›„

λͺ¨λΈ λ‘œλ”© 속도 5초 이상 1~2초
FPS 15~30 50~60
λͺ¨λ°”일 λŒ€μ‘ μ œν•œμ  μ›ν™œν•¨
초기 ν™”λ©΄ λ Œλ”λ§ λ²„λ²…μž„ λΆ€λ“œλŸ¬μ›€

🎯 5. λ‹€μŒ κΈ€ 예고: μ™„μ„±λœ μ‚¬μ΄νŠΈ 배포 & ν™œμš©

이제 μš°λ¦¬κ°€ λ§Œλ“  3D λ·°μ–΄ μ‚¬μ΄νŠΈλŠ” μ΅œμ ν™”κΉŒμ§€ 마친 μƒνƒœμž…λ‹ˆλ‹€.
λ‹€μŒ κΈ€μ—μ„œλŠ” 이 μ‚¬μ΄νŠΈλ₯Ό Netlify / Vercel에 λ°°ν¬ν•˜κ³  μ‹€μ œλ‘œ ν™œμš©ν•˜λŠ” 방법을 μ†Œκ°œν•©λ‹ˆλ‹€.
λ˜ν•œ, μ‹€μ œ 포트폴리였/μ‡Όν•‘λͺ°/κ²Œμž„ μ•„μ΄ν…œ λ·°μ–΄λ‘œ ν™•μž₯ν•˜λŠ” 아이디어도 ν•¨κ»˜ λ‹€λ£Ήλ‹ˆλ‹€.

βœ… λ‹€μŒ 편 예고:
"Three.js 3D λ·°μ–΄ μ‚¬μ΄νŠΈλ₯Ό μ‹€μ œλ‘œ λ°°ν¬ν•˜κ³  ν™œμš©ν•˜λŠ” 방법" πŸš€


 

β€» 이 ν¬μŠ€νŒ…μ€ 쿠팑 νŒŒνŠΈλ„ˆμŠ€ ν™œλ™μ˜ μΌν™˜μœΌλ‘œ, 이에 λ”°λ₯Έ μΌμ •μ•‘μ˜ 수수료λ₯Ό μ œκ³΅λ°›μŠ΅λ‹ˆλ‹€.
곡지사항
μ΅œκ·Όμ— 올라온 κΈ€
μ΅œκ·Όμ— 달린 λŒ“κΈ€
Total
Today
Yesterday
링크
Β«   2025/04   Β»
일 μ›” ν™” 수 λͺ© 금 ν† 
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
κΈ€ 보관함
λ°˜μ‘ν˜•