탭① 은 구조 결정용 Lo-fi 와이어프레임(회색/점선), 탭② 는 같은 구조가 실제로 동작하는 시뮬레이션,
탭③ 은 이 문서만 보고 동일 앱을 재구현할 수 있게 만든 명세다.
와이어프레임에 색·폰트를 넣지 않는 이유: "예쁜가?" 논쟁이 "구조가 맞는가?"를 덮기 때문. 시각 디자인은 Step 3에서 결정한다.
3-Panel: 좌우 고정폭(280 / 260px), 중앙 Preview만 유동(1fr). 창을 늘리면 작업 공간만 넓어진다.
어떤 화면에서도 A4 비율은 변하지 않는다. 대신 좌우 패널이 형태를 바꾼다.
Desktop ≥ 1200px — 3-Panel 상시 표시
Tablet 768~1199px — 패널이 오버레이 drawer로
Mobile ≤ 480px — 보기 중심, 풀스크린 시트
이 문서만 보고 동일한 앱 셸을 재구현할 수 있도록 작성한 명세. 시각 디자인 값(색·폰트)은 Step 3에서 확정되며, 여기의 색은 임시값이다.
297 × 210 mm 고정.px = mm × scale, scale = 렌더된 A4 폭(px) ÷ 297.1mm = 96 ÷ 25.4 ≈ 3.7795px → A4 폭 ≈ 1122px.px = pt × (25.4/72) × scale (1pt = 25.4/72 mm).inch = mm ÷ 25.4 (PptxGenJS는 inch 단위).engine/units.js)에만 둔다.| 영역 | Grid Area | 크기 | 비고 |
|---|---|---|---|
| Header | 1행 전체 | 높이 48px | 하단 1px 보더 |
| Left Panel | 2행 1열 | 폭 280px 고정 | 세로 스크롤 |
| Preview | 2행 2열 | 유동(1fr), 최소 480px | pasteboard 배경은 패널보다 어둡게 |
| Asset Library | 2행 3열 | 폭 260px 고정 | 세로 스크롤 |
| Status Bar | 3행 전체 | 높이 28px | 상단 1px 보더 |
CSS Grid 한 개로 구현: grid-template-rows: 48px 1fr 28px; grid-template-columns: 280px 1fr 260px;
| 그룹 | 버튼 | 동작 | 단축키 | 구현 Step |
|---|---|---|---|---|
| 이력 | Undo / Redo | Command 스택 이동. 불가 시 disabled | ⌘Z / ⌘⇧Z | 11 |
| 파일 | Save / Auto Save / Duplicate | localStorage 저장 · 자동저장 토글 · 슬라이드 복제 | ⌘S | 11 |
| 문서 | Template / Import | 템플릿 갤러리 · JSON 불러오기 | — | 10~11 |
| 우측 | 설정 / PDF / PPTX Export(Primary) | 설정 모달 · PDF(향후) · PptxGenJS로 .pptx 생성 | ⌘E | 12 |
| 섹션 | 필드 | 타입 | 바인딩 대상 |
|---|---|---|---|
| 문서 정보 | 제목 / 부제목 / 작성자 / 부서 / 날짜 | text / date input | title, subtitle, meta 요소 |
| 본문 | 본문 / 결론 / 성과 / 요약 / 표 설명 / 그래프 설명 / 체크리스트 | textarea, 동적 리스트 | 각 text 요소 |
| 텍스트 스타일 | Font, Size(pt), B/I/U, Color, Line Height, Letter Spacing, 정렬, Bullet, Numbering | select / toggle / color | 선택된 요소의 style |
input(즉시 반영), 이력 기록은 change(입력 완료 시 1회)로 분리.| 동작 | 스펙 |
|---|---|
| 선택 | 클릭 → 파란 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 오프셋으로 복제 |
| Zoom | Fit(기본: 영역-패딩에 맞춤) / 100 / 150 / 200%. 초과 시 스크롤. (실제 구현: ⌘+휠 줌 추가) |
draggable. dragstart 시 dataTransfer에 JSON {kind, ...payload} 저장 → A4 drop 시 마우스 위치를 mm로 환산해 요소 생성.document의 paste 이벤트에서 이미지 항목을 DataURL로 읽어 자동 저장 → 썸네일 그리드 표시 → 드래그로 배치. (실제 구현: IndexedDB 영속화)● 편집 중 → … 저장 중 → ✓ 저장됨 HH:MM.x, y · w×h (mm, 소수 1자리). 없으면 "선택 없음".{
"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,..." }
]
}
]
}
}
| 범위 | 레이아웃 |
|---|---|
| ≥ 1200px | 3-Panel 상시 표시 |
| 1024~1199px | Asset Library가 오버레이 drawer로 (토글 버튼) |
| 768~1023px | 양쪽 패널 모두 오버레이. 하단에 [입력]/[에셋] 탭 |
| ≤ 480px | 보기/간단 수정 중심. 패널은 풀스크린 시트. Header 아이콘 축약 |
모든 브레이크포인트에서 A4는 297:210 비율 유지 (aspect-ratio 또는 scale 계산).
core/(store·events·history) · model/ · engine/(layout·units) · ui/ · interactions/ · export/ 모듈로 분리.{do, undo})으로 메모리 효율화.