+```
+
+**변경 내용**: `overflow-auto`를 조건문 밖으로 이동 (공통 적용)
+**이유**: 프리뷰/일반 모드 모두 스크롤이 필요함
+
+#### 변경 3: 라인 275 - 백색 배경 컨테이너
+
+**현재 코드**:
+```
+className={`bg-white transition-all duration-300 ${isPreviewMode ? "shadow-2xl rounded-3xl overflow-auto border-8 border-gray-800" : "w-full"}`}
+```
+
+**변경 코드**:
+```
+className={`bg-white transition-all duration-300 ${isPreviewMode ? "shadow-2xl rounded-3xl overflow-auto border-8 border-gray-800" : "w-full min-h-full"}`}
+```
+
+**변경 내용**: 일반 모드에 `min-h-full` 추가
+**이유**: 컴포넌트가 적어 콘텐츠가 짧을 때에도 흰색 배경이 화면 전체를 채우도록 보장
+
+---
+
+## 3. 구현 순서 (의존성 기반)
+
+| 순서 | 작업 | 라인 | 의존성 | 상태 |
+|------|------|------|--------|------|
+| 1 | 라인 185: `overflow-hidden` 제거 | 185 | 없음 | [x] 완료 |
+| 2 | 라인 266: `overflow-auto` 공통 적용 | 266 | 순서 1 | [x] 완료 |
+| 3 | 라인 275: 일반 모드 `min-h-full` 추가 | 275 | 순서 2 | [x] 완료 |
+| 4 | 린트 검사 | - | 순서 1~3 | [x] 통과 |
+| 5 | 브라우저 검증 | - | 순서 4 | [ ] 대기 |
+
+---
+
+## 4. 사전 충돌 검사 결과
+
+**새로 추가할 변수/함수/타입: 없음**
+
+이번 수정은 기존 Tailwind CSS 클래스 문자열만 변경합니다.
+새로운 식별자(변수, 함수, 타입)를 추가하지 않으므로 충돌 검사 대상이 없습니다.
+
+---
+
+## 5. 에러 함정 경고
+
+### 함정 1: 순서 1만 하고 순서 2를 빼먹으면
+`overflow-hidden`만 제거하면 콘텐츠가 화면 밖으로 넘쳐 보이지만 스크롤은 안 됨.
+부모는 열었지만 자식에 스크롤 속성이 없는 상태.
+
+### 함정 2: 순서 2만 하고 순서 1을 빼먹으면
+자식에 `overflow-auto`를 넣어도 부모가 `overflow-hidden`으로 잘라내므로 여전히 스크롤 안 됨.
+**반드시 순서 1과 2를 함께 적용해야 함.**
+
+### 함정 3: 프리뷰 모드 영향
+프리뷰 모드는 이미 자체적으로 `overflow-auto`가 있으므로 이 수정에 영향 없음.
+`overflow-auto`가 중복 적용되어도 CSS에서 문제 없음.
+
+---
+
+## 6. 검증 방법
+
+1. `localhost:9771/pop/screens/4114` 접속 (iPhone SE 375px 기준)
+2. 화면 아래로 스크롤 가능한지 확인
+3. 맨 아래에 이미지(pop-text 5, 6)가 보이는지 확인
+4. 프리뷰 모드(`?preview=true`)에서도 기존처럼 정상 동작하는지 확인
+5. 컴포넌트가 적은 화면에서 흰색 배경이 화면 전체를 채우는지 확인
+
+---
+
+## 이전 완료 계획 (아카이브)
+
+
+POP 뷰어 실제 컴포넌트 렌더링 (완료)
+
+- [x] 뷰어 페이지에 레지스트리 초기화 import 추가
+- [x] `renderActualComponent()` 실제 컴포넌트 렌더링으로 교체
+- [x] 린트 검사 통과
+- 브라우저 검증: 컴포넌트 표시 정상, 스크롤 문제 발견 -> 별도 수정
+
+
+
+
+V2/V2 컴포넌트 설정 스키마 정비 (완료)
+
+- [x] 레거시 컴포넌트 스키마 제거
+- [x] V2 컴포넌트 overrides 스키마 정의 (16개)
+- [x] V2 컴포넌트 overrides 스키마 정의 (9개)
+- [x] componentConfig.ts 한 파일에서 통합 관리
+
+
+
+
+화면 복제 기능 개선 (진행 중)
- [완료] DB 구조 개편 (menu_objid 의존성 제거)
-- [완료] 복제 옵션 정리 (코드카테고리/연쇄관계 삭제, 이름 변경)
-- [완료] 화면 간 연결 복제 버그 수정 (targetScreenId 매핑 추가)
+- [완료] 복제 옵션 정리
+- [완료] 화면 간 연결 복제 버그 수정
- [대기] 화면 간 연결 복제 테스트
- [대기] 제어관리 복제 테스트
- [대기] 추가 옵션 복제 테스트
----
-
-## 수정 이력
-
-### 2026-01-26: 버튼 targetScreenId 매핑 버그 수정
-
-**문제**: 그룹 복제 시 버튼의 `targetScreenId`가 새 화면으로 매핑되지 않음
-
-- 수주관리 1→2→3→4 화면 복제 시 연결이 깨지는 문제
-
-**수정 파일**: `backend-node/src/services/screenManagementService.ts`
-
-- `updateTabScreenReferences` 함수에 `targetScreenId` 처리 로직 추가
-- 쿼리에 `targetScreenId` 검색 조건 추가
-- 문자열/숫자 타입 모두 처리
+
diff --git a/POPUPDATE_2.md b/POPUPDATE_2.md
index cc08d883..c4da5c4e 100644
--- a/POPUPDATE_2.md
+++ b/POPUPDATE_2.md
@@ -1,4 +1,4 @@
-# POP 컴포넌트 정의서 v7.0
+# POP 컴포넌트 정의서 v8.0
## POP 헌법 (공통 규칙)
@@ -50,6 +50,14 @@
- 모든 컴포넌트는 레지스트리에 등록해야 디자이너에 나타난다
- 모든 컴포넌트 인스턴스는 userConfigurable, displayName 공통 속성을 가진다
+### 제9조. 모달 화면의 설계
+
+- 모달은 인라인(컴포넌트 설정만으로 구성)과 외부 참조(별도 POP 화면 연결) 두 가지 방식이 있다
+- 단순한 목록 선택은 인라인 모달을 사용한다 (설정만으로 완결)
+- 복잡한 검색/필터가 필요하거나 여러 곳에서 재사용하는 모달은 별도 POP 화면을 만들어 참조한다
+- 모달 안의 화면도 동일한 POP 컴포넌트 시스템으로 구성된다 (같은 그리드, 같은 컴포넌트)
+- 모달 화면의 layout_data는 기존 screen_layouts_pop 테이블에 저장한다 (DB 변경 불필요)
+
---
## 현재 상태
@@ -203,7 +211,12 @@ DataSourceConfig를 받아서 기존 API를 호출하고 결과를 반환:
- `type`: "navigate" | "modal" | "save" | "delete" | "api" | "event" | "refresh"
- `navigate`: { screenId, url }
-- `modal`: { title, dataSource }
+- `modal`: { mode, title, screenId, inlineConfig, modalSize }
+ - mode: "inline" (설정만으로 구성) | "screen-ref" (별도 화면 참조)
+ - title: 모달 제목
+ - screenId: mode가 "screen-ref"일 때 참조할 POP 화면 ID
+ - inlineConfig: mode가 "inline"일 때 사용할 DataSourceConfig + 표시 설정
+ - modalSize: { width, height } 모달 크기
- `save`: { targetColumns }
- `delete`: { confirmMessage }
- `api`: { method, endpoint, body }
@@ -224,22 +237,97 @@ DataSourceConfig를 받아서 기존 API를 호출하고 결과를 반환:
- **이벤트**: 발행 없음, 수신 없음
- **설정**: 내용, 폰트 크기/굵기, 좌우/상하 정렬, 이미지 URL/맞춤/크기, 날짜 포맷 빌더
-### 2. pop-dashboard (신규)
+### 2. pop-dashboard (신규 - 2026-02-09 토의 결과 반영)
-- **한 줄 정의**: 숫자를 집계해서 보여줌
+- **한 줄 정의**: 여러 집계 아이템을 묶어서 다양한 방식으로 보여줌
- **카테고리**: display
-- **역할**: 숫자 데이터를 집계/계산하여 시각화
-- **서브타입**:
+- **역할**: 숫자 데이터를 집계/계산하여 시각화. 하나의 컴포넌트 안에 여러 집계 아이템을 담는 컨테이너
+- **구조**: 1개 pop-dashboard = 여러 DashboardItem의 묶음. 각 아이템은 독립적으로 데이터 소스/서브타입/보이기숨기기 설정 가능
+- **서브타입** (아이템별로 선택, 한 묶음에 혼합 가능):
- kpi-card: 숫자 + 단위 + 라벨 + 증감 표시
- chart: 막대/원형/라인 차트
- gauge: 게이지 (목표 대비 달성률)
- stat-card: 통계 카드 (건수 + 대기 + 링크)
-- **데이터**: DataSourceConfig (조인/집계 자유)
+- **표시 모드** (디자이너가 선택):
+ - arrows: 좌우 버튼으로 아이템 넘기기
+ - auto-slide: 전광판처럼 자동 전환 (터치 시 멈춤, 일정 시간 후 재개)
+ - grid: 컴포넌트 영역 내부를 행/열로 쪼개서 여러 아이템 동시 표시 (디자이너가 각 아이템 위치 직접 지정)
+ - scroll: 좌우 또는 상하 스와이프
+- **데이터**: 각 아이템별 독립 DataSourceConfig (조인/집계 자유)
+- **계산식 지원**: "생산량/총재고량", "출고량/현재고량" 같은 복합 표현 가능
+ - 값 A, B를 각각 다른 테이블/집계로 설정
+ - 표시 형태: 분수(1,234/5,678), 퍼센트(21.7%), 비율(1,234:5,678)
- **CRUD**: 주로 읽기. 목표값 수정 등 필요 시 write 컬럼으로 저장 가능
- **이벤트**:
- 수신: filter_changed, data_ready
- - 발행: kpi_clicked (KPI 카드 클릭 시 상세 데이터 전달)
-- **설정**: 데이터 소스, 집계 함수, 라벨, 단위, 색상 구간, 차트 타입, 새로고침 주기, 목표값, 표시 모드(slide/scroll/grid)
+ - 발행: kpi_clicked (아이템 클릭 시 상세 데이터 전달)
+- **설정**: 데이터 소스(드롭다운 기반 쉬운 집계), 집계 함수, 계산식, 라벨, 단위, 색상 구간, 차트 타입, 새로고침 주기, 목표값, 표시 모드, 아이템별 보이기/숨기기
+- **보이기/숨기기**: 각 아이템별로 pop-system에서 개별 on/off 가능 (userConfigurable)
+- **기존 POP 대시보드 폐기**: `frontend/components/pop/dashboard/` 폴더 전체를 이 컴포넌트로 대체 예정 (Phase 1~3 완료 후)
+
+#### pop-dashboard 데이터 구조
+
+```
+PopDashboardConfig {
+ items: DashboardItem[] // 아이템 목록 (각각 독립 설정)
+ displayMode: "arrows" | "auto-slide" | "grid" | "scroll"
+ autoSlideInterval: number // 자동 슬라이드 간격(초)
+ gridLayout: { columns: number, rows: number } // 행열 그리드 설정
+ showIndicator: boolean // 페이지 인디케이터 표시
+ gap: number // 아이템 간 간격
+}
+
+DashboardItem {
+ id: string
+ label: string // pop-system에서 보이기/숨기기용 이름
+ visible: boolean // 보이기/숨기기
+ subType: "kpi-card" | "chart" | "gauge" | "stat-card"
+ dataSource: DataSourceConfig // 각 아이템별 독립 데이터 소스
+
+ // 행열 그리드 모드에서의 위치 (디자이너가 직접 지정)
+ gridPosition: { col: number, row: number, colSpan: number, rowSpan: number }
+
+ // 계산식 (선택사항)
+ formula?: {
+ enabled: boolean
+ values: [
+ { id: "A", dataSource: DataSourceConfig, label: "생산량" },
+ { id: "B", dataSource: DataSourceConfig, label: "총재고량" },
+ ]
+ expression: string // "A / B", "A + B", "A / B * 100"
+ displayFormat: "value" | "fraction" | "percent" | "ratio"
+ }
+
+ // 서브타입별 설정
+ kpiConfig?: { unit, colorRanges, showTrend, trendPeriod }
+ chartConfig?: { chartType, xAxis, yAxis, colors }
+ gaugeConfig?: { min, max, target, colorRanges }
+ statConfig?: { categories, showLink }
+}
+```
+
+#### 설정 패널 흐름 (드롭다운 기반 쉬운 집계)
+
+```
+1. [+ 아이템 추가] 버튼 클릭
+2. 서브타입 선택: kpi-card / chart / gauge / stat-card
+3. 데이터 모드 선택: [단일 집계] 또는 [계산식]
+
+ [단일 집계]
+ - 테이블 선택 (table-schema API로 목록)
+ - 조인할 테이블 추가 (선택사항)
+ - 컬럼 선택 → 집계 함수 선택 (합계/건수/평균/최소/최대)
+ - 필터 조건 추가
+
+ [계산식] (예: 생산량/총재고량)
+ - 값 A: 테이블 -> 컬럼 -> 집계함수
+ - 값 B: 테이블 -> 컬럼 -> 집계함수 (다른 테이블도 가능)
+ - 계산식: A / B
+ - 표시 형태: 분수 / 퍼센트 / 비율
+
+4. 라벨, 단위, 색상 등 외형 설정
+5. 행열 그리드 위치 설정 (grid 모드일 때)
+```
### 3. pop-table (신규 - 가장 복잡)
@@ -335,6 +423,59 @@ DataSourceConfig를 받아서 기존 API를 호출하고 결과를 반환:
- **pop-icon과의 차이**: pop-icon은 이동/실행만 하고 값이 안 돌아옴. pop-lookup은 값을 골라서 돌려줌
- **pop-search와의 차이**: pop-search는 텍스트/날짜/드롭다운으로 필터링. pop-lookup은 모달을 열어서 목록에서 선택
+#### pop-lookup 모달 화면 설계 방식
+
+pop-lookup이 열리는 모달의 내부 화면은 **두 가지 방식** 중 선택할 수 있다:
+
+**방식 A: 인라인 모달 (기본)**
+- pop-lookup 컴포넌트의 설정 패널에서 직접 모달 내부 화면을 구성
+- DataSourceConfig + 표시 컬럼 + 검색 필터 설정만으로 동작
+- 별도 화면 생성 없이 컴포넌트 설정만으로 완결
+- 적합한 경우: 단순 목록 선택 (거래처 목록, 품목 목록 등)
+
+**방식 B: 외부 화면 참조 (고급)**
+- 별도의 POP 화면(screen_id)을 모달로 연결
+- 모달 안에서 검색/필터/테이블 등 복잡한 화면을 디자이너로 자유롭게 구성
+- 여러 pop-lookup에서 같은 모달 화면을 재사용 가능
+- 적합한 경우: 복잡한 검색/필터가 필요한 선택 화면, 여러 화면에서 공유하는 모달
+
+**설정 구조:**
+
+```
+modalConfig: {
+ mode: "inline" | "screen-ref"
+
+ // mode = "inline"일 때 사용
+ dataSource: DataSourceConfig
+ displayColumns: ColumnBinding[]
+ searchFilter: { enabled: boolean, targetColumns: string[] }
+ modalSize: { width: number, height: number }
+
+ // mode = "screen-ref"일 때 사용
+ screenId: number // 참조할 POP 화면 ID
+ returnMapping: { // 모달 화면에서 선택된 값을 어떻게 매핑할지
+ sourceColumn: string // 모달 화면에서 반환하는 컬럼
+ targetField: string // pop-lookup 필드에 표시할 값
+ }[]
+ modalSize: { width: number, height: number }
+}
+```
+
+**기존 시스템과의 호환성 (검증 완료):**
+
+| 항목 | 현재 상태 | pop-lookup 지원 여부 |
+|------|-----------|---------------------|
+| DB: layout_data JSONB | 유연한 JSON 구조 | modalConfig를 layout_data에 저장 가능 (스키마 변경 불필요) |
+| DB: screen_layouts_pop 테이블 | screen_id + company_code 기반 | 모달 화면도 별도 screen_id로 저장 가능 |
+| 프론트: TabsWidget | screenId로 외부 화면 참조 지원 | 같은 패턴으로 모달에서 외부 화면 로드 가능 |
+| 프론트: detectLinkedModals API | 연결된 모달 화면 감지 기능 있음 | 화면 간 참조 관계 추적에 활용 가능 |
+| 백엔드: saveLayoutPop/getLayoutPop | POP 전용 저장/조회 API 있음 | 모달 화면도 동일 API로 저장/조회 가능 |
+| 레이어 시스템 | layer_id 기반 다중 레이어 지원 | 모달 내부 레이아웃을 레이어로 관리 가능 |
+
+**DB 마이그레이션 불필요**: layout_data가 JSONB이므로 modalConfig를 컴포넌트 overrides에 포함하면 됨.
+**백엔드 변경 불필요**: 기존 saveLayoutPop/getLayoutPop API가 그대로 사용 가능.
+**프론트엔드 참고 패턴**: TabsWidget의 screenId 참조 방식을 그대로 차용.
+
### 9. pop-system (신규)
- **한 줄 정의**: 시스템 설정을 하나로 통합한 컴포넌트 (프로필, 테마, 보이기/숨기기)
@@ -413,7 +554,34 @@ sequenceDiagram
Note over Table: 발주 품목 3건 표시
```
-### 예시 4: 컬럼별 읽기/쓰기 분리 동작
+### 예시 4: pop-lookup 인라인 모달 vs 외부 화면 참조
+
+```mermaid
+sequenceDiagram
+ participant User as 사용자
+ participant Lookup as pop-lookup (거래처)
+ participant Modal as 모달
+
+ Note over User,Modal: [방식 A: 인라인 모달]
+ User->>Lookup: 거래처 필드 클릭
+ Lookup->>Modal: 인라인 모달 열림 (DataSourceConfig 기반)
+ Note over Modal: supplier 테이블에서 목록 조회
+ Note over Modal: 테이블형 목록 표시
+ User->>Modal: "대한금속" 선택
+ Modal->>Lookup: value_selected { supplier_code: "DH001", name: "대한금속" }
+ Note over Lookup: 필드에 "대한금속" 표시
+
+ Note over User,Modal: [방식 B: 외부 화면 참조]
+ User->>Lookup: 거래처 필드 클릭
+ Lookup->>Modal: 모달 열림 (screenId=42 화면 로드)
+ Note over Modal: 별도 POP 화면 렌더링
+ Note over Modal: pop-search(검색) + pop-table(목록) 등 배치된 컴포넌트 동작
+ User->>Modal: 검색 후 "대한금속" 선택
+ Modal->>Lookup: returnMapping 기반으로 값 반환
+ Note over Lookup: 필드에 "대한금속" 표시
+```
+
+### 예시 5: 컬럼별 읽기/쓰기 분리 동작
5개 컬럼이 있는 발주 화면:
@@ -431,13 +599,91 @@ sequenceDiagram
## 구현 우선순위
- Phase 0 (공통 인프라): ColumnBinding, JoinConfig, DataSourceConfig 타입, useDataSource 훅 (CRUD 포함), usePopEvent 훅 (데이터 전달 포함), PopActionConfig 타입
-- Phase 1 (기본 표시): pop-dashboard (KPI 카드 서브타입부터)
+- Phase 1 (기본 표시): pop-dashboard (4개 서브타입 전부 + 멀티 아이템 컨테이너 + 4개 표시 모드 + 계산식)
- Phase 2 (기본 액션): pop-button, pop-icon
- Phase 3 (데이터 목록): pop-table (테이블형부터, 카드형은 후순위)
- Phase 4 (입력/연동): pop-search, pop-field, pop-lookup
-- Phase 5 (고도화): pop-table 카드 템플릿, 차트, 게이지
+- Phase 5 (고도화): pop-table 카드 템플릿
- Phase 6 (시스템): pop-system (프로필, 테마, 대시보드 보이기/숨기기 통합)
+### Phase 1 상세 변경 (2026-02-09 토의 결정)
+
+기존 계획에서 "KPI 카드 우선"이었으나, 토의 결과 **4개 서브타입 전부를 Phase 1에서 구현**으로 변경:
+- kpi-card, chart, gauge, stat-card 모두 Phase 1
+- 멀티 아이템 컨테이너 (arrows, auto-slide, grid, scroll)
+- 계산식 지원 (formula)
+- 드롭다운 기반 쉬운 집계 설정
+- 기존 `frontend/components/pop/dashboard/` 폴더는 Phase 1 완료 후 폐기/삭제
+
+### 백엔드 API 현황 (호환성 점검 완료)
+
+기존 백엔드에 이미 구현되어 있어 새로 만들 필요 없는 API:
+
+| API | 용도 | 비고 |
+|-----|------|------|
+| `dataApi.getTableData()` | 동적 테이블 조회 | 페이징, 검색, 정렬, 필터 |
+| `dataApi.getJoinedData()` | 2개 테이블 조인 | Entity 조인, 필터링, 중복제거 |
+| `entityJoinApi.getTableDataWithJoins()` | Entity 조인 전용 | ID->이름 자동 변환 |
+| `dataApi.createRecord/updateRecord/deleteRecord()` | 동적 CRUD | - |
+| `dataApi.upsertGroupedRecords()` | 그룹 UPSERT | - |
+| `dashboardApi.executeQuery()` | SELECT SQL 직접 실행 | 집계/복합조인용 |
+| `dashboardApi.getTableSchema()` | 테이블/컬럼 목록 | 설정 패널 드롭다운용 |
+
+**백엔드 신규 개발 불필요** - 기존 API만으로 모든 데이터 연동 가능
+
+### useDataSource의 API 선택 전략
+
+```
+단순 조회 (조인/집계 없음) -> dataApi.getTableData() 또는 entityJoinApi
+2개 테이블 조인 -> dataApi.getJoinedData()
+3개+ 테이블 조인 또는 집계 -> DataSourceConfig를 SQL로 변환 -> dashboardApi.executeQuery()
+CRUD -> dataApi.createRecord/updateRecord/deleteRecord()
+```
+
+### POP 전용 훅 분리 (2026-02-09 결정)
+
+데스크탑과의 완전 분리를 위해 POP 전용 훅은 별도 폴더:
+- `frontend/hooks/pop/usePopEvent.ts` (POP 전용)
+- `frontend/hooks/pop/useDataSource.ts` (POP 전용)
+
+## 기존 시스템 호환성 검증 결과 (v8.0 추가)
+
+v8.0에서 추가된 모달 설계 방식에 대해 기존 시스템과의 호환성을 검증한 결과:
+
+### DB 스키마 (변경 불필요)
+
+| 테이블 | 현재 구조 | 호환성 |
+|--------|-----------|--------|
+| screen_layouts_v2 | layout_data JSONB + screen_id + company_code + layer_id | modalConfig를 컴포넌트 overrides에 포함하면 됨 |
+| screen_layouts_pop | 동일 구조 (POP 전용) | 모달 화면도 별도 screen_id로 저장 가능 |
+
+- layout_data가 JSONB 타입이므로 어떤 JSON 구조든 저장 가능
+- 모달 화면을 별도 screen_id로 만들어도 기존 UNIQUE(screen_id, company_code, layer_id) 제약조건과 충돌 없음
+- DB 마이그레이션 불필요
+
+### 백엔드 API (변경 불필요)
+
+| API | 엔드포인트 | 호환성 |
+|-----|-----------|--------|
+| POP 레이아웃 저장 | POST /api/screen-management/screens/:screenId/layout-pop | 모달 화면도 동일 API로 저장 |
+| POP 레이아웃 조회 | GET /api/screen-management/screens/:screenId/layout-pop | 모달 화면도 동일 API로 조회 |
+| 연결 모달 감지 | detectLinkedModals(screenId) | 화면 간 참조 관계 추적에 활용 |
+
+### 프론트엔드 (참고 패턴 존재)
+
+| 기존 기능 | 위치 | 활용 방안 |
+|-----------|------|-----------|
+| TabsWidget screenId 참조 | frontend/components/screen/widgets/TabsWidget.tsx | 같은 패턴으로 모달에서 외부 화면 로드 |
+| TabsConfigPanel | frontend/components/screen/config-panels/TabsConfigPanel.tsx | pop-lookup 설정 패널의 모달 화면 선택 UI 참조 |
+| ScreenDesigner 탭 내부 컴포넌트 | frontend/components/screen/ScreenDesigner.tsx | 모달 내부 컴포넌트 편집 패턴 참조 |
+
+### 결론
+
+- DB 마이그레이션: 불필요
+- 백엔드 변경: 불필요
+- 프론트엔드: pop-lookup 컴포넌트 구현 시 기존 TabsWidget의 screenId 참조 패턴을 그대로 차용
+- 새로운 API: 불필요 (기존 saveLayoutPop/getLayoutPop로 충분)
+
## 참고 파일
- 레지스트리: `frontend/lib/registry/PopComponentRegistry.ts`
@@ -445,3 +691,6 @@ sequenceDiagram
- 공통 스타일 타입: `frontend/lib/registry/pop-components/types.ts`
- POP 타입 정의: `frontend/components/pop/designer/types/pop-layout.ts`
- 기존 스펙 (v4): `popdocs/components-spec.md`
+- 탭 위젯 (모달 참조 패턴): `frontend/components/screen/widgets/TabsWidget.tsx`
+- POP 레이아웃 API: `frontend/lib/api/screen.ts` (saveLayoutPop, getLayoutPop)
+- 백엔드 화면관리: `backend-node/src/controllers/screenManagementController.ts`
diff --git a/frontend/app/(pop)/pop/screens/[screenId]/page.tsx b/frontend/app/(pop)/pop/screens/[screenId]/page.tsx
index f578b30e..d17ced93 100644
--- a/frontend/app/(pop)/pop/screens/[screenId]/page.tsx
+++ b/frontend/app/(pop)/pop/screens/[screenId]/page.tsx
@@ -24,6 +24,8 @@ import {
GRID_BREAKPOINTS,
detectGridMode,
} from "@/components/pop/designer/types/pop-layout";
+// POP 컴포넌트 자동 등록 (레지스트리 초기화 - PopRenderer보다 먼저 import)
+import "@/lib/registry/pop-components";
import PopRenderer from "@/components/pop/designer/renderers/PopRenderer";
import {
useResponsiveModeWithOverride,
@@ -180,7 +182,7 @@ function PopScreenViewPage() {
-
+
{/* 상단 툴바 (프리뷰 모드에서만) */}
{isPreviewMode && (
@@ -261,7 +263,7 @@ function PopScreenViewPage() {
)}
{/* POP 화면 컨텐츠 */}
-
+
{/* 현재 모드 표시 (일반 모드) */}
{!isPreviewMode && (
@@ -270,7 +272,7 @@ function PopScreenViewPage() {
)}
+ );
+ }
+
+ // 미등록 컴포넌트: 플레이스홀더 (fallback)
+ const typeLabel = COMPONENT_TYPE_LABELS[component.type] || component.type;
return (
{component.label || typeLabel}