BabylonJS × Blender 1회차 : 전체 파이프라인 개요 + 개발환경 세팅



BabylonJS × Blender 1회차 : 전체 파이프라인 개요 + 개발환경 세팅

목표: Blender→GLB→BabylonJS 흐름을 한 번에 이해
Blender: 기본 화면/오브젝트 조작(이동/회전/스케일), 저장
BabylonJS: 로컬 서버, 기본 Scene/Camera/Light
산출물: 빈 씬 + 기본 카메라/조명 템플릿
체크포인트: 브라우저 콘솔 에러 0, 리로드 즉시 표시


요약

이 시리즈의 핵심은 “모델을 만들고(Blender) → 파일로 내보내고(GLB) → 엔진에서 불러와서(BabylonJS) 화면에 안정적으로 보여주는 것”입니다. 초보자 단계에서 가장 많이 막히는 지점은 실력이 아니라 파이프라인과 개발환경입니다. 예를 들어 file://로 HTML을 열면 CORS나 리소스 로딩 제한 때문에 GLB/텍스처가 깨질 수 있고, Blender에서 단위/스케일이 정리되지 않으면 엔진에서 크기가 이상해 보일 수 있습니다. 1회차에서는 “정상적으로 실행되는 기본 템플릿”을 먼저 확보하고, 다음 회차부터 모델/텍스처/애니메이션을 얹어도 흔들리지 않는 기반을 만드는 데 집중합니다.


목차


1) 전체 파이프라인 한 장 요약

Blender와 BabylonJS를 함께 쓸 때의 흐름은 아래 5단계로 정리하면 안정적으로 운영할 수 있습니다.

단계 도구 무엇을 한다 초보자 체크
1) 모델링/배치 Blender 오브젝트 생성, 위치/회전/스케일 조정, 저장 조작 단축키(G/R/S) 익숙해지기
2) 내보내기 Blender GLB로 export(모델/머티리얼/텍스처 포함) 스케일/피벗/텍스처 경로가 깨지지 않게
3) 정적 호스팅 로컬 서버 브라우저에서 동일 출처로 리소스 제공 file:// 금지, http로 실행
4) 엔진 로딩 BabylonJS Scene/Camera/Light 구성, GLB를 씬에 붙임 콘솔 에러 0, 네트워크 404 0
5) 검증/반복 Blender + BabylonJS 크기/피벗/재질 확인 → 다시 export 리로드 즉시 반영되는 흐름 유지

1회차에서는 3)과 4)를 확실히 잡습니다. 여기서 기반이 흔들리면 이후 회차(모델 로딩/텍스처/애니메이션)에서 계속 같은 문제를 반복하게 됩니다.


2) Blender 기본 화면과 오브젝트 조작(이동/회전/스케일)

Blender를 “정교한 모델링 툴”로 보기 전에, 일단은 3D 오브젝트를 다루는 기본 조작기로 이해하시면 됩니다. BabylonJS에 들어갈 모델은 결국 “3D 공간에서 어떤 위치/회전/크기를 가졌는가”가 핵심이기 때문입니다.

2-1) 화면 구성(초보자 기준 핵심만)

  • Viewport(3D 뷰): 오브젝트를 보고 움직이는 메인 영역입니다.
  • Outliner: 씬의 오브젝트 목록(계층 구조)이 보입니다. 나중에 부모/자식 구조를 잡을 때 중요합니다.
  • Properties: 오브젝트/재질/렌더 설정을 조정합니다.

2-2) 오브젝트 조작 3종 세트(G/R/S)

  • 이동(Move): G 키 → 마우스 이동 → 확정 클릭(또는 Enter)
  • 회전(Rotate): R 키 → 회전 → 확정
  • 스케일(Scale): S 키 → 크기 조절 → 확정

축으로 제한하면 조작이 훨씬 안정적입니다.

  • GX 또는 Y 또는 Z: 해당 축으로만 이동
  • RZ: Z축 회전(바닥 기준 회전이 많아 가장 자주 씁니다)
  • SX: X축 방향으로만 스케일

