ERP-node/popdocs/sessions/2026-02-06.md

7.6 KiB

2026-02-06 작업 기록

요약

v5.1 자동 줄바꿈 + 검토 필요 시스템 완성, 브레이크포인트 재설계, 세로 자동 확장 구현


완료

브레이크포인트 재설계

  • GRID_BREAKPOINTS 값 수정 (기기 기반)
  • detectGridMode() 조건 수정
  • useDeviceOrientation.ts TABLET_MIN 768로 변경
  • 뷰어에서 detectGridMode() 사용하여 일관성 확보

세로 자동 확장

  • VIEWPORT_PRESETS에서 height 속성 제거
  • dynamicCanvasHeight useMemo 추가
  • MIN_CANVAS_HEIGHT, CANVAS_EXTRA_ROWS 상수 추가
  • gridLabels 동적 계산 (행 수 자동 조정)
  • gridCells 동적 계산 (PopRenderer)
  • 뷰어 프리뷰 모드 스크롤 지원

자동 줄바꿈 시스템 (v5.1)

  • convertAndResolvePositions() 자동 줄바꿈 로직
  • 원본 col 보존 로직
  • 초과 컴포넌트 맨 아래 배치
  • colSpan 자동 축소

검토 필요 시스템

  • needsReview() 함수 추가
  • OutOfBoundsPanel → ReviewPanel 변경
  • 파란색 테마 (안내 느낌)
  • 클릭 시 컴포넌트 선택

버그 수정

  • hiddenComponentIds 중복 정의 에러 수정
  • useDrop 의존성 배열 수정
  • 검토 필요 패널 모드별 표시 불일치 수정

그리드 셀 크기 강제 고정 (v5.2.1)

  • gridAutoRows → gridTemplateRows 변경 (행 높이 강제 고정)
  • dynamicRowCount를 gridStyle과 gridCells에서 공유
  • 컴포넌트 overflow: visible → overflow: hidden 변경
  • PopRenderer dynamicRowCount에서 숨김 컴포넌트 제외
  • PopCanvas와 PopRenderer의 여유행 기준 통일 (+3)
  • 디버깅용 console.log 2개 삭제
  • 뷰어 page.tsx viewportWidth 선언 순서 수정

브레이크포인트 변경 상세

변경 전 → 변경 후

모드 변경 전 변경 후 근거
mobile_portrait ~599px ~479px 스마트폰 세로 최대 440px
mobile_landscape 600~839px 480~767px 767px까지 스마트폰
tablet_portrait 840~1023px 768~1023px iPad Mini 768px 포함
tablet_landscape 1024px+ 동일 변경 없음

연구 결과 (기기별 CSS 뷰포트)

기기 CSS 뷰포트 너비
iPhone SE 375px
iPhone 16 Pro 402px
Galaxy S25 Ultra 440px
iPad Mini 7 768px
iPad Pro 11 834px (세로), 1194px (가로)
iPad Pro 13 1024px (세로), 1366px (가로)

세로 자동 확장 상세

핵심 상수

const MIN_CANVAS_HEIGHT = 600;  // 최소 캔버스 높이 (px)
const CANVAS_EXTRA_ROWS = 3;    // 항상 유지되는 여유 행 수

동적 높이 계산 로직

const dynamicCanvasHeight = useMemo(() => {
  const visibleComps = Object.values(layout.components)
    .filter(comp => !hiddenComponentIds.includes(comp.id));

  if (visibleComps.length === 0) return MIN_CANVAS_HEIGHT;

  const maxRowEnd = visibleComps.reduce((max, comp) => {
    const pos = getEffectivePosition(comp);
    return Math.max(max, pos.row + pos.rowSpan);
  }, 1);

  const totalRows = maxRowEnd + CANVAS_EXTRA_ROWS;
  const height = totalRows * (rowHeight + gap) + padding * 2;

  return Math.max(MIN_CANVAS_HEIGHT, height);
}, [dependencies]);

영향받는 영역

영역 변경
캔버스 컨테이너 minHeight: dynamicCanvasHeight
디바이스 스크린 minHeight: dynamicCanvasHeight
행 라벨 동적 행 수 계산
격자 셀 동적 행 수 계산

자동 줄바꿈 로직 상세

처리 단계

