6.2 KiB
6.2 KiB
ADR 006: v5.1 자동 줄바꿈 + 검토 필요 시스템
날짜: 2026-02-06
상태: 채택
의사결정자: 시스템 아키텍트
상황 (Context)
v5 반응형 레이아웃에서 "화면 밖" 개념으로 컴포넌트를 처리했으나, 다음 문제가 발생했습니다:
문제 1: 정보 손실
12칸 모드:
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ A │ B (col=5, 6칸) │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
4칸 모드 (기존):
┌────┬────┬────┬────┐ 화면 밖:
│ A │ │ - B
└────┴────┴────┴────┘
↑ A만 보임 ↑ 뷰어에서 안 보임!
문제 2: 사용자 의도 불일치
사용자가 기대한 "화면 밖" 역할:
- ❌ 컴포넌트 숨김 (현재 동작)
- ✅ "이 컴포넌트 검토 필요" 알림
결정 (Decision)
채택: 자동 줄바꿈 + 검토 필요 시스템
col > maxCol → 자동으로 맨 아래에 배치 (줄바꿈)
오버라이드 없음 → "검토 필요" 알림
구현 (Implementation)
1. 자동 줄바꿈 로직
파일: gridUtils.ts - convertAndResolvePositions()
// 단계별 처리:
1. 비율 변환 + 원본 col 보존
converted = components.map(comp => ({
id: comp.id,
position: convertPositionToMode(comp.position, targetMode),
originalCol: comp.position.col, // ⭐ 원본 보존
}))
2. 정상 vs 초과 분리
normalComponents = originalCol ≤ targetColumns
overflowComponents = originalCol > targetColumns
3. 초과 컴포넌트 자동 배치
maxRow = normalComponents의 최대 row
overflowComponents → col=1, row=맨아래+1
4. 겹침 해결
resolveOverlaps([...normalComponents, ...wrappedComponents])
2. 검토 필요 판별
파일: gridUtils.ts - needsReview()
function needsReview(
currentMode: GridMode,
hasOverride: boolean
): boolean {
// 12칸 모드는 기본 모드이므로 검토 불필요
if (GRID_BREAKPOINTS[currentMode].columns === 12) return false;
// 오버라이드가 있으면 이미 편집함 → 검토 완료
if (hasOverride) return false;
// 오버라이드 없으면 → 검토 필요
return true;
}
판단 기준 (최종): "이 모드에서 편집했냐 안 했냐"
3. 검토 필요 패널
파일: PopCanvas.tsx - ReviewPanel
// 필터링
const reviewComponents = visibleComponents.filter(comp => {
const hasOverride = !!layout.overrides?.[currentMode]?.positions?.[comp.id];
return needsReview(currentMode, hasOverride);
});
// UI
<ReviewPanel
components={reviewComponents}
onSelectComponent={onSelectComponent} // 클릭 시 선택
/>
변경 사항:
- 기존:
OutOfBoundsPanel(주황색, 드래그로 복원) - 변경:
ReviewPanel(파란색, 클릭으로 선택)
결과 (Consequences)
긍정적 효과
| 효과 | 설명 |
|---|---|
| 정보 손실 방지 | 모든 컴포넌트가 항상 그리드 안에 표시됨 |
| 사용자 부담 감소 | 자동 배치를 먼저 제공, 필요시에만 편집 |
| 의도 명확화 | "숨김" ≠ "검토 필요" (기능 분리) |
| 뷰어 호환 | 자동 배치가 뷰어에도 적용됨 |
트레이드오프
| 항목 | 설명 |
|---|---|
| 스크롤 증가 | 아래로 자동 배치되면 페이지가 길어질 수 있음 |
| 자동 배치 품질 | 사용자가 원하지 않는 위치에 배치될 수 있음 |
사용자 시나리오
시나리오 1: 수용 (자동 배치 그대로)
1. 12칸에서 컴포넌트 A, B, C 배치
2. 4칸 모드로 전환
3. 시스템: 자동 배치 + "검토 필요 (3개)" 알림
4. 사용자: 확인 → "괜찮네" → 아무것도 안 함
5. 결과: 자동 배치 유지 (오버라이드 없음)
시나리오 2: 편집 (오버라이드 저장)
1. 12칸에서 컴포넌트 A, B, C 배치
2. 4칸 모드로 전환
3. 시스템: 자동 배치 + "검토 필요 (3개)" 알림
4. 사용자: A 클릭 → 드래그/리사이즈
5. 결과: A 오버라이드 저장 → A 검토 완료
6. "검토 필요 (2개)" (B, C만 남음)
시나리오 3: 보류 (나중에)
1. 12칸에서 컴포넌트 A, B, C 배치
2. 4칸 모드로 전환
3. 시스템: 자동 배치 + "검토 필요 (3개)" 알림
4. 사용자: 다른 모드로 전환 또는 저장
5. 결과: 자동 배치 유지, 나중에도 "검토 필요" 표시
기능 비교
| 구분 | 역할 | 뷰어에서 | 판단 기준 |
|---|---|---|---|
| 검토 필요 | 자동 배치 알림 | 보임 | 오버라이드 없음 |
| 숨김 | 의도적 숨김 | 안 보임 | hidden 배열에 ID |
대안 (Alternatives Considered)
A안: 완전 자동 (채택 ✅)
- 모든 초과 컴포넌트 자동 배치
- "검토 필요" 알림으로 확인 유도
- 업계 표준 (Webflow, Retool)
B안: 선택적 자동 (미채택)
- 첫 전환 시만 자동 배치
- 사용자가 원하면 "화면 밖"으로 드래그
- 복잡성 증가
C안: 수동 배치 유지 (미채택)
- 기존 "화면 밖" 패널 유지
- 사용자가 모든 모드 수동 편집
- 사용자 부담 과다
참고 자료
업계 표준 (2026년 기준)
- Grafana, Tableau: Masonry Layout (조적식)
- Retool, PowerApps: Vertical Stacking (수직 스택)
- Webflow, Framer: CSS Grid Auto-Placement
공통점: "Fluid Reflow (유동적 재배치)" - 정보 손실 방지
관련 파일
| 파일 | 변경 내용 |
|---|---|
gridUtils.ts |
convertAndResolvePositions, needsReview 추가 |
PopCanvas.tsx |
ReviewPanel로 변경 |
PopRenderer.tsx |
isOutOfBounds import 제거 |
pop-layout.ts |
타입 변경 없음 (기존 구조 유지) |
결론: 자동 줄바꿈 + 검토 필요 시스템으로 정보 손실 방지 및 사용자 부담 최소화