2-3) 저장(가장 중요한 습관)

  • Blender 파일(.blend)은 “원본”입니다. 엔진에 넣는 GLB는 “산출물”입니다.
  • 원본과 산출물을 분리하면, 수정/재export가 빠르고 안전해집니다.


3) 개발환경 세팅: 폴더 구조 + 로컬 서버

BabylonJS는 브라우저에서 동작합니다. 브라우저는 보안 정책상 로컬 파일 접근이 제한될 수 있으므로, 반드시 로컬 서버로 실행하는 습관이 필요합니다. 이것이 “콘솔 에러 0”의 첫 번째 조건입니다.

3-1) 추천 폴더 구조(최소 템플릿)

1회차 산출물은 빈 씬 템플릿이지만, 이후 GLB가 들어올 것을 고려해 폴더를 미리 잡아두면 편합니다.

project-root/
  index.html
  assets/
    models/
    textures/
  src/
    main.js  (선택: 분리하고 싶을 때)

이번 글의 예시는 단순성을 위해 index.html 하나로 진행하지만, 폴더는 위처럼 만들어두는 것을 권장합니다.

3-2) 로컬 서버 실행 옵션(가장 쉬운 것부터)

방법 명령 장점 주의
Python 내장 서버 python -m http.server 5500 설치 부담이 낮음 폴더에서 실행해야 함
Node http-server npx http-server -p 5500 간단, 널리 사용 Node 필요
VSCode Live Server 확장 실행 리로드가 편함 확장 설치 필요

명령어를 바로 복사해 실행할 수 있도록 예시를 정리합니다.

# (1) Python
python -m http.server 5500

# (2) Node (설치형)
npm i -g http-server
http-server -p 5500

# (3) Node (설치 없이 npx)
npx http-server -p 5500

서버를 실행한 뒤 브라우저에서 http://localhost:5500로 접속하면 됩니다. 이때부터 “리로드 즉시 표시”가 가능한 개발 루프가 만들어집니다.


Node http-server를 사용하여 서버 접속을 실행했습니다.

4) BabylonJS 기본 템플릿: Scene/Camera/Light

이 시리즈에서는 “항상 같은 템플릿에서 시작”하는 것을 권장합니다. 템플릿이 안정적이면 문제를 분리하기 쉬워집니다.

  • 화면이 안 나오면: 카메라/조명/렌더 루프 문제일 확률이 큽니다.
  • 모델만 안 나오면: 모델 경로/로딩/스케일 문제로 범위를 좁힐 수 있습니다.

4-1) 빈 씬 + 기본 카메라/조명 템플릿(산출물)

아래 index.html은 1회차 산출물입니다. 바닥(ground)과 기준 오브젝트(토러스/박스)를 넣어 “지금 정상적으로 렌더링 중”임을 확실히 보여주도록 구성했습니다. 콘솔 에러 0, 리로드 즉시 표시 체크에 적합합니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>BabylonJS × Blender Pipeline - Template (Empty Scene)</title>
  <style>
    html, body { width:100%; height:100%; margin:0; overflow:hidden; font-family:system-ui, -apple-system, Segoe UI, Roboto, sans-serif; }
    #renderCanvas { width:100%; height:100%; display:block; touch-action:none; }
    #hud {
      position: fixed; left: 12px; top: 12px;
      width: min(520px, 94vw);
      padding: 12px 12px 10px;
      border-radius: 14px;
      background: rgba(0,0,0,0.55);
      border: 1px solid rgba(255,255,255,0.18);
      color: rgba(255,255,255,0.92);
      z-index: 10;
    }
    #hudTitle { margin:0 0 8px 0; font-size:14px; font-weight:700; }
    #stats { font-size:12px; line-height:1.55; }
    .row { display:flex; justify-content:space-between; gap:10px; }
    .k { color: rgba(255,255,255,0.75); }
    .v { font-variant-numeric: tabular-nums; }
    #hint { margin-top:8px; color: rgba(255,255,255,0.72); font-size:12px; line-height:1.45; }
    #hint code { background: rgba(255,255,255,0.12); padding: 1px 6px; border-radius: 6px; }
  </style>
  <script src="https://cdn.babylonjs.com/babylon.js"></script>
