13 KiB
13 KiB
POP v4 통합 설계 모드 스펙
작성일: 2026-02-04 최종 업데이트: 2026-02-04 상태: Phase 3 완료 (visibility + 줄바꿈 컴포넌트)
개요
v3/v4 탭을 제거하고, v4 자동 모드를 기본으로 하되 모드별 오버라이드 기능을 지원하는 통합 설계 방식.
핵심 개념
기존 방식 (v3)
4개 모드 각각 설계 필요
태블릿 가로: 버튼 → col 1, row 1
태블릿 세로: 버튼 → col 1, row 5 (따로 설정)
모바일 가로: 버튼 → col 1, row 1 (따로 설정)
모바일 세로: 버튼 → col 1, row 10 (따로 설정)
새로운 방식 (v4 통합)
기본: 태블릿 가로에서 규칙 설정
버튼 → width: fill, height: 48px
결과: 모든 모드에 자동 적용
태블릿 가로: 버튼 너비 1024px, 높이 48px
태블릿 세로: 버튼 너비 768px, 높이 48px
모바일 가로: 버튼 너비 667px, 높이 48px
모바일 세로: 버튼 너비 375px, 높이 48px
예외: 특정 모드에서 편집하면 오버라이드
모바일 세로: 버튼 높이 36px (수동 설정)
현재 UI (Phase 1.5 완료)
┌─────────────────────────────────────────────────────────────────┐
│ ← 목록 화면명 *변경됨 [↶][↷] 자동 레이아웃 (v4) [저장] │
├─────────────────────────────────────────────────────────────────┤
│ 편집 중: v4 (자동 반응형) │
│ 규칙 기반 레이아웃 │
├────────────┬────────────────────────────────────┬───────────────┤
│ 컴포넌트 │ 미리보기: [모바일↕][모바일↔] │ 속성 │
│ │ [태블릿↕][태블릿↔(기본)] │ │
│ 필드 │ 너비: [====●====] 1024 x 768 │ │
│ 버튼 │ │ │
│ 리스트 │ ┌──────────────────────────────┐ │ 탭: 크기 │
│ 인디케이터 │ │ [필드1] [필드2] [필드3] │ │ 설정 │
│ 스캐너 │ │ [필드4] [Spacer] [버튼] │ │ 표시 ⬅ 🆕│
│ 숫자패드 │ │ │ │ 데이터 │
│ 스페이서 │ │ (가로 배치 + 자동 줄바꿈) │ │ │
│ 줄바꿈 🆕 │ │ (스크롤 가능) │ │ │
│ │ └──────────────────────────────┘ │ │
│ │ 태블릿 가로 (1024x768) │ │
└────────────┴────────────────────────────────────┴───────────────┘
레이아웃 방식 (업계 표준)
| 서비스 | 방식 |
|---|---|
| Figma | Auto Layout (Flexbox) |
| Webflow | Flexbox + CSS Grid |
| FlutterFlow | Row/Column/Stack |
| Adalo 2.0 | Flexbox + Constraints |
| POP v4 | Flexbox (horizontal + wrap) |
특수 컴포넌트 사용법
Spacer (빈 공간)
[버튼A] [Spacer(fill)] [버튼B] → 버튼B가 오른쪽 끝으로
[Spacer] [컴포넌트] [Spacer] → 컴포넌트가 가운데로
[Spacer(fill)] [컴포넌트] → 컴포넌트가 오른쪽으로
줄바꿈 (Break) 🆕 Phase 3
[필드A] [필드B] [줄바꿈] [필드C] → 필드C가 새 줄로 이동
태블릿: [필드A] [필드B] [필드C] ← 줄바꿈 숨김 (한 줄)
모바일: [필드A] [필드B] ← 줄바꿈 표시 (두 줄)
[필드C]
프리셋 버튼 (4개 모드)
| 버튼 | 해상도 | 설명 |
|---|---|---|
| 모바일↕ | 375 x 667 | 모바일 세로 |
| 모바일↔ | 667 x 375 | 모바일 가로 |
| 태블릿↕ | 768 x 1024 | 태블릿 세로 |
| 태블릿↔* | 1024 x 768 | 태블릿 가로 (기본) |
레이아웃 판별 로직
// 새 화면 또는 빈 레이아웃 → v4로 시작
const hasValidLayout = loadedLayout && loadedLayout.version;
const hasComponents = loadedLayout?.components &&
Object.keys(loadedLayout.components).length > 0;
if (hasValidLayout && hasComponents) {
// v4면 v4, 그 외 v3로 변환
} else {
// v4로 새로 시작
}
오버라이드 동작 (Phase 2 예정)
자동 감지 방식
- 사용자가 **태블릿 가로(기본)**에서 편집 → 기본 규칙 저장
- 사용자가 다른 모드에서 편집 → 해당 모드 오버라이드 자동 저장
- 편집 안 한 모드 → 기본 규칙에서 자동 계산
편집 상태 표시
| 상태 | 버튼 색상 | 설명 |
|---|---|---|
| 기본 (태블릿 가로) | 강조 + "(기본)" | 항상 표시 |
| 자동 | 기본 색상 | 편집 안 함 |
| 편집됨 | 강조 색상 | 오버라이드 있음 |
되돌리기
- 편집된 모드에만 "자동으로 되돌리기" 버튼 활성화
- 클릭 시 오버라이드 삭제 → 기본 규칙 복원
데이터 구조
PopLayoutDataV4 (Phase 2에서 수정 예정)
interface PopLayoutDataV4 {
version: "pop-4.0";
root: PopContainerV4;
components: Record<string, PopComponentDefinitionV4>;
dataFlow: PopDataFlow;
settings: PopGlobalSettingsV4;
// 모드별 오버라이드 (Phase 2에서 추가)
overrides?: {
mobile_portrait?: ModeOverride;
mobile_landscape?: ModeOverride;
tablet_portrait?: ModeOverride;
// tablet_landscape는 기본이므로 오버라이드 없음
};
}
interface ModeOverride {
components?: Record<string, Partial<PopComponentDefinitionV4>>;
containers?: Record<string, Partial<PopContainerV4>>;
}
PopComponentDefinitionV4 (Phase 3에서 수정 예정)
interface PopComponentDefinitionV4 {
type: PopComponentType;
label?: string;
size: PopSizeConstraintV4;
alignSelf?: "start" | "center" | "end" | "stretch";
// 모드별 표시 설정 (Phase 3에서 추가)
visibility?: {
mobile_portrait?: boolean; // 기본 true
mobile_landscape?: boolean; // 기본 true
tablet_portrait?: boolean; // 기본 true
tablet_landscape?: boolean; // 기본 true
};
}
컴포넌트 표시/숨김 (Phase 3 예정)
업계 표준 (Webflow, Figma)
- 삭제가 아닌 숨김 처리
- 특정 모드에서만
display: none - 언제든 다시 표시 가능
UI (속성 패널)
┌─────────────────────────┐
│ 버튼 │
├─────────────────────────┤
│ 표시 설정 │
│ [x] 모바일 세로 │
│ [x] 모바일 가로 │
│ [x] 태블릿 세로 │
│ [x] 태블릿 가로 │
│ │
│ (체크 해제 = 숨김) │
└─────────────────────────┘
구현 상태
Phase 1: 기본 구조 (완료)
- v3/v4 탭 제거 (자동 판별)
- 새 화면 → v4로 시작
- 기존 v3 화면 → v3로 로드 (하위 호환)
- 4개 프리셋 버튼 (모바일↕, 모바일↔, 태블릿↕, 태블릿↔)
- 기본 프리셋 표시 (태블릿 가로 + "(기본)")
- 슬라이더 유지 (320~1200px, 비율 유지)
- ComponentPaletteV4 생성
Phase 1.5: Flexbox 가로 배치 (완료)
- Undo/Redo (Ctrl+Z / Ctrl+Shift+Z, 데스크탑 모드와 동일 방식)
- 드래그 리사이즈 핸들
- Flexbox 가로 배치 (
direction: horizontal,wrap: true) - 컴포넌트 타입별 기본 크기 설정
- Spacer 컴포넌트 (
pop-spacer) - 컴포넌트 순서 변경 (드래그 앤 드롭)
- 디바이스 스크린 무한 스크롤
Phase 1.6: 비율 스케일링 시스템 (완료)
- 기준 너비 1024px (10인치 태블릿 가로)
- 최대 너비 1366px (12인치 태블릿)
- 뷰포트 감지 및 resize 이벤트 리스너
- 컴포넌트 크기 스케일 적용 (fixedWidth/Height)
- 컨테이너 스케일 적용 (gap, padding)
- 디자인 모드 분리 (scale=1)
- DndProvider 에러 수정
Phase 2: 오버라이드 기능 (다음)
- ModeOverride 데이터 구조 추가
- 편집 감지 → 자동 오버라이드 저장
- 편집 상태 표시 (버튼 색상)
- "자동으로 되돌리기" 버튼
Phase 3: 컴포넌트 표시/숨김
- visibility 속성 추가
- 속성 패널 체크박스 UI
- 렌더러에서 visibility 처리
Phase 4: 순서 오버라이드
- 모드별 children 순서 오버라이드
- 드래그로 순서 변경 UI
관련 파일
| 파일 | 역할 | 상태 |
|---|---|---|
PopDesigner.tsx |
v3/v4 통합 디자이너 | 완료 |
PopCanvasV4.tsx |
v4 캔버스 (4개 프리셋 + 슬라이더) | 완료 |
PopFlexRenderer.tsx |
v4 Flexbox 렌더러 + 비율 스케일링 | 완료 |
ComponentPaletteV4.tsx |
v4 컴포넌트 팔레트 | 완료 |
ComponentEditorPanelV4.tsx |
v4 속성 편집 패널 | 완료 |
pop-layout.ts |
v3/v4 타입 정의 | 완료, Phase 2-3에서 수정 예정 |
page.tsx (뷰어) |
v4 뷰어 + viewportWidth 감지 | 완료 |
비율 스케일링 시스템
업계 표준
Rockwell Automation HMI의 "Scale with Fixed Aspect Ratio" 방식 적용
원리
10인치(1024px) 기준으로 디자인 → 8~12인치에서 배치 유지, 크기만 비례 조정
계산
scale = viewportWidth / 1024
scaledWidth = originalWidth * scale
scaledHeight = originalHeight * scale
scaledGap = originalGap * scale
scaledPadding = originalPadding * scale
화면별 결과
| 화면 | scale | 200px 컴포넌트 | 8px gap |
|---|---|---|---|
| 8인치 (800px) | 0.78 | 156px | 6px |
| 10인치 (1024px) | 1.00 | 200px | 8px |
| 12인치 (1366px) | 1.33 | 266px | 11px |
| 14인치+ | 1.33 (max) | 266px + 여백 | 11px |
적용 위치
| 파일 | 함수/변수 | 역할 |
|---|---|---|
PopFlexRenderer.tsx |
BASE_VIEWPORT_WIDTH |
기준 너비 상수 (1024) |
PopFlexRenderer.tsx |
calculateSizeStyle(size, settings, scale) |
크기 스케일 적용 |
PopFlexRenderer.tsx |
ContainerRenderer.containerStyle |
gap, padding 스케일 적용 |
page.tsx |
viewportWidth state |
뷰포트 너비 감지 |
page.tsx |
Math.min(window.innerWidth, 1366) |
최대 너비 제한 |
Phase 3: Visibility + 줄바꿈 컴포넌트 (완료) ✅
개요
모드별 컴포넌트 표시/숨김 제어 및 강제 줄바꿈 기능 추가.
추가 타입
visibility 속성
interface PopComponentDefinitionV4 {
// 기존 속성...
// 🆕 모드별 표시/숨김
visibility?: {
tablet_landscape?: boolean;
tablet_portrait?: boolean;
mobile_landscape?: boolean;
mobile_portrait?: boolean;
};
}
pop-break 컴포넌트
type PopComponentType =
| "pop-field"
| "pop-button"
| "pop-list"
| "pop-indicator"
| "pop-scanner"
| "pop-numpad"
| "pop-spacer"
| "pop-break"; // 🆕 줄바꿈
사용 예시
모바일 전용 버튼
{
id: "call-button",
type: "pop-button",
label: "전화 걸기",
visibility: {
tablet_landscape: false, // 태블릿: 숨김
mobile_portrait: true, // 모바일: 표시
},
}
모드별 줄바꿈
레이아웃: [A] [B] [줄바꿈] [C] [D]
줄바꿈 visibility: { tablet_landscape: false, mobile_portrait: true }
결과:
태블릿: [A] [B] [C] [D] (한 줄)
모바일: [A] [B] (두 줄)
[C] [D]
속성 패널 "표시" 탭
┌─────────────────────┐
│ 탭: 크기 설정 표시 📍│
├─────────────────────┤
│ 모드별 표시 설정 │
│ ☑ 태블릿 가로 │
│ ☑ 태블릿 세로 │
│ ☐ 모바일 가로 (숨김)│
│ ☑ 모바일 세로 │
└─────────────────────┘
참고 문서
이 문서는 v4 통합 설계 모드의 스펙을 정의합니다. 최종 업데이트: 2026-02-04 (Phase 3 완료)