기술 노트2025년 4월 20일
Konva.js + Three.js로 2D→3D 도면 변환 구현하기
작성: Hiramise 팀
Hiramise는 2D 도면과 3D 뷰어가 동일한 JSON 데이터를 공유합니다. 사용자가 2D에서 장비를 이동하면 3D가 즉시 반영됩니다. 이 글에서는 그 구현 핵심을 공유합니다.
좌표계 설계 원칙
2D와 3D는 좌표계가 다릅니다. Konva.js는 좌상단 원점(Y축 하향), Three.js는 중앙 원점(Y축 상향)입니다. 두 시스템을 잇는 변환 함수가 핵심입니다.
- 내부 저장 단위: mm 정수 (부동소수점 누적 오차 방지)
- 2D 렌더링 시: mm → 픽셀 (DPR·줌 배율 반영)
- 3D 렌더링 시: mm → Three.js 단위 (1 unit = 100mm 채택)
- Y축 반전: floorY = roomHeight_mm − konvaY
공유 JSON 스키마
도면 데이터는 단일 JSON으로 저장됩니다. boundary(벽), equipment(장비 목록), metadata(업종·국가)의 3개 섹션으로 구성됩니다.
- boundary: 외벽 + 내벽 폴리라인, mm 좌표
- equipment: id, archetype, x_mm, y_mm, width_mm, depth_mm, rotation_deg
- metadata: country, category, specialty, format
3D 렌더링 파이프라인
각 equipment 항목은 archetype ID로 GLB 모델을 매핑합니다. width_mm와 depth_mm에 따라 모델을 자동 스케일링해 실제 치수와 일치시킵니다.
- Tier 1 (55%): Three.js parametric 코드 생성 — GLB 파일 없음
- Tier 2–4: R2에 업로드된 GLB → useGLTF로 로드
- 스케일링: scale.x = targetWidth / modelNativeWidth
- 회전: rotation.y = −(rotation_deg × π / 180) (Y축 반전 보정)
이 구조 덕분에 새 장비 카탈로그 추가 시 GLB 파일과 archetype 매핑 한 줄만 추가하면 됩니다. 코어 렌더러 수정 없이 카탈로그를 확장할 수 있습니다.