144 lines
4.0 KiB
Markdown
144 lines
4.0 KiB
Markdown
# 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)
|