← Back
jikime

jikime/model-house

View on GitHub ↗https://model-house.vercel.app ↗
Stars
9
Forks
1
Watchers
9
Open issues
0
Contributors
2
Language
TypeScript
License
—
Default branch
main
Created Oct 1, 2026Updated Oct 1, 2026

Star growth

Today—
This week—
This month—

Star history will appear here once this repo has been tracked for a couple of days.

README

우리집 모델하우스

입주 전, 우리 집을 먼저 걸어보는 사이버 모델하우스입니다. 평면 타입을 고르면 가구까지 갖춘 3D 모델하우스로 들어가고, 유상옵션·인테리어 스타일·바닥재를 바꿔 보며 추가금을 바로 확인합니다. 한국 아파트의 전형적인 평면(59㎡·84㎡)과 벽식구조, 발코니 확장 같은 분양 옵션을 반영했고, 직접 벽을 그려 "내 평면"을 만들 수도 있습니다. 한국어가 기본이고 영어로 전환할 수 있습니다.

평면과 가격은 국내 아파트 일반형과 분양 사례를 참고한 예시입니다. 특정 단지의 평면이 아니며, 실제 분양가·옵션가와 다릅니다.

주요 기능

타입 선택 — 첫 화면에서 평면 타입을 고릅니다.

타입 구조 전용 / 공급 특징
59A 3Bay 판상형 59.85㎡ / 80.9㎡ (24평형) 맞통풍, 효율 설계
84A 4Bay 판상형 84.95㎡ / 112.4㎡ (34평형) 맞통풍, 알파룸, 워크인 드레스룸
84B 3Bay 타워형 84.80㎡ / 113.2㎡ (34평형) 남·동 2면 개방 코너 거실, 팬트리
내 평면 직접 그림 벽으로 둘러싼 영역에서 자동 계산 빈 도면 또는 분양 타입 복사

면적은 한국 전용면적 산정 기준처럼 벽 중심선으로 계산합니다(서비스 면적인 발코니·다용도실 제외).

3D 둘러보기

  • 2D 평면에서 벽이 솟아오르며 3D로 전환, 조감 보기
  • 방 탭(거실·주방·안방…)을 누르면 그 방의 눈높이 시점으로 이동해 제자리에서 둘러보기, 미니맵에 현재 위치 표시
  • 모델하우스 투어: 현관부터 방마다 자동으로 이동하며 면적·바닥재·그 방에 적용된 옵션을 설명
  • 걸어보기: 데스크톱은 WASD + 마우스, 터치 기기는 가상 조이스틱. 벽·가구·유리문 충돌, 현관 단차, 문 열고 닫기
  • 일조 시간 슬라이더, 야경, 단면(벽 자르기), 가구·이름 표시 켜고 끄기

꾸미기 패널

  • 유상옵션: 발코니 확장, 시스템에어컨, 빌트인 가전 패키지(인덕션·식기세척기·김치냉장고), 드레스룸 시스템장, 현관 중문, 침실 2·3 통합 — 고르면 2D·3D 평면이 실제로 바뀝니다
  • 스타일·마감: 인테리어 스타일 패키지 3종(내추럴 우드 · 모던 화이트 · 호텔 그레이지), 벽지 6색, 방마다 바닥재(강마루·강화마루·원목마루·포세린 타일·타일·논슬립 타일·장판·대리석) — 분양 기본 사양 대비 차액을 원화로 계산
  • 가구: 한국 가정 가구·가전 60여 종(4인 소파, 안마의자, 김치냉장고, 워시타워 등)을 끌어 놓거나 눌러 추가, 선택해서 크기·색·회전 수정

2D 평면 — 벽 중심선 치수 체인, 구조(내력벽) 표시, 거리 측정, 가구 배치, 1:50 축척 표시

견적 요약 — 면적(전용·공급·서비스·실사용), 스타일, 선택한 옵션과 바닥재 변경 내역, 예상 추가금 합계. 인쇄·이미지 저장