1. 비율 변환 + 원본 col 보존
   converted = map(comp => ({
     position: convertPositionToMode(comp.position),
     originalCol: comp.position.col,  // 원본 보존
   }))

2. 정상 vs 초과 분리
   normalComponents = filter(originalCol <= targetColumns)
   overflowComponents = filter(originalCol > targetColumns)

3. 초과 컴포넌트 맨 아래 배치
   maxRow = normalComponents의 최대 (row + rowSpan - 1)
   overflowComponents → col=1, row=maxRow+1

4. colSpan 자동 축소
   if (colSpan > targetColumns) colSpan = targetColumns

5. 겹침 해결
   resolveOverlaps([...normalComponents, ...wrappedComponents])

대화 핵심

반응형 불일치 문제

사용자 리포트:

"아이폰 SE, iPad Pro 프리셋은 잘 되는데, 브라우저 수동 리사이즈 시 6칸 모드가 적용 안 되는 것 같아"

원인 분석:

  • useResponsiveMode: width/height 비율로 landscape/portrait 판정
  • GRID_BREAKPOINTS: 순수 너비 기반
  • 768~839px 구간에서 불일치 발생

해결:

  • 뷰어에서 detectGridMode(viewportWidth) 사용
  • 프리뷰 모드만 useResponsiveModeWithOverride 유지

세로 무한 스크롤 결정

사용자 질문:

"우리 화면 모드는 너비만 신경쓰면 되잖아? 세로는 무한 스크롤이 가능해야 하겠네?"

확인 사항:

  1. 너비만 신경쓰면 됨
  2. 캔버스 세로 무한 스크롤 필요
  3. 뷰어에서 터치 스크롤 지원

구현 방식 선택:

  • 수동 행 추가 방식 vs 자동 확장 방식 (채택)
  • 이유: 여유 공간 3행 자동 유지, 사용자 부담 최소화

빌드 결과

exit_code: 0
주요 변경 파일: 6개

관련 링크


이번 작업에서 배운 것

새로 알게 된 기술 개념

  • gridAutoRows vs gridTemplateRows: gridAutoRows는 행의 최소 높이만 보장하고 콘텐츠에 따라 늘어날 수 있음. gridTemplateRows는 행 높이를 강제 고정함. 가이드 셀과 컴포넌트가 같은 Grid 컨테이너에 있을 때, 컴포넌트 콘텐츠가 행 높이를 밀어내면 인접한 빈 가이드 셀 크기도 함께 변해 시각적 불일치가 발생함.

발생했던 에러와 원인 패턴

에러 원인 패턴
그리드 셀 크기 불균일 같은 CSS Grid에서 gridAutoRows(최소값)를 사용하면 콘텐츠가 행 높이를 변형시킴
Canvas vs Renderer 행 수 불일치 같은 데이터(행 수)를 두 곳에서 계산하면서 필터 조건(숨김 제외)이 달랐음
디버깅 console.log 잔존 기능 완료 후 정리 단계를 생략함
viewportWidth 참조 순서 변수 사용 코드가 선언 코드보다 위에 위치 (JS 호이스팅으로 동작은 하지만 가독성 저하)

다음에 비슷한 작업할 때 주의할 점

  1. CSS Grid에서 "고정 크기" 셀이 필요하면 gridTemplateRows를 사용하고, gridAutoRows는 동적 추가행 대비용으로만 유지
  2. 같은 데이터를 여러 곳에서 계산할 때, 필터 조건이 동일한지 반드시 비교 (숨김 제외 등)
  3. 기능 완료 후 console.log를 Grep으로 검색하여 디버깅 로그 정리
  4. 변수 선언 순서는 의존 관계 순서와 일치시켜야 가독성과 유지보수성 확보

중단점

다음 작업: Phase 4 실제 컴포넌트 구현

  • pop-label, pop-button 등 실제 렌더링 구현
  • 데이터 바인딩 연결
  • STATUS.md의 "다음 작업" 섹션 참조

다음 작업자 참고

  1. 테스트 필요

    • 아이폰 SE 실기기 테스트
    • iPad Mini 세로 모드 확인
    • 브라우저 리사이즈로 모드 전환 확인
  2. 향후 작업

    • Phase 4: 실제 컴포넌트 구현 (pop-label, pop-button 등)
    • 데이터 바인딩 연결
    • 워크플로우 연동