feat(pop-designer): 반응형 레이아웃 시스템 구현
모드별(4/6/8/12칸) 컴포넌트 위치/크기 오버라이드 저장 화면 밖 컴포넌트 오른쪽 패널 표시 및 드래그 재배치 컴포넌트 숨김 기능 (드래그/H키/클릭, 드래그로 해제) 리사이즈 겹침 검사 추가 드롭 위치 그리드 범위 초과 시 자동 조정 숨김 컴포넌트 드래그 안됨 버그 수정 (상태 업데이트 통합)
This commit is contained in:
@@ -12,6 +12,277 @@
|
||||
|
||||
---
|
||||
|
||||
## [2026-02-05 심야] 반응형 레이아웃 + 숨김 기능 완성
|
||||
|
||||
### 배경 (왜 이 작업이 필요했는가)
|
||||
|
||||
**문제 상황**:
|
||||
- 12칸 모드에서 배치한 컴포넌트가 4칸 모드에서 초과됨
|
||||
- 모드별로 컴포넌트 위치/크기를 다르게 설정할 방법 없음
|
||||
- 특정 모드에서만 컴포넌트를 숨길 방법 없음
|
||||
|
||||
**해결 방향**:
|
||||
- 모드별 오버라이드 시스템으로 위치/크기 개별 저장
|
||||
- 화면 밖 컴포넌트를 별도 패널에 표시하고 드래그로 재배치
|
||||
- 숨김 기능으로 특정 모드에서 컴포넌트 제외
|
||||
|
||||
### Added
|
||||
|
||||
- **모드별 오버라이드 시스템** (PopDesigner.tsx, pop-layout.ts)
|
||||
- `PopModeOverrideV5.positions`: 모드별 컴포넌트 위치 저장
|
||||
- `PopModeOverrideV5.hidden`: 모드별 숨김 컴포넌트 ID 배열
|
||||
- `getEffectiveComponentPosition()`: 오버라이드된 위치 반환
|
||||
- 드래그/리사이즈 시 자동으로 오버라이드 저장
|
||||
|
||||
- **화면 밖 컴포넌트 패널** (PopCanvas.tsx)
|
||||
- `OutOfBoundsPanel`: 현재 모드에서 초과하는 컴포넌트 표시
|
||||
- `OutOfBoundsItem`: 드래그 가능한 회색 컴포넌트 카드
|
||||
- `isOutOfBounds()`: 컴포넌트가 현재 모드 칸 수 초과 여부 판단
|
||||
- 클릭하면 숨김 패널로 이동
|
||||
|
||||
- **숨김 기능** (PopDesigner.tsx, PopCanvas.tsx)
|
||||
- `HiddenPanel`: 숨김 처리된 컴포넌트 표시
|
||||
- `HiddenItem`: 드래그로 숨김 해제 가능
|
||||
- `handleHideComponent()`: 컴포넌트 숨김 처리
|
||||
- `handleUnhideComponent()`: 숨김 해제 (handleMoveComponent에 통합)
|
||||
- 숨김 방법 3가지:
|
||||
1. 그리드 → 숨김패널 드래그
|
||||
2. H키 단축키
|
||||
3. 화면밖 컴포넌트 클릭
|
||||
|
||||
- **리사이즈 겹침 검사** (PopRenderer.tsx)
|
||||
- `checkResizeOverlap()`: 리사이즈 시 다른 컴포넌트와 겹침 검사
|
||||
- 겹치면 리사이즈 취소 및 toast 알림
|
||||
|
||||
- **원본으로 되돌리기** (PopDesigner.tsx)
|
||||
- `handleResetToDefault()`: 현재 모드 오버라이드 삭제
|
||||
- 자동 위치 계산으로 복원
|
||||
|
||||
### Fixed
|
||||
|
||||
- **숨김 컴포넌트 드래그 안됨 버그**
|
||||
- 원인: `onUnhideComponent`와 `onMoveComponent`가 별도로 호출되어 상태 충돌
|
||||
- 해결: `handleMoveComponent`에서 숨김 해제 로직 통합 (단일 상태 업데이트)
|
||||
|
||||
- **그리드 범위 초과 에러**
|
||||
- 원인: 드롭 위치 + colSpan이 칸 수 초과
|
||||
- 해결: 드롭 시 `adjustedCol` 계산하여 자동으로 왼쪽으로 밀어서 배치
|
||||
|
||||
- **getAllEffectivePositions에 숨김 컴포넌트 포함**
|
||||
- 해결: 숨김 및 화면밖 컴포넌트를 결과에서 제외
|
||||
|
||||
### Changed
|
||||
|
||||
- **PopModeOverrideV5 타입 확장**
|
||||
```typescript
|
||||
interface PopModeOverrideV5 {
|
||||
positions?: Record<string, Partial<PopGridPosition>>; // 위치 오버라이드
|
||||
hidden?: string[]; // 숨김 컴포넌트 ID 배열
|
||||
}
|
||||
```
|
||||
|
||||
- **12칸 모드(tablet_landscape) 제한**
|
||||
- 기본 모드이므로 숨김 기능 비활성화
|
||||
- 화면밖 패널 표시 안함
|
||||
- 위치 변경은 기본 position에 직접 저장
|
||||
|
||||
- **패널 레이아웃 재구성** (PopCanvas.tsx)
|
||||
- 오른쪽에 화면밖 패널 + 숨김 패널 세로 배치
|
||||
- 12칸 모드에서는 패널 숨김
|
||||
|
||||
### Technical Details
|
||||
|
||||
```
|
||||
오버라이드 데이터 흐름:
|
||||
|
||||
1. 컴포넌트 드래그/리사이즈
|
||||
↓
|
||||
2. currentMode 확인
|
||||
↓
|
||||
3-a. tablet_landscape → layout.components[id].position 직접 수정
|
||||
3-b. 다른 모드 → layout.overrides[mode].positions[id]에 저장
|
||||
↓
|
||||
4. getEffectiveComponentPosition()이 우선순위대로 반환
|
||||
우선순위: overrides > autoResolved > 기본 position
|
||||
|
||||
숨김 기능 흐름:
|
||||
|
||||
1. 숨김 요청 (드래그/H키/클릭)
|
||||
↓
|
||||
2. layout.overrides[mode].hidden 배열에 ID 추가
|
||||
↓
|
||||
3. PopRenderer에서 hidden 체크 → 렌더링 제외
|
||||
↓
|
||||
4. HiddenPanel에서 표시
|
||||
↓
|
||||
5. 드래그로 그리드에 복원 → hidden 배열에서 제거 + 위치 업데이트 (단일 상태 업데이트)
|
||||
```
|
||||
|
||||
### 수정 파일
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `pop-layout.ts` | PopModeOverrideV5.hidden 추가 |
|
||||
| `PopDesigner.tsx` | handleHideComponent, handleUnhideComponent 통합, 오버라이드 저장 |
|
||||
| `PopCanvas.tsx` | OutOfBoundsPanel, HiddenPanel 추가, 드롭 위치 자동 조정 |
|
||||
| `PopRenderer.tsx` | 숨김 필터링, 리사이즈 겹침 검사 |
|
||||
| `gridUtils.ts` | getAllEffectivePositions에서 숨김/화면밖 제외, isOutOfBounds 함수 |
|
||||
|
||||
---
|
||||
|
||||
## [2026-02-05 저녁] 드래그앤드롭 완전 수정
|
||||
|
||||
### 배경 (왜 좌표 계산이 틀렸는가)
|
||||
|
||||
**문제 상황**:
|
||||
- 컴포넌트를 아래로 드래그해도 위로 올라감
|
||||
- Row 92 같은 비정상적인 좌표로 배치됨
|
||||
- 드래그 이동/리사이즈가 전혀 작동하지 않음
|
||||
|
||||
**핵심 원인**: 캔버스에 `transform: scale(0.8)` 적용 시 좌표 계산 불일치
|
||||
```
|
||||
문제:
|
||||
- getBoundingClientRect() → 스케일 적용된 크기 반환 (예: 1024px → 819px)
|
||||
- getClientOffset() → 뷰포트 기준 실제 마우스 좌표
|
||||
- 이 둘을 그대로 계산하면 좌표가 완전히 틀림
|
||||
```
|
||||
|
||||
**해결**: 단순한 상대 좌표 + 스케일 보정
|
||||
```typescript
|
||||
// 캔버스 내 상대 좌표 (스케일 보정)
|
||||
const relX = (마우스X - 캔버스left) / canvasScale;
|
||||
const relY = (마우스Y - 캔버스top) / canvasScale;
|
||||
calcGridPosition(relX, relY, customWidth, ...); // 실제 캔버스 크기 사용
|
||||
```
|
||||
|
||||
### Added
|
||||
- **`calcGridPosition()` 함수** (PopCanvas.tsx)
|
||||
- 캔버스 내 상대 좌표를 그리드 좌표로 변환
|
||||
- 패딩, gap, 셀 너비를 고려한 정확한 계산
|
||||
|
||||
- **공통 DND 상수** (constants/dnd.ts)
|
||||
- `DND_ITEM_TYPES.COMPONENT`: 팔레트에서 새 컴포넌트
|
||||
- `DND_ITEM_TYPES.MOVE_COMPONENT`: 기존 컴포넌트 이동
|
||||
- 3개 파일에서 중복 정의되던 것을 통합
|
||||
|
||||
### Fixed
|
||||
- **스케일 보정 누락**
|
||||
- 캔버스 줌(scale)이 적용된 상태에서 좌표 계산 오류
|
||||
- `(offset - rect.left) / scale`로 보정
|
||||
|
||||
- **DND 타입 상수 불일치**
|
||||
- PopCanvas: `"component"`, `"MOVE_COMPONENT"`
|
||||
- PopRenderer: `"MOVE_COMPONENT"` (하드코딩)
|
||||
- ComponentPalette: `"component"` (로컬 정의)
|
||||
- 모두 공통 상수로 통합
|
||||
|
||||
- **컴포넌트 중첩(겹침) 문제**
|
||||
- 원인: `toast` import 누락으로 겹침 감지 로직이 실행 안됨
|
||||
- 해결: `sonner`에서 toast import 추가
|
||||
- 겹침 시 `findNextEmptyPosition()`으로 자동 재배치
|
||||
|
||||
- **리사이즈 핸들 작동 안됨**
|
||||
- 원인: `useDrop` 훅 2개가 같은 `canvasRef`에 중복 적용
|
||||
- 해결: 단일 `useDrop`으로 통합 (`COMPONENT` + `MOVE_COMPONENT` 모두 처리)
|
||||
|
||||
- **불필요한 toast 메시지 제거**
|
||||
- "컴포넌트가 이동되었습니다" 알림 삭제
|
||||
|
||||
### Changed
|
||||
- **mouseToGridPosition 단순화**
|
||||
- 복잡한 DOMRect 전달 대신 필요한 값만 직접 전달
|
||||
- gridUtils.ts의 함수는 유지 (다른 곳에서 사용)
|
||||
|
||||
### Technical Details
|
||||
```
|
||||
좌표 변환 흐름 (수정 후):
|
||||
|
||||
1. 마우스 드롭
|
||||
offset = monitor.getClientOffset() // 뷰포트 기준 {x: 500, y: 300}
|
||||
|
||||
2. 캔버스 위치
|
||||
canvasRect = canvasRef.getBoundingClientRect() // {left: 250, top: 100}
|
||||
|
||||
3. 스케일 보정된 상대 좌표
|
||||
relX = (500 - 250) / 0.8 = 312.5 // 캔버스 내 실제 X
|
||||
relY = (300 - 100) / 0.8 = 250 // 캔버스 내 실제 Y
|
||||
|
||||
4. 그리드 좌표 계산
|
||||
calcGridPosition(312.5, 250, 1024, 12, 48, 16, 24)
|
||||
→ { col: 5, row: 4 }
|
||||
```
|
||||
|
||||
### 수정 파일
|
||||
| 파일 | 변경 내용 |
|
||||
|------|----------|
|
||||
| `PopCanvas.tsx` | calcGridPosition 추가, 스케일 보정 적용 |
|
||||
| `PopDesigner.tsx` | toast 메시지 제거 |
|
||||
| `PopRenderer.tsx` | DND 상수 import |
|
||||
| `ComponentPalette.tsx` | DND 상수 import |
|
||||
| `constants/dnd.ts` | 새 파일 (DND 타입 상수) |
|
||||
| `constants/index.ts` | 새 파일 (export) |
|
||||
|
||||
---
|
||||
|
||||
## [2026-02-05 오후] 그리드 가이드 CSS Grid 통합
|
||||
|
||||
### 배경 (왜 재설계했는가)
|
||||
|
||||
**문제 상황**:
|
||||
- GridGuide.tsx(SVG 기반)와 PopRenderer.tsx(CSS Grid)가 좌표계 불일치
|
||||
- 격자선과 컴포넌트가 정렬되지 않음 ("무늬가 따로 논다")
|
||||
- 행/열 라벨이 4부터 시작하는 등 오류
|
||||
|
||||
**핵심 원칙**:
|
||||
> "격자선은 컴포넌트와 같은 좌표계에서 태어나야 한다"
|
||||
|
||||
**결정**: SVG 격자 삭제, CSS Grid 기반 통합
|
||||
→ 상세: [decisions/004-grid-guide-integration.md](./decisions/004-grid-guide-integration.md)
|
||||
|
||||
### Breaking Changes
|
||||
- `GridGuide.tsx` 삭제 (SVG 기반 격자)
|
||||
|
||||
### Added
|
||||
- **CSS Grid 기반 격자 셀** (PopRenderer.tsx)
|
||||
- `gridCells`: 12x20 = 240개 실제 DOM 셀
|
||||
- `border-dashed border-blue-300/40` 스타일
|
||||
- 컴포넌트는 `z-index:10`으로 위에 표시
|
||||
- `showGridGuide` prop으로 ON/OFF
|
||||
|
||||
- **행/열 라벨** (PopCanvas.tsx)
|
||||
- 열 라벨: 1~12 (캔버스 상단)
|
||||
- 행 라벨: 1~20 (캔버스 좌측)
|
||||
- absolute positioning으로 정확한 정렬
|
||||
- 줌/패닝에 연동
|
||||
|
||||
- **그리드 토글 버튼** (PopCanvas.tsx)
|
||||
- "그리드 ON/OFF" 버튼 추가
|
||||
- 격자 표시 상태 관리
|
||||
|
||||
### Changed
|
||||
- **컴포넌트 타입 단순화**
|
||||
- `PopComponentType`: `pop-sample` 1개로 단순화
|
||||
- `DEFAULT_COMPONENT_GRID_SIZE`: `pop-sample` 전용
|
||||
- `ComponentPalette.tsx`: 샘플 박스 1개만 표시
|
||||
- `PopRenderer.tsx`: 샘플 박스 렌더링으로 단순화
|
||||
|
||||
### Technical Details
|
||||
```
|
||||
역할 분담:
|
||||
- PopRenderer: 격자 셀(div) + 컴포넌트 (같은 CSS Grid 좌표계)
|
||||
- PopCanvas: 라벨 + 줌/패닝 + 토글
|
||||
- GridGuide: 삭제
|
||||
|
||||
격자 셀 구조:
|
||||
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
|
||||
│1,1│2,1│3,1│4,1│5,1│6,1│7,1│8,1│9,1│10│11│12 │ ← col
|
||||
├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
|
||||
│1,2│... │
|
||||
└───┴───────────────────────────────────────────┘
|
||||
↑ row
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## [2026-02-05] v5 그리드 시스템 완전 통합
|
||||
|
||||
### 배경 (왜 v5로 전환했는가)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# POP 파일 상세 목록
|
||||
|
||||
**최종 업데이트: 2026-02-05 (v5 그리드 시스템 통합)**
|
||||
**최종 업데이트: 2026-02-05 저녁 (드래그앤드롭 수정)**
|
||||
|
||||
이 문서는 POP 화면 시스템과 관련된 모든 파일을 나열하고 각 파일의 역할을 설명합니다.
|
||||
|
||||
@@ -151,9 +151,11 @@ const [hasChanges, setHasChanges] = useState(false);
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| 역할 | v5 CSS Grid 기반 캔버스 |
|
||||
| 역할 | v5 CSS Grid 기반 캔버스 + 행/열 라벨 |
|
||||
| 렌더링 | CSS Grid (4/6/8/12칸) |
|
||||
| 모드 | 4개 (태블릿/모바일 x 가로/세로) |
|
||||
| 라벨 | 열 라벨 (1~12), 행 라벨 (1~20) |
|
||||
| 토글 | 그리드 ON/OFF 버튼 |
|
||||
|
||||
**핵심 Props**:
|
||||
|
||||
@@ -247,8 +249,9 @@ export { default as ComponentEditorPanel, default } from "./ComponentEditorPanel
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| 역할 | v5 레이아웃 CSS Grid 렌더러 |
|
||||
| 입력 | PopLayoutDataV5, viewportWidth, currentMode |
|
||||
| 역할 | v5 레이아웃 CSS Grid 렌더러 + 격자 셀 |
|
||||
| 입력 | PopLayoutDataV5, viewportWidth, currentMode, showGridGuide |
|
||||
| 격자 | 12x20 = 240개 실제 DOM 셀 (CSS Grid 좌표계) |
|
||||
|
||||
**핵심 Props**:
|
||||
|
||||
@@ -259,12 +262,37 @@ interface PopRendererProps {
|
||||
currentMode?: GridMode;
|
||||
isDesignMode?: boolean;
|
||||
selectedComponentId?: string | null;
|
||||
showGridGuide?: boolean; // 격자 표시 여부
|
||||
onComponentClick?: (componentId: string) => void;
|
||||
onBackgroundClick?: () => void;
|
||||
className?: string;
|
||||
}
|
||||
```
|
||||
|
||||
**격자 셀 렌더링**:
|
||||
|
||||
```typescript
|
||||
// 12x20 = 240개 셀 생성
|
||||
const gridCells = useMemo(() => {
|
||||
const cells = [];
|
||||
for (let row = 1; row <= 20; row++) {
|
||||
for (let col = 1; col <= 12; col++) {
|
||||
cells.push({ id: `${col}-${row}`, col, row });
|
||||
}
|
||||
}
|
||||
return cells;
|
||||
}, []);
|
||||
|
||||
// 컴포넌트와 동일한 CSS Grid 좌표계로 렌더링
|
||||
{showGridGuide && gridCells.map(cell => (
|
||||
<div
|
||||
key={cell.id}
|
||||
className="border border-dashed border-blue-300/40"
|
||||
style={{ gridColumn: cell.col, gridRow: cell.row }}
|
||||
/>
|
||||
))}
|
||||
```
|
||||
|
||||
**CSS Grid 스타일 생성**:
|
||||
|
||||
```typescript
|
||||
@@ -374,6 +402,41 @@ export * from "./pop-layout";
|
||||
|
||||
---
|
||||
|
||||
## 5.5. Constants 파일 (신규)
|
||||
|
||||
### `frontend/components/pop/designer/constants/dnd.ts`
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| 역할 | DnD(Drag and Drop) 관련 상수 |
|
||||
| 생성일 | 2026-02-05 |
|
||||
|
||||
**핵심 상수**:
|
||||
|
||||
```typescript
|
||||
export const DND_ITEM_TYPES = {
|
||||
/** 팔레트에서 새 컴포넌트 드래그 */
|
||||
COMPONENT: "POP_COMPONENT",
|
||||
/** 캔버스 내 기존 컴포넌트 이동 */
|
||||
MOVE_COMPONENT: "POP_MOVE_COMPONENT",
|
||||
} as const;
|
||||
```
|
||||
|
||||
**사용처**:
|
||||
- `PopCanvas.tsx` - useDrop accept 타입
|
||||
- `PopRenderer.tsx` - useDrag type
|
||||
- `ComponentPalette.tsx` - useDrag type
|
||||
|
||||
---
|
||||
|
||||
### `frontend/components/pop/designer/constants/index.ts`
|
||||
|
||||
```typescript
|
||||
export * from "./dnd";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Utils 파일
|
||||
|
||||
### `frontend/components/pop/designer/utils/gridUtils.ts`
|
||||
@@ -545,12 +608,12 @@ export * from "./dashboard";
|
||||
| 폴더 | 파일 수 | 설명 |
|
||||
|------|---------|------|
|
||||
| `app/(pop)` | 4 | App Router 페이지 |
|
||||
| `components/pop/designer` | 9 | 디자이너 모듈 (v5) |
|
||||
| `components/pop/designer` | 11 | 디자이너 모듈 (v5) - constants 포함 |
|
||||
| `components/pop/management` | 5 | 관리 모듈 |
|
||||
| `components/pop/dashboard` | 12 | 대시보드 모듈 |
|
||||
| `components/pop` (루트) | 15 | 루트 컴포넌트 |
|
||||
| `lib` | 3 | 라이브러리 |
|
||||
| **총계** | **48** | |
|
||||
| **총계** | **50** | |
|
||||
|
||||
---
|
||||
|
||||
@@ -565,6 +628,7 @@ export * from "./dashboard";
|
||||
| `ComponentEditorPanelV4.tsx` | v4 편집 패널 |
|
||||
| `PopPanel.tsx` | 레거시 팔레트 패널 |
|
||||
| `test-v4/page.tsx` | v4 테스트 페이지 |
|
||||
| `GridGuide.tsx` | SVG 기반 격자 가이드 (좌표 불일치로 삭제, CSS Grid 통합) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -10,10 +10,20 @@
|
||||
| 기능 | 파일 | 함수/컴포넌트 | 설명 |
|
||||
|------|------|--------------|------|
|
||||
| 그리드 렌더링 | PopRenderer.tsx | `PopRenderer` | CSS Grid 기반 v5 렌더링 |
|
||||
| 격자 셀 렌더링 | PopRenderer.tsx | `gridCells` (useMemo) | 12x20 = 240개 DOM 셀 |
|
||||
| 위치 변환 | gridUtils.ts | `convertPositionToMode()` | 12칸 → 4/6/8칸 변환 |
|
||||
| 모드 감지 | pop-layout.ts | `detectGridMode()` | 뷰포트 너비로 모드 판별 |
|
||||
| 컴포넌트 스타일 | PopRenderer.tsx | `convertPosition()` | 그리드 좌표 → CSS |
|
||||
|
||||
## 그리드 가이드
|
||||
|
||||
| 기능 | 파일 | 함수/컴포넌트 | 설명 |
|
||||
|------|------|--------------|------|
|
||||
| 격자 셀 | PopRenderer.tsx | `gridCells` | CSS Grid 기반 격자선 |
|
||||
| 열 라벨 | PopCanvas.tsx | `gridLabels.columns` | 1~12 표시 |
|
||||
| 행 라벨 | PopCanvas.tsx | `gridLabels.rows` | 1~20 표시 |
|
||||
| 토글 | PopCanvas.tsx | `showGridGuide` 상태 | 격자 ON/OFF |
|
||||
|
||||
## 드래그 앤 드롭
|
||||
|
||||
| 기능 | 파일 | 함수/컴포넌트 | 설명 |
|
||||
@@ -72,9 +82,10 @@
|
||||
| 파일 | 핵심 기능 |
|
||||
|------|----------|
|
||||
| PopDesigner.tsx | 레이아웃 로드/저장, 컴포넌트 CRUD, 히스토리 |
|
||||
| PopCanvas.tsx | DnD, 줌, 패닝, 모드 전환, 그리드 표시 |
|
||||
| PopRenderer.tsx | CSS Grid 렌더링, 위치 변환, 컴포넌트 표시 |
|
||||
| PopCanvas.tsx | DnD, 줌, 패닝, 모드 전환, 행/열 라벨, 격자 토글 |
|
||||
| PopRenderer.tsx | CSS Grid 렌더링, 격자 셀, 위치 변환, 컴포넌트 표시 |
|
||||
| ComponentEditorPanel.tsx | 속성 편집 (위치, 크기, 설정, 표시) |
|
||||
| ComponentPalette.tsx | 컴포넌트 팔레트 (드래그 가능한 컴포넌트 목록) |
|
||||
| pop-layout.ts | 타입 정의, 유틸리티 함수, 상수 |
|
||||
| gridUtils.ts | 좌표 계산, 겹침 감지, 자동 배치 |
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
|------|------|------|--------|
|
||||
| useDrag 에러 (뷰어에서) | isDesignMode 체크 후 early return | 2026-02-04 | DnD, useDrag, 뷰어 |
|
||||
| DndProvider 중복 에러 | 최상위에서만 Provider 사용 | 2026-02-04 | DndProvider, react-dnd |
|
||||
| **컴포넌트 중첩(겹침)** | toast import 누락 → `sonner`에서 import | 2026-02-05 | 겹침, overlap, toast |
|
||||
| **리사이즈 핸들 작동 안됨** | useDrop 2개 중복 → 단일 useDrop으로 통합 | 2026-02-05 | resize, 핸들, useDrop |
|
||||
| **드래그 좌표 완전 틀림 (Row 92)** | 캔버스 scale 보정 누락 → `(offset - rect.left) / scale` | 2026-02-05 | scale, 좌표, transform |
|
||||
| **DND 타입 상수 불일치** | 3개 파일에 중복 정의 → `constants/dnd.ts`로 통합 | 2026-02-05 | 상수, DND, 타입 |
|
||||
| **컴포넌트 이동 안됨** | useDrop accept 타입 불일치 → 공통 상수 사용 | 2026-02-05 | 이동, useDrop, accept |
|
||||
|
||||
## 타입 관련
|
||||
|
||||
@@ -50,12 +55,62 @@
|
||||
|
||||
---
|
||||
|
||||
## 해결 안 된 문제 (진행 중)
|
||||
## 그리드 가이드 관련
|
||||
|
||||
| 문제 | 상태 | 관련 파일 |
|
||||
| 문제 | 해결 | 날짜 | 키워드 |
|
||||
|------|------|------|--------|
|
||||
| SVG 격자와 CSS Grid 좌표 불일치 | GridGuide.tsx 삭제, PopRenderer에서 CSS Grid 셀로 격자 렌더링 | 2026-02-05 | 격자, SVG, CSS Grid, 좌표 |
|
||||
| 행/열 라벨 위치 오류 | PopCanvas에 absolute positioning 라벨 추가 | 2026-02-05 | 라벨, 행, 열, 정렬 |
|
||||
| 격자선과 컴포넌트 불일치 | 동일한 CSS Grid 좌표계 사용 | 2026-02-05 | 통합, 정렬, 일체감 |
|
||||
|
||||
---
|
||||
|
||||
## 해결 완료 (이번 세션)
|
||||
|
||||
| 문제 | 상태 | 해결 방법 |
|
||||
|------|------|----------|
|
||||
| PopCanvas 타입 오류 | 미해결 | PopCanvas.tsx:76 |
|
||||
| 팔레트 UI 없음 | 미해결 | PopDesigner.tsx |
|
||||
| PopCanvas 타입 오류 | **해결** | 임시 타입 가드 추가 |
|
||||
| 팔레트 UI 없음 | **해결** | ComponentPalette.tsx 신규 추가 |
|
||||
| SVG 격자 좌표 불일치 | **해결** | CSS Grid 기반 통합 |
|
||||
| 드래그 좌표 완전 틀림 | **해결** | scale 보정 + calcGridPosition 함수 |
|
||||
| DND 타입 상수 불일치 | **해결** | constants/dnd.ts 통합 |
|
||||
| 컴포넌트 이동 안됨 | **해결** | useDrop/useDrag 타입 통일 |
|
||||
| 컴포넌트 중첩(겹침) | **해결** | toast import 추가 → 겹침 감지 로직 정상 작동 |
|
||||
| 리사이즈 핸들 작동 안됨 | **해결** | useDrop 통합 (2개 → 1개) |
|
||||
|
||||
---
|
||||
|
||||
## 드래그 좌표 버그 상세 (2026-02-05)
|
||||
|
||||
### 증상
|
||||
- 컴포넌트를 아래로 드래그 → 위로 올라감
|
||||
- Row 92 같은 비정상 좌표
|
||||
- 드래그 이동/리사이즈 전혀 작동 안됨
|
||||
|
||||
### 원인
|
||||
```
|
||||
캔버스: transform: scale(0.8)
|
||||
|
||||
getBoundingClientRect() → 스케일 적용된 크기 (1024px → 819px)
|
||||
getClientOffset() → 뷰포트 기준 실제 마우스 좌표
|
||||
|
||||
이 둘을 그대로 계산하면 좌표 완전 틀림
|
||||
```
|
||||
|
||||
### 해결
|
||||
```typescript
|
||||
// 스케일 보정된 상대 좌표 계산
|
||||
const relX = (offset.x - canvasRect.left) / canvasScale;
|
||||
const relY = (offset.y - canvasRect.top) / canvasScale;
|
||||
|
||||
// 실제 캔버스 크기로 그리드 계산
|
||||
calcGridPosition(relX, relY, customWidth, ...);
|
||||
```
|
||||
|
||||
### 교훈
|
||||
> CSS `transform: scale()` 적용된 요소에서 좌표 계산 시,
|
||||
> `getBoundingClientRect()`는 스케일 적용된 값을 반환하지만
|
||||
> 마우스 좌표는 뷰포트 기준이므로 **반드시 스케일 보정 필요**
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -10,17 +10,23 @@
|
||||
| 항목 | 값 |
|
||||
|------|-----|
|
||||
| 버전 | **v5** (CSS Grid 기반) |
|
||||
| 상태 | **기본 기능 완료** |
|
||||
| 다음 | 실제 테스트, Phase 4 (실제 컴포넌트 구현) |
|
||||
| 상태 | **반응형 레이아웃 + 숨김 기능 완료** |
|
||||
| 다음 | Phase 4 (실제 컴포넌트 구현) |
|
||||
|
||||
**마지막 업데이트**: 2026-02-05
|
||||
**마지막 업데이트**: 2026-02-05 심야
|
||||
|
||||
---
|
||||
|
||||
## 마지막 대화 요약
|
||||
|
||||
> (B)(C)(D) 모두 완료. 팔레트 UI 추가, 타입 오류 수정, 문서 v5 기준 통일.
|
||||
> 다음: 실제 테스트 후 Phase 4 (실제 컴포넌트 렌더링, 데이터 바인딩) 진행.
|
||||
> **반응형 레이아웃 시스템 완성**:
|
||||
> - 모드별 컴포넌트 재배치 (오버라이드) 시스템 구현
|
||||
> - 화면 밖 컴포넌트 오른쪽 패널 배치 기능
|
||||
> - 컴포넌트 숨김/숨김해제 기능 (모드별)
|
||||
> - 리사이즈 겹침 검사 추가
|
||||
> - H키 단축키로 숨김 처리
|
||||
>
|
||||
> 다음: Phase 4 (실제 컴포넌트 구현)
|
||||
|
||||
---
|
||||
|
||||
@@ -31,6 +37,7 @@
|
||||
| 지금 뭐 해야 해? | [STATUS.md](./STATUS.md) |
|
||||
| 저장/조회 규칙 | [SAVE_RULES.md](./SAVE_RULES.md) |
|
||||
| 왜 v5로 바꿨어? | [decisions/003-v5-grid-system.md](./decisions/003-v5-grid-system.md) |
|
||||
| 그리드 가이드 설계 | [decisions/004-grid-guide-integration.md](./decisions/004-grid-guide-integration.md) |
|
||||
| 이전 문제 해결 | [PROBLEMS.md](./PROBLEMS.md) |
|
||||
| 코드 어디 있어? | [FILES.md](./FILES.md) |
|
||||
| 기능별 색인 | [INDEX.md](./INDEX.md) |
|
||||
@@ -43,9 +50,10 @@
|
||||
| 파일 | 역할 | 경로 |
|
||||
|------|------|------|
|
||||
| 타입 정의 | v5 레이아웃 타입 | `frontend/components/pop/designer/types/pop-layout.ts` |
|
||||
| 캔버스 | 그리드 캔버스 + DnD | `frontend/components/pop/designer/PopCanvas.tsx` |
|
||||
| 렌더러 | CSS Grid 렌더링 | `frontend/components/pop/designer/renderers/PopRenderer.tsx` |
|
||||
| 캔버스 | 그리드 캔버스 + DnD + 라벨 | `frontend/components/pop/designer/PopCanvas.tsx` |
|
||||
| 렌더러 | CSS Grid 렌더링 + 격자 셀 | `frontend/components/pop/designer/renderers/PopRenderer.tsx` |
|
||||
| 디자이너 | 메인 컴포넌트 | `frontend/components/pop/designer/PopDesigner.tsx` |
|
||||
| 팔레트 | 컴포넌트 목록 | `frontend/components/pop/designer/panels/ComponentPalette.tsx` |
|
||||
|
||||
---
|
||||
|
||||
@@ -89,6 +97,8 @@ decisions/, sessions/, archive/
|
||||
|
||||
**핵심**: 컴포넌트를 칸 단위로 배치 (col, row, colSpan, rowSpan)
|
||||
|
||||
**그리드 가이드**: CSS Grid 기반 격자 셀 + 행/열 라벨 (ON/OFF 토글)
|
||||
|
||||
---
|
||||
|
||||
*상세: [SPEC.md](./SPEC.md) | 히스토리: [CHANGELOG.md](./CHANGELOG.md)*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 현재 상태
|
||||
|
||||
> **마지막 업데이트**: 2026-02-05
|
||||
> **마지막 업데이트**: 2026-02-05 심야
|
||||
> **담당**: POP 화면 디자이너
|
||||
|
||||
---
|
||||
@@ -15,27 +15,52 @@
|
||||
| v5 편집 패널 | 완료 | `ComponentEditorPanel.tsx` |
|
||||
| v5 유틸리티 | 완료 | `gridUtils.ts` |
|
||||
| 레거시 삭제 | 완료 | v1~v4 코드, 데이터 |
|
||||
| 문서 정리 | **완료** | popdocs v5 기준 재정비 |
|
||||
| 컴포넌트 팔레트 | **완료** | `ComponentPalette.tsx` |
|
||||
| 타입 오류 수정 | **완료** | PopCanvas.tsx:76 |
|
||||
| 드래그앤드롭 | **완료** | 팔레트 → 캔버스 연결 |
|
||||
| 문서 정리 | 완료 | popdocs v5 기준 재정비 |
|
||||
| 컴포넌트 팔레트 | 완료 | `ComponentPalette.tsx` |
|
||||
| 드래그앤드롭 | 완료 | 스케일 보정, DND 상수 통합 |
|
||||
| 그리드 가이드 재설계 | 완료 | CSS Grid 기반 통합 |
|
||||
| **모드별 오버라이드** | **완료** | 위치/크기 모드별 저장 |
|
||||
| **화면 밖 컴포넌트** | **완료** | 오른쪽 패널 배치, 드래그로 복원 |
|
||||
| **숨김 기능** | **완료** | 모드별 숨김/숨김해제 |
|
||||
| **리사이즈 겹침 검사** | **완료** | 실시간 겹침 방지 |
|
||||
|
||||
---
|
||||
|
||||
## 다음 작업 (우선순위)
|
||||
|
||||
1. **실제 테스트**
|
||||
- 디자이너 페이지에서 컴포넌트 드래그앤드롭 테스트
|
||||
- 저장/로드 동작 확인
|
||||
|
||||
2. **실제 컴포넌트 구현** (Phase 4)
|
||||
1. **실제 컴포넌트 구현** (Phase 4)
|
||||
- pop-label, pop-button 등 실제 렌더링
|
||||
- 데이터 바인딩 연결
|
||||
|
||||
3. **추가 기능**
|
||||
- 컴포넌트 복사/붙여넣기
|
||||
- 다중 선택
|
||||
- 정렬 도우미
|
||||
2. **워크플로우 연동**
|
||||
- 버튼 액션 연결
|
||||
- 화면 전환 로직
|
||||
|
||||
---
|
||||
|
||||
## 최근 주요 변경 (2026-02-05 심야)
|
||||
|
||||
### 반응형 레이아웃 시스템
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| 모드별 재배치 | 4/6/8/12칸 모드별로 컴포넌트 위치/크기 개별 저장 |
|
||||
| 자동 레이아웃 고정 | 드래그/리사이즈 시 자동으로 오버라이드 저장 |
|
||||
| 원본으로 되돌리기 | 오버라이드 삭제하여 자동 재배치로 복원 |
|
||||
|
||||
### 화면 밖 컴포넌트 처리
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| 오른쪽 패널 표시 | 현재 모드에서 초과하는 컴포넌트 별도 표시 |
|
||||
| 드래그로 복원 | 패널에서 그리드로 드래그하여 재배치 |
|
||||
| 위치 자동 조정 | 그리드 범위 초과 시 자동으로 왼쪽으로 밀어서 배치 |
|
||||
|
||||
### 숨김 기능
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| 모드별 숨김 | 특정 모드에서만 컴포넌트 숨김 가능 |
|
||||
| 숨김 방법 | 드래그→숨김패널 / H키 / 화면밖 컴포넌트 클릭 |
|
||||
| 숨김 해제 | 숨김패널에서 그리드로 드래그 |
|
||||
| 12칸 모드 제한 | 기본 모드(12칸)에서는 숨김 기능 비활성화 |
|
||||
|
||||
---
|
||||
|
||||
@@ -44,7 +69,11 @@
|
||||
| 문제 | 상태 | 비고 |
|
||||
|------|------|------|
|
||||
| 타입 이름 불일치 | 해결됨 | V5 접미사 제거 |
|
||||
| 팔레트 없음 | 해결됨 | ComponentPalette.tsx 추가 |
|
||||
| SVG 격자 좌표 불일치 | 해결됨 | GridGuide 삭제, CSS Grid 통합 |
|
||||
| 드래그 좌표 계산 오류 | 해결됨 | 스케일 보정 적용 |
|
||||
| DND 타입 상수 불일치 | 해결됨 | constants/dnd.ts로 통합 |
|
||||
| 숨김 컴포넌트 드래그 안됨 | 해결됨 | 상태 업데이트 순서 수정 |
|
||||
| 그리드 범위 초과 에러 | 해결됨 | 드롭 위치 자동 조정 |
|
||||
|
||||
---
|
||||
|
||||
@@ -52,7 +81,8 @@
|
||||
|
||||
| 날짜 | 요약 | 상세 |
|
||||
|------|------|------|
|
||||
| 2026-02-05 | v5 통합, 문서 재정비, 팔레트 UI 추가 | [sessions/2026-02-05.md](./sessions/2026-02-05.md) |
|
||||
| 2026-02-05 심야 | 반응형 레이아웃, 숨김 기능, 겹침 검사 | 이 세션 |
|
||||
| 2026-02-05 저녁 | v5 통합, 그리드 가이드 재설계 | [sessions/2026-02-05.md](./sessions/2026-02-05.md) |
|
||||
|
||||
---
|
||||
|
||||
@@ -60,6 +90,8 @@
|
||||
|
||||
| ADR | 제목 | 날짜 |
|
||||
|-----|------|------|
|
||||
| 005 | 반응형 레이아웃 및 숨김 기능 | 2026-02-05 |
|
||||
| 004 | 그리드 가이드 CSS Grid 통합 | 2026-02-05 |
|
||||
| 003 | v5 CSS Grid 채택 | 2026-02-05 |
|
||||
| 001 | v4 제약조건 기반 | 2026-02-03 |
|
||||
|
||||
|
||||
143
popdocs/decisions/004-grid-guide-integration.md
Normal file
143
popdocs/decisions/004-grid-guide-integration.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# ADR-004: 그리드 가이드 CSS Grid 통합
|
||||
|
||||
**상태**: 승인됨
|
||||
**날짜**: 2026-02-05
|
||||
**결정자**: 개발팀
|
||||
|
||||
---
|
||||
|
||||
## 컨텍스트
|
||||
|
||||
그리드 가이드는 다음 목적을 가짐:
|
||||
1. **시각적 기준**: 어디에 배치할지 눈으로 확인 가능
|
||||
2. **정렬 도움**: 칸에 맞춰 배치하기 쉬움
|
||||
3. **디자인 일관성**: 규칙적인 배치 유도
|
||||
|
||||
기존 구현:
|
||||
- `GridGuide.tsx`: SVG `<line>` 요소로 격자선 렌더링
|
||||
- `PopRenderer.tsx`: CSS Grid로 컴포넌트 배치
|
||||
|
||||
---
|
||||
|
||||
## 문제
|
||||
|
||||
### 좌표계 불일치
|
||||
```
|
||||
SVG 좌표: 픽셀 기반 (0, 0) ~ (width, height)
|
||||
CSS Grid 좌표: 칸 기반 (col 1~12, row 1~20)
|
||||
|
||||
→ 두 좌표계를 정확히 동기화하기 어려움
|
||||
→ 격자선과 컴포넌트가 정렬되지 않음 ("무늬가 따로 논다")
|
||||
```
|
||||
|
||||
### 구체적 증상
|
||||
1. GridGuide의 행/열 라벨이 4부터 시작 (잘못된 계산)
|
||||
2. 격자선 위치와 실제 CSS Grid 셀 위치 불일치
|
||||
3. 줌/패닝 시 두 레이어가 다르게 동작
|
||||
|
||||
---
|
||||
|
||||
## 결정
|
||||
|
||||
**GridGuide.tsx를 삭제하고, PopRenderer.tsx에서 CSS Grid 기반으로 격자를 직접 렌더링한다.**
|
||||
|
||||
핵심 원칙:
|
||||
> "격자선은 컴포넌트와 같은 좌표계에서 태어나야 한다"
|
||||
|
||||
---
|
||||
|
||||
## 대안 검토
|
||||
|
||||
### Option A: SVG 계산 수정
|
||||
- **방법**: GridGuide의 좌표 계산을 정확히 수정
|
||||
- **장점**: 기존 코드 활용
|
||||
- **단점**: 근본적으로 두 좌표계가 다름, 유지보수 어려움
|
||||
- **결정**: 채택 안 함
|
||||
|
||||
### Option B: PopRenderer에 CSS 배경 격자
|
||||
- **방법**: `background-image: linear-gradient()`로 격자 표현
|
||||
- **장점**: 구현 간단
|
||||
- **단점**: 라벨 표시 불가, 셀 단위 상호작용 불가
|
||||
- **결정**: 채택 안 함
|
||||
|
||||
### Option C: CSS Grid 셀로 격자 렌더링 (채택)
|
||||
- **방법**: 실제 `div` 요소를 12x20 = 240개 생성, CSS Grid로 배치
|
||||
- **장점**:
|
||||
- 컴포넌트와 100% 동일한 좌표계
|
||||
- 셀 단위 hover, 클릭 등 상호작용 가능
|
||||
- 라벨은 캔버스 외부에 별도 렌더링
|
||||
- **단점**: DOM 요소 증가 (240개)
|
||||
- **결정**: 채택
|
||||
|
||||
---
|
||||
|
||||
## 구현 상세
|
||||
|
||||
### 역할 분담
|
||||
|
||||
| 컴포넌트 | 역할 | 좌표계 |
|
||||
|----------|------|--------|
|
||||
| PopRenderer | 격자 셀 + 컴포넌트 | CSS Grid |
|
||||
| PopCanvas | 라벨 + 줌/패닝 + 토글 | absolute |
|
||||
| GridGuide | (삭제) | - |
|
||||
|
||||
### PopRenderer 변경
|
||||
|
||||
```typescript
|
||||
// gridCells 생성 (useMemo)
|
||||
const gridCells = useMemo(() => {
|
||||
const cells = [];
|
||||
for (let row = 1; row <= 20; row++) {
|
||||
for (let col = 1; col <= 12; col++) {
|
||||
cells.push({ id: `${col}-${row}`, col, row });
|
||||
}
|
||||
}
|
||||
return cells;
|
||||
}, []);
|
||||
|
||||
// 렌더링
|
||||
{showGridGuide && gridCells.map(cell => (
|
||||
<div
|
||||
key={cell.id}
|
||||
className="border border-dashed border-blue-300/40"
|
||||
style={{
|
||||
gridColumn: cell.col,
|
||||
gridRow: cell.row,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
```
|
||||
|
||||
### PopCanvas 라벨 구조
|
||||
|
||||
```
|
||||
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10][11][12] ← 열 라벨 (캔버스 상단)
|
||||
┌───────────────────────────────────────────┐
|
||||
[1] │ │ │ │ │ │ │ │ │ │ │ │
|
||||
[2] │ │ │ │ │ │ │ │ │ │ │ │
|
||||
[3] │ │ │ │ ■ │ │ │ │ │ │ │ │ ← 5열 3행
|
||||
└───────────────────────────────────────────┘
|
||||
↑ 행 라벨 (캔버스 좌측)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 결과
|
||||
|
||||
### 기대 효과
|
||||
1. 격자선과 컴포넌트 100% 정렬
|
||||
2. 정확한 행/열 번호 표시 (1부터 시작)
|
||||
3. 줌/패닝 시 일관된 동작
|
||||
4. 향후 셀 클릭으로 빠른 배치 기능 확장 가능
|
||||
|
||||
### 트레이드오프
|
||||
- DOM 요소 240개 추가 (성능 영향 미미)
|
||||
- GridGuide 코드 삭제 필요
|
||||
|
||||
---
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- 문제: [PROBLEMS.md](../PROBLEMS.md) > P004
|
||||
- 변경: [CHANGELOG.md](../CHANGELOG.md) > 2026-02-05 오후
|
||||
- 세션: [sessions/2026-02-05.md](../sessions/2026-02-05.md)
|
||||
@@ -1,12 +1,21 @@
|
||||
# 2026-02-05 작업 기록
|
||||
|
||||
## 요약
|
||||
v5 그리드 시스템 통합 완료, popdocs 문서 구조 재정비
|
||||
v5 그리드 시스템 통합 완료, 그리드 가이드 재설계, **드래그앤드롭 좌표 버그 수정**, popdocs 문서 구조 재정비
|
||||
|
||||
---
|
||||
|
||||
## 완료
|
||||
|
||||
### 드래그앤드롭 완전 수정 (저녁)
|
||||
- [x] 스케일 보정 누락 문제 해결
|
||||
- [x] calcGridPosition 함수 추가
|
||||
- [x] DND 타입 상수 통합 (constants/dnd.ts)
|
||||
- [x] 불필요한 toast 메시지 제거
|
||||
- [x] 컴포넌트 이동/리사이즈 정상 작동 확인
|
||||
- [x] **컴포넌트 중첩(겹침) 문제 해결** - toast import 누락 수정
|
||||
- [x] **리사이즈 핸들 작동 문제 해결** - useDrop 훅 통합
|
||||
|
||||
### v5 통합 작업
|
||||
- [x] 레거시 파일 삭제 (PopCanvasV4, PopFlexRenderer, PopLayoutRenderer 등)
|
||||
- [x] 파일명 정규화 (V5 접미사 제거)
|
||||
@@ -22,31 +31,64 @@ v5 그리드 시스템 통합 완료, popdocs 문서 구조 재정비
|
||||
- [x] INDEX.md 생성 (기능별 색인)
|
||||
- [x] sessions/ 폴더 구조 도입
|
||||
|
||||
### 디자이너 완성 작업
|
||||
- [x] 컴포넌트 팔레트 UI 추가 (ComponentPalette.tsx)
|
||||
- [x] PopCanvas.tsx 타입 오류 수정
|
||||
- [x] 드래그앤드롭 연결
|
||||
|
||||
### 그리드 가이드 재설계
|
||||
- [x] GridGuide.tsx 삭제 (SVG 기반 → 좌표 불일치 문제)
|
||||
- [x] PopRenderer.tsx 격자 셀 렌더링 (CSS Grid 기반, 동일 좌표계)
|
||||
- [x] PopCanvas.tsx 행/열 라벨 추가 (캔버스 바깥)
|
||||
- [x] 컴포넌트 타입 단순화 (pop-sample 1개)
|
||||
|
||||
### 기반 정리 작업
|
||||
- [x] pop-layout.ts: PopComponentType을 pop-sample 1개로 단순화
|
||||
- [x] ComponentPalette.tsx: 샘플 박스 1개만 표시
|
||||
- [x] PopRenderer.tsx: 샘플 박스 렌더링으로 단순화
|
||||
|
||||
---
|
||||
|
||||
## 미완료
|
||||
|
||||
- [ ] 컴포넌트 팔레트 UI 추가 (PopDesigner.tsx 좌측)
|
||||
- [ ] PopCanvas.tsx 타입 오류 수정 (line 76)
|
||||
- [ ] ARCHITECTURE.md v5 기준 업데이트
|
||||
- [ ] CHANGELOG.md 오늘 작업 추가
|
||||
- [x] 실제 화면 테스트 (디자이너 페이지) → 완료, 정상 작동
|
||||
- [ ] 간격 조정 규칙 결정 (전역 고정 vs 화면별 vs 컴포넌트별)
|
||||
|
||||
---
|
||||
|
||||
## 중단점
|
||||
## 그리드 가이드 재설계 상세
|
||||
|
||||
> **다음 작업자 참고**:
|
||||
>
|
||||
> 1. **타입 오류**: PopCanvas.tsx line 76
|
||||
> - `}: PopCanvasV5Props)` → `}: PopCanvasProps)`로 변경
|
||||
> - 인터페이스는 이미 `PopCanvasProps`로 정의됨 (line 48)
|
||||
>
|
||||
> 2. **팔레트 UI**: PopDesigner.tsx에 컴포넌트 팔레트 추가 필요
|
||||
> - 위치: 좌측 ResizablePanel (현재 비어있음)
|
||||
> - 참고: 이전 ComponentPaletteV4.tsx (삭제됨, archive에서 참고 가능)
|
||||
> - DnD 타입: PopCanvas.tsx에 `DND_ITEM_TYPES` 인라인 정의됨
|
||||
>
|
||||
> 3. **문서**: ARCHITECTURE.md가 아직 v3/v4 기준임
|
||||
### 문제 원인
|
||||
1. GridGuide.tsx가 SVG로 별도 렌더링 → CSS Grid 기반 컴포넌트와 좌표계 불일치
|
||||
2. PopRenderer의 그리드 배경이 희미 (rgba 0.2)
|
||||
3. 행/열 번호 라벨 없음
|
||||
|
||||
### 해결 방안 (Option C 하이브리드)
|
||||
```
|
||||
역할 분담:
|
||||
- PopRenderer: 격자선 + 컴포넌트 (같은 좌표계)
|
||||
- PopCanvas: 라벨 + 줌/패닝 + 드롭존
|
||||
- GridGuide: 삭제
|
||||
```
|
||||
|
||||
### 핵심 설계
|
||||
```
|
||||
SVG 격자 (별도 좌표) → CSS Grid 셀 (동일 좌표)
|
||||
- gridCells: 12열 × 20행 = 240개 실제 DOM 셀
|
||||
- border-dashed border-blue-300/40 스타일
|
||||
- 컴포넌트는 z-index:10으로 위에 표시
|
||||
```
|
||||
|
||||
### 라벨 구조
|
||||
```
|
||||
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10][11][12] ← 열 라벨 (캔버스 상단)
|
||||
┌───────────────────────────────────────────┐
|
||||
[1] │ │ │ │ │ │ │ │ │ │ │ │
|
||||
[2] │ │ │ │ │ │ │ │ │ │ │ │
|
||||
[3] │ │ │ │ ■ │ │ │ │ │ │ │ │ ← 5열 3행
|
||||
└───────────────────────────────────────────┘
|
||||
↑ 행 라벨 (캔버스 좌측)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -58,28 +100,78 @@ v5 그리드 시스템 통합 완료, popdocs 문서 구조 재정비
|
||||
- **연구**: Softr, Ant Design, Material Design 분석
|
||||
- **결정**: CSS Grid 기반 그리드 시스템 채택
|
||||
|
||||
### 그리드 가이드 재설계 배경
|
||||
- **문제**: SVG GridGuide와 CSS Grid PopRenderer가 좌표계 불일치
|
||||
- **원칙**: "격자선은 컴포넌트와 같은 좌표계에서 태어나야 한다"
|
||||
- **결정**: CSS Grid 기반 실제 DOM 셀로 격자 렌더링
|
||||
|
||||
### popdocs 재정비 배경
|
||||
- **문제**: 문서 구조가 AI 에이전트 진입점 역할 못함
|
||||
- **해결**: Progressive Disclosure 적용, 저장/조회 규칙 명시화
|
||||
- **참고**: 2025-2026 AI 컨텍스트 엔지니어링 최신 기법
|
||||
|
||||
### 핵심 결정
|
||||
- Layer 1 (진입점): README, STATUS, SAVE_RULES
|
||||
- Layer 2 (상세): CHANGELOG, PROBLEMS, INDEX 등
|
||||
- Layer 3 (심화): decisions/, sessions/, archive/
|
||||
---
|
||||
|
||||
## 빌드 결과
|
||||
|
||||
```
|
||||
exit_code: 0
|
||||
popScreenMngList: 29.4 kB (311 KB First Load)
|
||||
총 변경: 8,453줄 삭제, 1,819줄 추가 (순감 6,634줄)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 관련 링크
|
||||
|
||||
- ADR: [decisions/003-v5-grid-system.md](../decisions/003-v5-grid-system.md)
|
||||
- CHANGELOG: 오늘 작업 추가 필요
|
||||
- 삭제된 파일 목록: FILES.md 하단 "삭제된 파일" 섹션
|
||||
|
||||
---
|
||||
|
||||
## 메모
|
||||
## 드래그앤드롭 좌표 버그 수정 상세
|
||||
|
||||
- POPUPDATE.md (루트)는 별도로 유지 (전체 프로젝트 기록용)
|
||||
- popdocs/는 POP 디자이너 개발 전용
|
||||
- rangraph 연동 고려 (장기 기억 검색용)
|
||||
### 문제 현상
|
||||
- 컴포넌트를 아래로 드래그해도 위로 올라감
|
||||
- Row 92 같은 비정상적인 좌표로 배치됨
|
||||
- 드래그 이동/리사이즈가 전혀 작동하지 않음
|
||||
|
||||
### 핵심 원인
|
||||
캔버스에 `transform: scale(0.8)` 적용 시 좌표 계산 불일치:
|
||||
```
|
||||
getBoundingClientRect() → 스케일 적용된 크기 (1024px → 819px)
|
||||
getClientOffset() → 뷰포트 기준 실제 마우스 좌표
|
||||
이 둘을 그대로 계산하면 좌표가 완전히 틀림
|
||||
```
|
||||
|
||||
### 해결 방법
|
||||
단순한 상대 좌표 + 스케일 보정:
|
||||
```typescript
|
||||
// 캔버스 내 상대 좌표 (스케일 보정)
|
||||
const relX = (offset.x - canvasRect.left) / canvasScale;
|
||||
const relY = (offset.y - canvasRect.top) / canvasScale;
|
||||
|
||||
// 그리드 좌표 계산 (실제 캔버스 크기 사용)
|
||||
calcGridPosition(relX, relY, customWidth, breakpoint.columns, ...);
|
||||
```
|
||||
|
||||
### 추가 수정
|
||||
- DND 타입 상수를 3개 파일에서 중복 정의 → `constants/dnd.ts`로 통합
|
||||
- 불필요한 "컴포넌트가 이동되었습니다" toast 메시지 제거
|
||||
|
||||
---
|
||||
|
||||
## 다음 작업자 참고
|
||||
|
||||
1. **테스트 완료**
|
||||
- 디자이너 페이지에서 그리드 가이드 확인 ✅
|
||||
- 컴포넌트 드래그앤드롭 테스트 ✅
|
||||
- 4가지 모드 전환 테스트 (추가 확인 필요)
|
||||
|
||||
2. **향후 결정 필요**
|
||||
- 간격 조정: 전역 고정 vs 화면별 vs 컴포넌트별
|
||||
- 행 수: 현재 20행 고정, 동적 변경 여부
|
||||
|
||||
3. **Phase 4 준비**
|
||||
- 실제 컴포넌트 구현 (pop-label, pop-button 등)
|
||||
- 데이터 바인딩 연결
|
||||
|
||||
Reference in New Issue
Block a user