본문 바로가기
React

[React] 3D 아바타 컴포넌트 만들기

by teamnova 2025. 8. 11.
728x90

 

안녕하세요 오늘은 React + Three.js 기반의 3D 아바타 컴포넌트 예제를 만들어보겠습니다. 

우선 3D 렌더링 라이브러리를 필수로 설치해야합니다 

 

 

 

1. 관련 라이브러리 설치 

- 이 예제는 TailwindCSS로 스타일링 돼있으니 Tailwind도 같이 세팅해줍니다. 

npm install @react-three/fiber @react-three/drei three
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

 

 

 

three.js docs

 

threejs.org

 

 

 

2. 코드 전체 

import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
import { OrbitControls, Box, Sphere } from '@react-three/drei'

// 간단한 3D 아바타
function SimpleAvatar() {
  const avatarRef = useRef()
  const [hovered, setHover] = useState(false)
  const [isWaving, setIsWaving] = useState(false)

  useFrame((state) => {
    if (avatarRef.current) {
      // 부드러운 호흡 애니메이션
      avatarRef.current.position.y = Math.sin(state.clock.elapsedTime * 2) * 0.1
     
      // 손 흔들기 애니메이션
      if (isWaving) {
        avatarRef.current.rotation.y = Math.sin(state.clock.elapsedTime * 5) * 0.3
      }
    }
  })

  return (
    <group
      ref={avatarRef}
      onClick={() => setIsWaving(!isWaving)}
      onPointerOver={() => setHover(true)}
      onPointerOut={() => setHover(false)}
      scale={hovered ? 1.1 : 1}
    >
      {/* 머리 */}
      <Sphere
        args={[0.4, 16, 16]}
        position={[0, 1.8, 0]}
      >
        <meshStandardMaterial color="#ffdbac" />
      </Sphere>
     
      {/* 몸통 */}
      <Box
        args={[0.8, 1.2, 0.4]}
        position={[0, 0.6, 0]}
      >
        <meshStandardMaterial color="#4a90e2" />
      </Box>
     
      {/* 왼팔 */}
      <Box
        args={[0.15, 0.8, 0.15]}
        position={[-0.6, 0.8, 0]}
        rotation={[0, 0, isWaving ? Math.sin(Date.now() * 0.01) * 0.5 : 0]}
      >
        <meshStandardMaterial color="#ffdbac" />
      </Box>
     
      {/* 오른팔 */}
      <Box
        args={[0.15, 0.8, 0.15]}
        position={[0.6, 0.8, 0]}
      >
        <meshStandardMaterial color="#ffdbac" />
      </Box>
     
      {/* 왼다리 */}
      <Box
        args={[0.2, 0.8, 0.2]}
        position={[-0.2, -0.6, 0]}
      >
        <meshStandardMaterial color="#2c3e50" />
      </Box>
     
      {/* 오른다리 */}
      <Box
        args={[0.2, 0.8, 0.2]}
        position={[0.2, -0.6, 0]}
      >
        <meshStandardMaterial color="#2c3e50" />
      </Box>
     
      {/* 눈 */}
      <Sphere
        args={[0.05, 8, 8]}
        position={[-0.15, 1.9, 0.3]}
      >
        <meshStandardMaterial color="#000000" />
      </Sphere>
     
      <Sphere
        args={[0.05, 8, 8]}
        position={[0.15, 1.9, 0.3]}
      >
        <meshStandardMaterial color="#000000" />
      </Sphere>
     
      {/* 입 */}
      <Box
        args={[0.2, 0.05, 0.05]}
        position={[0, 1.7, 0.3]}
      >
        <meshStandardMaterial color="#000000" />
      </Box>
    </group>
  )
}

// 아바타 씬
function AvatarScene() {
  return (
    <div className="w-full h-96">
      <Canvas
        camera={{ position: [0, 2, 5], fov: 60 }}
        style={{ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' }}
      >
        {/* 조명 */}
        <ambientLight intensity={0.6} />
        <pointLight position={[10, 10, 10]} intensity={1} />
        <pointLight position={[-10, -10, -10]} intensity={0.3} color="#ff6b6b" />
       
        {/* 아바타 */}
        <SimpleAvatar />
       
        {/* 컨트롤 */}
        <OrbitControls
          enablePan={false}
          enableZoom={true}
          enableRotate={true}
          maxDistance={10}
          minDistance={3}
        />
      </Canvas>
    </div>
  )
}

// 메인 컴포넌트
function AvatarPortfolio() {
  return (
    <section className="min-h-screen flex flex-col justify-center items-center bg-gradient-to-br from-blue-900 via-purple-900 to-pink-900 py-20 px-6">
      <div className="max-w-4xl mx-auto text-center">
        <h2 className="text-5xl font-bold text-white mb-6">
          Meet My 3D Avatar
        </h2>
        <p className="text-xl text-gray-300 mb-12 max-w-2xl mx-auto">
          Click on the avatar to make it wave! Drag to rotate, scroll to zoom.
        </p>
       
        <div className="bg-black/20 rounded-2xl p-8 backdrop-blur-sm border border-white/10">
          <AvatarScene />
        </div>
       
        <div className="mt-8 text-gray-300">
          <p className="text-lg">
            💡 <strong>Interactions:</strong> Click to wave • Hover to scale • Drag to rotate
          </p>
        </div>
      </div>
    </section>
  )
}

export default AvatarPortfolio

 

 

- 먼저 Canvas 로 3D 공간을 생성해줍니다. 

- SimpleAvatar 라이브러리의 기본 도형들로 사람 모양을 만들어줍니다