0. 이 보드를 읽는 법

탭① 은 구조 결정용 Lo-fi 와이어프레임(회색/점선), 탭② 는 같은 구조가 실제로 동작하는 시뮬레이션, 탭③ 은 이 문서만 보고 동일 앱을 재구현할 수 있게 만든 명세다.
와이어프레임에 색·폰트를 넣지 않는 이유: "예쁜가?" 논쟁이 "구조가 맞는가?"를 덮기 때문. 시각 디자인은 Step 3에서 결정한다.

1. 전체 앱 셸 — Desktop (1440px 기준)

3-Panel: 좌우 고정폭(280 / 260px), 중앙 Preview만 유동(1fr). 창을 늘리면 작업 공간만 넓어진다.

1 Header (48px)
UndoRedo
SaveAutoDuplicate
TemplateImport
설정
PDFPPTX Export
2 Left Panel (280px)
아코디언: 문서 정보
제목 / 부제목
작성자 / 부서 / 날짜
아코디언: 본문
본문 textarea
결론 / 성과 / 요약
아코디언: 텍스트 스타일
Font·Size·B/I/U·Color·정렬…
3 Preview — 작업대 + A4
제목 영역
본문 텍스트
그래프 / 이미지
결론 / 로고
4 Asset Library (260px)
탭: Images·Shapes·Clipboard…
Clipboard
Img 1
Img 2
Img 3
Img 4
Uploads
+ 파일 업로드
5 Status Bar (28px)
저장 상태
선택 요소 (x, y, w, h — mm)
Zoom: Fit · 100 · 150 · 200%
  • 1
    Header — 좌→우 = 사용 빈도 순(이력→파일→문서). Export는 우측 끝: Primary CTA는 우측 끝이라는 데스크톱 앱 관례.
  • 2
    Left Panel — Form 입력, 아코디언 섹션. 280px = 한글 레이블+입력창의 최소폭이자 Preview를 침범하지 않는 최대폭.
  • 3
    Preview — 어두운 pasteboard 위 흰 A4(297:210 고정). 기본 Fit.
  • 4
    Asset Library — 칩 탭 + 썸네일 2열(260px에서 식별 가능한 최소 썸네일 확보).
  • 5
    Status Bar — 좌: 저장 상태 / 중: 선택 요소 mm 좌표 / 우: Zoom(우하단 = PowerPoint·Figma 관례).

2. 반응형 전략 — 패널은 접히고, A4는 지켜진다

어떤 화면에서도 A4 비율은 변하지 않는다. 대신 좌우 패널이 형태를 바꾼다.

Header
Left
A4
Asset
Status

Desktop ≥ 1200px — 3-Panel 상시 표시

Header (축약)
A4
Status
하단 탭: [입력] [에셋] → 오버레이

Tablet 768~1199px — 패널이 오버레이 drawer로

Header
A4
Status
하단 탭바

Mobile ≤ 480px — 보기 중심, 풀스크린 시트

이것은 프로토타입입니다. 실제 앱(Step 4~)은 core/model/engine/ui/interactions 모듈로 분리해 다시 작성합니다. 해볼 것: 왼쪽 폼 입력 → 즉시 반영 · 요소 드래그 — 다른 요소의 행/열과 정렬되면 분홍 가이드라인에 자석처럼 흡착 · 핸들 리사이즈 — 변이 다른 요소에 흡착되고, W/H가 다른 요소와 같아지면 크기 배지가 분홍으로 강조 · 오른쪽 에셋을 A4로 드래그&드롭 · 이미지 복사 후 ⌘+V → Clipboard 탭에 저장 · Delete/방향키(⇧=10mm) · ⌘Z/⌘⇧Z · 줌 버튼

클론용 상세 스펙 v1 (Step 2 기준)

이 문서만 보고 동일한 앱 셸을 재구현할 수 있도록 작성한 명세. 시각 디자인 값(색·폰트)은 Step 3에서 확정되며, 여기의 색은 임시값이다.