</head>
<body>
  <div id="hud">
    <p id="hudTitle">빈 씬 템플릿(카메라/조명/바닥) - 체크포인트용</p>
    <div id="stats">
      <div class="row"><span class="k">FPS</span><span class="v" id="fps">-</span></div>
      <div class="row"><span class="k">Camera Radius</span><span class="v" id="rad">-</span></div>
      <div class="row"><span class="k">Tip</span><span class="v">Wheels/Zoom로 카메라 이동 가능</span></div>
    </div>
    <div id="hint">
      <div>체크: 브라우저 콘솔 에러 0, 새로고침 시 즉시 화면 표시</div>
      <div>다음 회차에서 GLB 로딩 코드가 이 템플릿에 추가됩니다.</div>
    </div>
  </div>

  <canvas id="renderCanvas"></canvas>

  <script>
    const canvas = document.getElementById("renderCanvas");
    const engine = new BABYLON.Engine(canvas, true);

    const ui = {
      fps: document.getElementById("fps"),
      rad: document.getElementById("rad")
    };

    let scene, camera;

    function createScene() {
      const s = new BABYLON.Scene(engine);
      s.clearColor = new BABYLON.Color4(0.06, 0.07, 0.09, 1.0);

      // Camera: ArcRotate는 초보자에게 가장 안정적(드래그 회전/휠 줌/패닝 가능)
      camera = new BABYLON.ArcRotateCamera(
        "camera",
        Math.PI / 2,
        Math.PI / 2.6,
        16,
        new BABYLON.Vector3(0, 1.2, 0),
        s
      );
      camera.attachControl(canvas, true);
      camera.wheelDeltaPercentage = 0.01;

      // Light: 가장 단순한 조명 조합(기본 확인용)
      const hemi = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), s);
      hemi.intensity = 1.0;

      // Ground: 공간 감각용
      const ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 40, height: 40 }, s);
      const gmat = new BABYLON.StandardMaterial("gmat", s);
      gmat.diffuseColor = new BABYLON.Color3(0.14, 0.15, 0.17);
      gmat.alpha = 0.98;
      ground.material = gmat;

      // Reference Objects: "정상 렌더링 중" 확인용
      const refMat = new BABYLON.StandardMaterial("refMat", s);
      refMat.diffuseColor = new BABYLON.Color3(0.75, 0.78, 0.90);

      const box = BABYLON.MeshBuilder.CreateBox("refBox", { size: 1.2 }, s);
      box.position.set(0, 0.6, 0);
      box.material = refMat;

      const ring = BABYLON.MeshBuilder.CreateTorus("refRing", { diameter: 3.0, thickness: 0.18, tessellation: 72 }, s);
      ring.position.set(-4.5, 1.4, -3.5);
      ring.material = refMat;

      // 약간의 방향감(축 느낌)
      const poleMat = new BABYLON.StandardMaterial("poleMat", s);
      poleMat.diffuseColor = new BABYLON.Color3(0.24, 0.26, 0.30);

      for (let i = 0; i < 10; i++) {
        const pole = BABYLON.MeshBuilder.CreateCylinder("pole" + i, { height: 3.5, diameter: 0.25, tessellation: 24 }, s);
        pole.position.set((Math.random() - 0.5) * 28, 1.75, (Math.random() - 0.5) * 28);
        pole.material = poleMat;
      }

      return s;
    }

    scene = createScene();

    engine.runRenderLoop(() => {
      scene.render();
      ui.fps.textContent = engine.getFps().toFixed(1);
      ui.rad.textContent = camera.radius.toFixed(2);

      const ring = scene.getMeshByName("refRing");
      if (ring) ring.rotation.y += 0.006;
    });

    window.addEventListener("resize", () => engine.resize());
  </script>
</body>
</html>

이 템플릿이 “매번 정상 실행”되면, 이후 회차에서는 여기 위에 GLB 로딩(ImportMesh/SceneLoader)과 로딩 UI를 단계적으로 추가해도 흔들리지 않습니다.