평면 편집기(내 평면)

  • 벽 그리기: 클릭으로 연속 그리기, 끝점·벽선·50mm 격자에 붙기, 숫자 입력 + Enter로 정확한 길이
  • 문·창·미닫이·개구부를 벽 위에 놓기, 선택해서 폭·열림 방향·현관문 지정
  • 벽 끝점으로 길이 조절, 가운데 손잡이로 평행 이동(모서리로 이어진 벽도 함께 늘어남)
  • 벽으로 둘러싸인 영역을 자동으로 방으로 인식, 방 종류·이름 지정
  • 분양 타입을 복사해 고치거나 빈 도면에서 시작. 만든 평면도 3D 둘러보기·걸어보기·견적에 그대로 쓰입니다

그 밖에 — 실행 취소/다시 실행, 브라우저에 자동 저장(다시 열면 보던 모델하우스로), 저장 파일 내보내기·불러오기(형식 검증), 이미지 저장, 한국어/영어, 태블릿·휴대폰 화면 대응

시작하기

Node.js 20 이상이 필요합니다.

npm install
npm run dev          # 개발 서버 (http://localhost:5173)

빌드:

npm run build        # dist/ — 정적 호스팅용. 3D 엔진은 처음 3D로 들어갈 때 별도 파일로 로드
npm run preview      # dist/ 미리 보기
npm run build:single # dist-single/index.html 한 파일 — 서버 없이 더블클릭으로 열기용 (시스템 한글 폰트 사용)
npm run typecheck    # 타입 검사

테스트