1. 제품 정의

  • 웹 폼 기반 보고서 에디터. 좌측 폼 입력 → 중앙 A4 Landscape Preview 실시간 반영 → 최종 .pptx Export (텍스트/이미지/도형이 실제 PowerPoint 객체).
  • 핵심 원칙 WYSIWYE: Preview와 Export는 동일한 JSON 문서 모델을 읽는다. DOM을 읽어 Export하지 않는다.
  • 기술 제약: HTML + CSS + Vanilla JS. 프레임워크 금지. .pptx 생성은 PptxGenJS 라이브러리 사용(로컬 보관).

2. 좌표계·단위 (가장 중요)

  • 문서 규격: A4 Landscape = 297 × 210 mm 고정.
  • 내부 저장 단위: mm (요소의 x, y, w, h 전부). 폰트 크기만 pt.
  • 렌더 변환: px = mm × scale, scale = 렌더된 A4 폭(px) ÷ 297.
  • 100% 줌 정의: 96dpi 기준 1mm = 96 ÷ 25.4 ≈ 3.7795px → A4 폭 ≈ 1122px.
  • 폰트 렌더: px = pt × (25.4/72) × scale (1pt = 25.4/72 mm).
  • Export 변환: inch = mm ÷ 25.4 (PptxGenJS는 inch 단위).
  • 모든 변환 함수는 단일 모듈(engine/units.js)에만 둔다.

3. 앱 셸 치수

영역Grid Area크기비고
Header1행 전체높이 48px하단 1px 보더
Left Panel2행 1열폭 280px 고정세로 스크롤
Preview2행 2열유동(1fr), 최소 480pxpasteboard 배경은 패널보다 어둡게
Asset Library2행 3열폭 260px 고정세로 스크롤
Status Bar3행 전체높이 28px상단 1px 보더

CSS Grid 한 개로 구현: grid-template-rows: 48px 1fr 28px; grid-template-columns: 280px 1fr 260px;

4. Header 버튼 인벤토리 (좌→우)

그룹버튼동작단축키구현 Step
이력Undo / RedoCommand 스택 이동. 불가 시 disabled⌘Z / ⌘⇧Z11
파일Save / Auto Save / DuplicatelocalStorage 저장 · 자동저장 토글 · 슬라이드 복제⌘S11
문서Template / Import템플릿 갤러리 · JSON 불러오기10~11
우측설정 / PDF / PPTX Export(Primary)설정 모달 · PDF(향후) · PptxGenJS로 .pptx 생성⌘E12

5. Left Panel 필드 인벤토리

섹션필드타입바인딩 대상
문서 정보제목 / 부제목 / 작성자 / 부서 / 날짜text / date inputtitle, subtitle, meta 요소
본문본문 / 결론 / 성과 / 요약 / 표 설명 / 그래프 설명 / 체크리스트textarea, 동적 리스트각 text 요소
텍스트 스타일Font, Size(pt), B/I/U, Color, Line Height, Letter Spacing, 정렬, Bullet, Numberingselect / toggle / color선택된 요소의 style
  • 입력 → 모델 갱신 → Preview 리렌더 (단방향). 입력 이벤트는 input(즉시 반영), 이력 기록은 change(입력 완료 시 1회)로 분리.
  • 섹션은 아코디언. 스타일 섹션은 선택 요소가 없으면 비활성 + 안내문.

6. Preview 동작 스펙

동작스펙
선택클릭 → 파란 1.5px 아웃라인 + 핸들 8개(모서리4 + 변4, 8×8px 흰 사각+파랑 보더). 빈 곳 클릭 → 해제. Shift+클릭 → 다중 선택(추가/제거)
이동드래그. mm 단위로 환산해 모델 갱신. Delete로 삭제. 방향키 1mm, Shift+방향키 10mm
리사이즈모서리 핸들 = 대각(이미지는 비율 고정), 변 핸들 = 단방향. 최소 크기 10×6mm
스냅 — 이동드래그 중 내 요소의 좌/중/우·상/중/하 6개 기준선이 다른 요소의 변/중심 + 페이지 중심과 2mm 이내로 접근하면 흡착(마그네틱) + 분홍 1px 가이드라인 표시. 축마다 가장 가까운 후보 1개에만 스냅
스냅 — 리사이즈① 변 마그네틱: 움직이는 변이 다른 요소의 변/중심에 2mm 이내 → 흡착 + 가이드라인. ② 크기 마그네틱: W 또는 H가 다른 요소의 W/H와 같아지는 순간 흡착 + 우하단 크기 배지(W×H mm)가 분홍 강조. 같은 축에서는 변 흡착이 크기 흡착보다 우선
복사/붙여넣기⌘C 선택 요소 복사 → ⌘V 시 +5mm 오프셋으로 복제
ZoomFit(기본: 영역-패딩에 맞춤) / 100 / 150 / 200%. 초과 시 스크롤. (실제 구현: ⌘+휠 줌 추가)