브라우저에서 접속한 모습니다.
개발자 콘솔에서 오류가 없음을 확인할 수 있습니다.


5) 체크포인트: 콘솔 에러 0, 리로드 즉시 표시

초보자에게 가장 좋은 품질 기준은 “그럴듯해 보이는 것”이 아니라 반복 가능한 실행 안정성입니다. 이번 회차의 체크포인트는 아래 2개입니다.

체크포인트 확인 방법 정상 기준 실패 시 의심
브라우저 콘솔 에러 0 DevTools Console 확인 오류/경고 최소, 빨간 에러 없음 CDN 차단, 스크립트 경로, 문법 오류
리로드 즉시 표시 F5/새로고침 화면이 즉시 렌더링되고 HUD가 표시 로컬 서버 미사용, 캐시/서버 경로 문제


6) 자주 막히는 원인과 해결

  • 증상: 화면이 검은색만 보임
    가능 원인: 카메라가 씬을 보지 못함, 렌더 루프 미실행, 스크립트 로딩 실패
    대응: 콘솔에서 babylon.js 로딩(404 여부) 확인, engine.runRenderLoop 존재 확인, 카메라 타깃/반경 값을 기본값으로 되돌리기
  • 증상: 콘솔에 CORS/Blocked 관련 메시지
    가능 원인: file://로 실행하거나, 리소스를 다른 출처로 잘못 요청
    대응: 반드시 로컬 서버(http://localhost)로 실행
  • 증상: 화면은 나오는데 조작이 안 됨
    가능 원인: camera.attachControl이 빠졌거나 캔버스 이벤트가 막힘
    대응: attachControl(canvas, true) 확인, CSS에서 캔버스가 100%인지 확인
  • 증상: 새로고침할 때마다 가끔 깨짐
    가능 원인: 브라우저 캐시/서비스워커/불안정한 개발 루프
    대응: 캐시 비활성(DevTools Network), 간단한 서버로 통일, 파일 위치/경로 고정


7) 실행 단계(실습 순서)

  • 프로젝트 폴더를 만들고 index.html을 생성합니다.
  • 위의 “빈 씬 템플릿” 코드를 그대로 붙여넣습니다.
  • 로컬 서버를 실행합니다(권장: python -m http.server 5500 또는 npx http-server -p 5500).
  • 브라우저에서 http://localhost:5500로 접속합니다.
  • DevTools를 열고 Console 에러가 0인지 확인합니다.
  • 새로고침(F5) 후 즉시 HUD/바닥/기준 오브젝트가 보이는지 확인합니다.
  • Blender를 열고 기본 큐브를 선택한 뒤 G/R/S로 이동/회전/스케일을 짧게 연습하고 저장합니다(원본 저장 습관).
  • 오늘의 산출물 기준을 통과하면, 다음 회차부터 assets/models에 GLB를 추가하고 BabylonJS에서 로딩하는 단계로 진행합니다.


8) 추가로 생각해볼 점

  • “템플릿이 곧 생산성”입니다: 매번 새로 세팅하면 작은 실수로 시간이 많이 소모됩니다. 1회차 템플릿을 레포의 시작점으로 고정해두면 이후 속도가 크게 올라갑니다.
  • 모델 문제가 생겨도 엔진 템플릿은 정상이어야 합니다: GLB를 얹기 전에도 항상 화면이 나오는 상태를 유지하면, 문제 범위를 빠르게 좁힐 수 있습니다.
  • 단위/스케일은 앞으로 계속 등장합니다: 지금은 조작만 익히지만, 다음 회차에서 “왜 모델이 너무 크거나 작은가”가 본격적으로 나오므로, Blender에서 “현실적인 크기” 감각을 조금씩 맞춰두는 것이 좋습니다.
  • 체크포인트는 습관입니다: 콘솔 에러 0, 리로드 즉시 표시를 매 회차 반복하면 “원인 추적”이 쉬워지고, 파이프라인이 단단해집니다.


이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.



Reactions

댓글 쓰기

0 댓글