npm test             # 단위 테스트 (Vitest)
npm run test:e2e     # 브라우저 테스트 (빌드 → 미리보기 서버 → Playwright)
  • 단위 테스트 (tests/*.test.ts): 평면 데이터 검증 — 전용면적 범위, 공간끼리 겹침, 현관에서 모든 공간까지 동선(격자 탐색), 가구·설비가 벽에 박히지 않는지, 방 시점 카메라 여유, 벽 그래프에서 방 찾기
  • 브라우저 테스트 (tests/e2e/*.py): 첫 화면 → 3D 입장 → 방 시점·투어 → 옵션·스타일·추가금 → 타입 전환 → 2D·가구 → 견적 → 걸어보기 → 영어 → 필요할 때만 그리기 확인 → 저장·복원 → 가져오기 검증 → WebGL 불가 환경, 평면 편집기 전 과정
    • 필요: python3, pip install playwright, playwright install chromium (또는 CHROMIUM_PATH 지정). 파이썬 경로는 E2E_PYTHON으로 바꿀 수 있습니다

단축키

키 동작
T 2D / 3D 전환
V / M 선택 / 측정 (2D)
R / Shift+R 선택한 가구 90° 회전
Delete 선택한 가구 삭제
Ctrl/⌘ + D 선택한 가구 복제
Ctrl/⌘ + Z, Ctrl/⌘ + Shift + Z 실행 취소, 다시 실행
방향키 (Shift) 선택한 가구 10mm (100mm) 이동
F, + / - 화면에 맞춤, 확대 / 축소 (2D)
Shift + F 전체 화면
Esc 선택 해제 · 그리기 끝내기
걸어보기: WASD / 방향키, Shift, E 이동, 빠르게, 문 열고 닫기
평면 편집: V W D N 선택 · 벽 · 문 · 창 도구

구조

Vite + TypeScript, UI 프레임워크 없이 DOM을 직접 다룹니다. 2D 평면도는 SVG, 3D는 Three.js r160입니다.

src/
  main.ts          시작점: 렌더링 연결, 이벤트 바인딩
  core/            상태·실행 취소·저장(state), 현재 평면·견적(plan), 편집 동작(actions), 이름 표시
  data/apt/        아파트 타입 스키마, 평면 빌더(벽 중심선 → 형상), 59A·84A·84B, 벽 그래프 방 찾기, 내 평면
  data/            바닥재 단가(materials), 스타일·벽지(styles), 유상옵션(options), 가구 목록(library)
  i18n/            한국어(ko)·영어(en) 사전 — 키가 두 사전에 모두 있어야 타입 검사 통과
  plan2d/          SVG 평면도, 확대·이동, 붙이기, 포인터 조작, 평면 편집기, 작은 평면 그림
  ui/              첫 화면, 상단 바, 꾸미기 패널, 방 탭·미니맵, 추가금·견적, 투어, 보기 모드, 편집 패널
  view3d/          3D 장면(index), 가구·설비 모델(furniture), 기본 도형(prims), 재질(materials)
tests/             평면·방 찾기 단위 테스트, e2e/ 브라우저 테스트

도면 상태는 브라우저 localStorage(wmh:state-v3)에 저장됩니다.

3D 성능

  • 필요할 때만 그리기: 카메라·애니메이션·문·걸어보기가 움직일 때만 렌더링하고, 가만히 있으면(걸어보기에서 서 있을 때 포함) GPU를 쓰지 않습니다
  • 화면 갱신 한 번에 최대 한 번: 다음 프레임 예약은 늘 하나뿐이고, 120·144·165Hz 모니터에서는 일정한 간격으로 건너뛰어 초당 60번 안팎만 그립니다
  • 카메라 관성은 시간 기준으로 줄여 느린 컴퓨터에서도 1.5초 안팎에 멈추고, 방 시점·전체 보기로 이동할 때 남은 관성을 버립니다
  • 캔버스 픽셀 상한(약 420만): 레티나·5K 모니터의 큰 창에서도 칠할 픽셀이 4배로 늘지 않습니다
  • 미리 준비: 첫 화면에 머무는 동안 WebGL·환경 반사맵·장면을 만들고 셰이더를 미리 컴파일해, 처음 3D로 들어갈 때 멈추지 않습니다. 이후 2D↔3D 전환에서는 바뀐 것만 다시 만듭니다
  • 전환 화면 안정: 카메라가 높을수록 근평면을 멀리 둬 깊이 정밀도를 확보하고(눌린 벽·가구가 바닥과 번갈아 보이는 떨림 방지), 천장은 처음부터 제 높이에 둬 그림자가 전환 도중 한 번에 바뀌지 않습니다
  • 그림자는 장면이 바뀔 때만 다시 계산합니다
  • 병합: 가구 하나를 재질별 메시 몇 개로, 벽·창틀·유리·천장·바닥은 재질별로 한 번에 합칩니다 (84A 기준 그림 호출 약 1,800 → 약 340)
  • 증분 갱신: 가구는 바뀐 것만 다시 만들고, 옮기기만 했으면 위치만 바꿉니다
  • 도형 재사용: 같은 치수의 가구 부품(상자·둥근 상자·원기둥·구)은 한 번만 계산해 스타일·옵션을 바꿀 때 다시 쓰고, 조명 원판은 재질 하나를 같이 씁니다
  • 점광원은 야경일 때만 두고 개수를 바꾸지 않아 셰이더 재컴파일을 피합니다

평면 타입 추가하기

src/data/apt/schema.ts의 AptType을 따라 src/data/apt/에 파일을 만들고 index.ts의 TYPES에 등록합니다.

  • walls: 벽 중심선(수평·수직), 두께, 종류(e 외벽 · b 내력벽 · n 경량벽 · low), 개구부(door · entry · window · slide · gap, 위치는 벽 방향 절대 좌표). when: 'ext'처럼 옵션 조건을 달 수 있습니다
  • rooms: 중심선 다각형, 종류, 기본 바닥재, 이름 위치, 서비스 면적 여부, 옵션에 따른 합치기(join), 방 시점(view)
  • fixtures: 주방 가구·욕실 도기·신발장·옵션 품목 같은 붙박이, furniture: 기본 연출 가구(스타일 색 역할 role)
  • options / price / tags / dims / entry

npm test가 전용면적·겹침·동선·충돌·시점을 검사하므로, 새 타입을 넣고 테스트를 통과시키면 됩니다.