📌 프로젝트 초기 세팅 (Next.js + TypeScript + Three.js)
# Next.js 프로젝트 생성 npx create-next-app@latest just-meow-it --typescript # 필요한 패키지 설치 cd just-meow-it yarn install yarn add @react-three/fiber @react-three/drei three
@react-three/fiber
=== R3F → Three.js를 React에서 사용할 수 있도록 도와주는 라이브러리. 즉 Three.js의 React 버전@react-three/drei
→ Three.js 유틸리티 (카메라, 조명, OrbitControls 등)three
→ Three.js 라이브러리
📌 기본 코드 (고양이 모델 띄우기)
이제 기본적인 3D 고양이를 화면에 띄워보겠다.🐱💬
그 이전에 우선 Sketchfab 사이트에서 적절한 고양이 모델을 다운로드 받은 뒤, public
폴더 아래 넣어두었다.
1️⃣ 고양이 모델 컴포넌트 (components/CatModel.tsx
)
"use client"; import { Canvas } from "@react-three/fiber"; import { OrbitControls, useGLTF } from "@react-three/drei"; import { Suspense } from "react"; const CatModel = () => { const { scene } = useGLTF("/cat_model/scene.gltf"); // public 폴더의 glTF 모델 로드 return <primitive object={scene} scale={0.06} position={[0, -1, 0]} />; }; const CatScene = () => { return ( <Canvas camera={{ position: [0, 2, 5] }}> <ambientLight intensity={0.5} /> <directionalLight position={[2, 2, 2]} /> <Suspense fallback={null}> <CatModel /> </Suspense> <OrbitControls /> </Canvas> ); }; export default CatScene;
코드에 대한 자세한 설명은 아래에서....
2️⃣ 레이아웃 (app/layout.tsx)
import type { Metadata } from "next"; import "./globals.css"; export const metadata: Metadata = { title: "Just Meow It", description: "고민이 있을 때는 고양이의 조언을 들어보세요.", }; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="ko"> <head /> <body className="bg-gray-100"> <div className="container mx-auto">{children}</div> </body> </html> ); }
메인 페이지의 공통 레이아웃을 작성하는 파일이다. 필요한 메타데이터 코드도 미리 넣어주었다.
3️⃣메인 페이지 (app/page.tsx)
import CatModel from "@/components/CatModel"; export default function Home() { return ( <main className="flex flex-col items-center justify-center h-screen gap-6"> <h1 className="text-3xl font-bold">🐱 고양이의 가르침</h1> <CatModel /> </main> ); }
루트 도메인에서 화면에 표시될 데이터를 불러온다.
간단하게 제목과 고양이 모델 컴포넌트 2개만 렌더링해보았다.
📌 실행해보기
yarn dev