7. Asset Library 스펙

  • 칩 탭: Images / Charts / Icons / Shapes / Tables / Clipboard / Recent / Uploads (시뮬레이션은 4개만).
  • 모든 에셋은 draggable. dragstart 시 dataTransfer에 JSON {kind, ...payload} 저장 → A4 drop 시 마우스 위치를 mm로 환산해 요소 생성.
  • Clipboard: documentpaste 이벤트에서 이미지 항목을 DataURL로 읽어 자동 저장 → 썸네일 그리드 표시 → 드래그로 배치. (실제 구현: IndexedDB 영속화)
  • Uploads: 파일 선택/드래그 업로드 → 목록 유지.

8. Status Bar 스펙

  • 좌: 저장 상태 3단계 — ● 편집 중… 저장 중✓ 저장됨 HH:MM.
  • 중: 선택 요소 이름 + x, y · w×h (mm, 소수 1자리). 없으면 "선택 없음".
  • 우: Zoom 버튼 그룹(현재 값 강조).

9. 문서 JSON 모델 (Step 10에서 확정, 현재 형태)

{
  "report": {
    "title": "2026년 상반기 실적 보고",
    "pageSize": { "w": 297, "h": 210 },          // mm, A4 Landscape
    "slides": [
      {
        "id": "slide-1",
        "elements": [                              // z-order 순 평면 배열
          {
            "id": "title",
            "type": "text",                        // text|image|shape|line|table|chart
            "frame": { "x": 20, "y": 15, "w": 190, "h": 20 },   // mm
            "constraint": { "minW": 10, "minH": 6,
                            "aspectLock": false, "priority": 100 },
            "style": { "font": "system", "size": 24,            // pt
                       "bold": true, "italic": false, "underline": false,
                       "color": "#222222", "align": "left",
                       "lineHeight": 1.4, "letterSpacing": 0 },
            "content": "2026년 상반기 실적 보고"
          },
          { "id": "img-1", "type": "image",
            "frame": { "x": 190, "y": 60, "w": 85, "h": 60 },
            "constraint": { "aspectLock": true, "priority": 60 },
            "src": "data:image/png;base64,..." }
        ]
      }
    ]
  }
}

10. 반응형 브레이크포인트

범위레이아웃
≥ 1200px3-Panel 상시 표시
1024~1199pxAsset Library가 오버레이 drawer로 (토글 버튼)
768~1023px양쪽 패널 모두 오버레이. 하단에 [입력]/[에셋] 탭
≤ 480px보기/간단 수정 중심. 패널은 풀스크린 시트. Header 아이콘 축약

모든 브레이크포인트에서 A4는 297:210 비율 유지 (aspect-ratio 또는 scale 계산).

11. 시뮬레이션(탭②)과 실제 구현의 차이

  • 시뮬레이션은 단일 파일 프로토타입. 실제 앱은 core/(store·events·history) · model/ · engine/(layout·units) · ui/ · interactions/ · export/ 모듈로 분리.
  • 시뮬레이션의 Undo는 전체 스냅샷 방식. 실제 구현은 Command 패턴({do, undo})으로 메모리 효율화.
  • Layout Engine(Priority 기반 자동 축소), 다중 선택 러버밴드, 요소 간 스냅, 인라인 텍스트 편집(더블클릭)은 Step 7~11에서 구현.