📌 catModel에 대한 상세한 설명
"use client"; import { Canvas } from "@react-three/fiber"; import { OrbitControls, useGLTF } from "@react-three/drei"; import { Suspense } from "react"; const CatModel = () => { const { scene } = useGLTF("/cat_model/scene.gltf"); // public 폴더의 glTF 모델 로드 return <primitive object={scene} scale={0.06} position={[0, -1, 0]} />; }; const CatScene = () => { return ( <Canvas camera={{ position: [0, 2, 5] }}> <ambientLight intensity={0.5} /> <directionalLight position={[2, 2, 2]} /> <Suspense fallback={null}> <CatModel /> </Suspense> <OrbitControls /> </Canvas> ); }; export default CatScene;
위 코드는 react-three/fiber
와 @react-three/drei
를 사용해 3D 모델을 로드하고 렌더링하는 코드이다.
"use client";
가장 먼저, 컴포넌트가 클라이언트 사이드에서만 렌더링되도록 지정해 준다. 해당 키워드를 통해서버 사이드 렌더링(SSR)을 비활성화하고 컴포넌트를 클라이언트 전용으로 처리하게 만들 수 있다.
🤔 왜 클라이언트 사이드 렌더링 처리를 하는가?
Three.js는 3D 그래픽 렌더링을 위한 클라이언트 측 라이브러리로, 브라우저에서 실행되는 WebGL을 사용한다.
WebGL은 서버에서 실행되지 않고 클라이언트의 브라우저 환경에서만 실행된다. 따라서 Three.js를 사용할 때는 클라이언트 사이드에서만 렌더링되도록 해야 한다.
import { Canvas } from "@react-three/fiber"; import { OrbitControls, useGLTF } from "@react-three/drei"; import { Suspense } from "react";
@react-three/fiber
에서 Canvas는 Three.js 씬을 그릴 캔버스이다. 3D 모델을 포함한 장면을 렌더링하는 역할을 한다.@react-three/drei
는 Three.js를 React에서 사용하기 위한 유용한 유틸리티와 컴포넌트들을 제공한다.OrbitControls
: 카메라가 3D 모델 주위를 회전할 수 있게 도와주는 컨트롤러useGLTF
: GLTF (GL Transmission Format) 형식의 3D 모델을 로드하는 훅
- Suspense는 React에서 비동기 컴포넌트를 처리할 때 로딩 상태를 관리하는 컴포넌트이다. 여기서는 모델 로딩 중에 대기 상태를 처리하기 위해 사용된다.
const CatModel = () => { const { scene } = useGLTF("/cat_model/scene.gltf"); // public 폴더의 glTF 모델 로드 return <primitive object={scene} scale={0.06} position={[0, -1, 0]} />; };
- CatModel 컴포넌트는
useGLTF
훅을 사용하여 cat_model/scene.gltf 경로의 3D 모델을 로드한다.- useGLTF("/cat_model/scene.gltf"): public 폴더에 위치한 GLTF 모델 파일을 비동기적으로 로드한다. 로딩된 모델은 scene 객체로 반환된다.
- <primitive object={scene} />: 로드된 GLTF 모델을 React 컴포넌트에서 렌더링하기 위해
primitive
를 사용한다. primitive는 Three.js 객체를 React 컴포넌트로 변환할 때 사용된다. - scale={0.06}: 모델의 크기를 0.06배로 조정한다.
- position={[0, -1, 0]}: 모델의 위치를 (x, y, z) 좌표로 설정한다.
const CatScene = () => { return ( <Canvas camera={{ position: [0, 2, 5] }}> <ambientLight intensity={0.5} /> <directionalLight position={[2, 2, 2]} /> <Suspense fallback={null}> <CatModel /> </Suspense> <OrbitControls /> </Canvas> ); };
- CatScene 컴포넌트는 3D 모델을 렌더링하는 장면을 구성한다.
- <Canvas camera={{ position: [0, 2, 5] }}>: Canvas는
react-three/fiber
에서 사용하는 컨테이너로, 3D 씬을 렌더링하는 역할을 한다.camera
: 카메라의 초기 위치를 설정하는 속성position: [0, 2, 5]
: 카메라가 3D 씬의 [0, 2, 5] 위치에 배치됨을 의미
- <ambientLight intensity={0.5} />: Ambient light는 3D 씬에서 모든 객체를 균일하게 밝히는 조명이다. intensity로 밝기를 설정할 수 있다.
- <directionalLight position={[2, 2, 2]} />: Directional light는 태양과 같은 강한 빛을 시뮬레이션한다. position 속성으로 빛의 위치를 지정한다.
- <Suspense fallback={null}>: Suspense는 CatModel 컴포넌트가 로딩되는 동안의 로딩 상태를 처리하는데 사용된다. 현재는
fallback={null}
로 설정해서, 로딩 중에 아무것도 표시되지 않고 있다. - <OrbitControls />: 사용자가 마우스를 이용해 3D 씬을 회전, 확대/축소할 수 있게 해주는 컨트롤러이다.
- <Canvas camera={{ position: [0, 2, 5] }}>: Canvas는
📌 참고한 문서
- Three.js: Three.js의 공식 사이트
- @react-three/fiber: React에서 Three.js를 사용할 수 있게 해주는 라이브러리, 공식 GitHub 레파지토리
- @react-three/drei: Three.js와 React를 결합하는데 유용한 다양한 추가 컴포넌트를 제공하는 라이브러리, 공식 GitHub 레파지토리
배포한 사이트 링크
Just Meow It | 고양이의 조언으로 고민 해결하기
Just Meow It | 고양이의 조언으로 고민 해결하기
고양이의 지혜를 통해 고민을 해결해 보세요.
just-meow-it.timeqlife.com
다음 주 주말에 오픈그래프도 추가해야지...
'웹 프로젝트 > 😺Just Meow It: 고양이의 조언' 카테고리의 다른 글
[😺Just Meow It: 고양이의 조언] Three.js + Next.js / vercel 배포 및 구글/네이버 검색어 등록, 구글 애드센스 광고 추가 (1) | 2025.04.05 |
---|