문제:
1. ColumnVisibilityPanel에서 순서 변경 후 onColumnOrderChange가 호출되지 않음
2. 필터 입력 시 데이터가 제대로 필터링되지 않음
3. useAuth 훅 import 경로 오류 (@/hooks/use-auth → @/hooks/useAuth)
해결:
1. ColumnVisibilityPanel.handleApply()에 onColumnOrderChange 호출 추가
2. 필터 변경 감지 및 데이터 로드 로직 디버깅 로그 추가
3. useAuth import 경로 수정
테스트:
- 거래처관리 화면에서 컬럼 순서 변경 → 실시간 반영 ✅
- 페이지 새로고침 → 순서 유지 (localStorage) ✅
- 필터 입력 → 필터 변경 감지 (추가 디버깅 필요)
- FilterPanel: 필터별 너비(width) 설정 기능 추가 (50-500px)
- TableSearchWidget: 필터가 여러 줄로 자동 wrap되도록 flex-wrap 적용
- TableSearchWidget: 필터 너비 설정을 localStorage에 저장/복원
- InteractiveScreenViewerDynamic: TableSearchWidget의 높이를 auto로 설정하여 콘텐츠에 맞게 자동 조정
- globals.css: 입력 필드 포커스 시 검정 테두리 제거 (combobox, input)
주요 변경사항:
1. 필터 설정에서 각 필터의 표시 너비를 개별 설정 가능
2. 필터가 많을 때 자동으로 여러 줄로 배치 (overflow 방지)
3. 설정된 필터 너비가 새로고침 후에도 유지됨
4. TableSearchWidget 높이가 콘텐츠에 맞게 자동 조정
TODO: TableSearchWidget 높이 변화 시 아래 컴포넌트 자동 재배치 기능 구현 예정
- TableRegistration에 getColumnUniqueValues 콜백 함수 추가
- TableListComponent에서 현재 데이터의 고유 값 추출 함수 구현
- TableSearchWidget에서 select 타입 필터의 옵션을 자동으로 로드
- 테이블 데이터가 변경되면 필터 옵션도 자동 업데이트
- 데이터 건수 표시 기능도 함께 수정 (등록 순서 문제 해결)
- TableOptionsContext 기반 테이블 자동 감지 시스템 구현
- 독립 위젯으로 드래그앤드롭 배치 가능
- 3가지 기능: 컬럼 가시성, 필터 설정, 그룹 설정
- FlowWidget, TableList, SplitPanel 등 모든 테이블 컴포넌트 지원
- 유틸리티 카테고리에 등록 (1920×80px)
- 위젯 크기 제어 가이드 룰 파일에 추가
- 백엔드: screenManagementService에 getMenuByScreen 함수 추가
- 백엔드: GET /api/screen-management/screens/:id/menu 엔드포인트 추가
- 프론트엔드: screenApi.getScreenMenu() 함수 추가
- ScreenDesigner: 화면 로드 시 menu_objid 자동 조회
- ScreenDesigner: menuObjid를 RealtimePreview와 UnifiedPropertiesPanel에 전달
- UnifiedPropertiesPanel: menuObjid를 DynamicComponentConfigPanel에 전달
이로써 화면 편집기에서 코드/카테고리/채번규칙이 해당 화면이 할당된 메뉴 기준으로 필터링됨
- useCodeOptions 훅에 menuObjid 파라미터 추가
- commonCodeApi.codes.getList에 menuObjid 전달
- SelectBasicComponent에서 menuObjid 받아서 useCodeOptions로 전달
- InteractiveScreenViewer에서 DynamicWebTypeRenderer로 menuObjid 전달
- 화면 페이지에서 RealtimePreview로 menuObjid 전달
이제 코드 위젯도 카테고리처럼 형제 메뉴별로 격리됩니다.
✅ 구현 내용:
1. 백엔드 API 추가
- GET /api/table-management/menu/:menuObjid/category-columns
- 형제 메뉴들의 테이블에서 카테고리 타입 컬럼 조회
- menuService.getSiblingMenuObjids() 재사용
2. 프론트엔드 CategoryWidget 수정
- menuObjid를 props로 받아 CategoryColumnList에 전달
- effectiveMenuObjid로 props.menuObjid도 처리
- 선택된 컬럼에 tableName 포함하여 상태 관리
3. CategoryColumnList 수정
- menuObjid 기반으로 형제 메뉴의 모든 카테고리 컬럼 조회
- 테이블명+컬럼명 함께 표시
- onColumnSelect에 tableName 전달
4. 메뉴 네비게이션 수정
- AppLayout.tsx: 화면 이동 시 menuObjid를 URL 쿼리 파라미터로 전달
- useMenu.ts: 동일하게 menuObjid 전달
- page.tsx: 자식 컴포넌트에도 menuObjid 전달
🎯 효과:
- 이제 형제 메뉴들이 서로 다른 테이블을 사용해도 카테고리 공유 가능
- 메뉴 클릭 → 화면 이동 시 자동으로 menuObjid 전달
- 카테고리 위젯이 형제 메뉴의 모든 카테고리 컬럼 표시
✅ 주요 변경사항:
- 백엔드: menuService.ts 추가 (형제 메뉴 조회 유틸리티)
- 백엔드: numberingRuleService.getAvailableRulesForMenu() 메뉴 스코프 적용
- 백엔드: tableCategoryValueService 메뉴 스코프 준비 (menuObjid 파라미터 추가)
- 프론트엔드: TextInputConfigPanel에 부모 메뉴 선택 UI 추가
- 프론트엔드: 메뉴별 채번규칙 필터링 (형제 메뉴 공유)
🔧 기술 세부사항:
- getSiblingMenuObjids(): 같은 부모를 가진 형제 메뉴 OBJID 조회
- 채번규칙 우선순위: menu (형제) > table > global
- 사용자 메뉴(menu_type='1') 레벨 2만 부모 메뉴로 선택 가능
📝 다음 단계:
- 카테고리 컴포넌트도 메뉴 스코프로 전환 예정
- 메뉴 클릭 시 localStorage에 메뉴 이름 저장 (useMenu, AppLayout)
- 엑셀 다운로드 시 localStorage의 메뉴 이름을 파일명으로 사용
- 백엔드 카테고리 컬럼 조회 쿼리 파라미터 버그 수정
- API 호출 시 불필요한 autoFilter 파라미터 제거
파일명 형식: {메뉴이름}_{날짜}.xlsx
예시: 품목등록테스트_2025-11-11.xlsx
- 회원가입 페이지 및 폼 컴포넌트 추가
- 로그인 페이지와 일관된 디자인
- 아이디, 비밀번호, 이름, 차량번호, 휴대폰번호 입력 필드
- 비밀번호 확인 필드 추가
- 유효성 검사 기능 구현
- 차량번호: 한국 차량번호 형식 검증 (12가3456, 123가4567, 서울12가3456 등)
- 휴대폰번호: 하이픈 포함 형식 검증 (010-1234-5678)
- 비밀번호: 최소 6자 이상, 확인 일치 검증
- 사용자ID: 최소 4자 이상
- 이름: 최소 2자 이상
- UI/UX 개선
- 각 필드별 실시간 유효성 검사 및 에러 메시지 표시
- 비밀번호 표시/숨김 토글 버튼
- 자동 설정된 필드에 안내 문구 표시
- 로그인 페이지로 돌아가기 버튼 추가
- 로그인 페이지에 회원가입 링크 추가
- 타입 및 훅 추가
- RegisterFormData, RegisterResponse 타입 정의
- useRegister 훅으로 비즈니스 로직 분리
- auth API mock 함수 (백엔드 연동 준비)
- 사용자 경험 고려
- 입력 필드별 placeholder 예시 제공
- 도움말 텍스트로 입력 형식 안내
- 로딩 상태 표시
- 문제: 테이블 리스트에서 writer 컬럼이 user_id로 표시됨
- 해결:
1. 백엔드: entityJoinService에서 writer 컬럼 자동 감지
2. writer 컬럼 발견 시 user_info 테이블과 자동 조인
3. writer_name 별칭으로 user_name 반환
4. 프론트엔드: writer 컬럼일 때 writer_name 우선 표시
- 영향:
- writer 컬럼이 있는 모든 테이블에서 자동으로 작성자명 표시
- 기존 entity 조인 설정과 충돌 없이 작동
- column_labels 설정 불필요
- 문제: 속성 패널에서 너비 입력 시 size.width는 변경되지만 화면에 반영되지 않음
- 원인: RealtimePreviewDynamic의 baseStyle에서 componentStyle을 getWidth() 이후에 스프레드하여 size.width를 덮어씀
- 해결:
1. componentStyle에서 width, height 제거
2. 나머지 스타일만 먼저 적용
3. getWidth(), getHeight()로 size 기반 크기를 마지막에 설정
- 영향:
- 속성 패널에서 입력한 너비/높이가 화면에 즉시 반영됨
- component.style의 width/height는 무시되고 size.width/height만 사용됨
- 디버깅 로그 제거
- 문제: 속성 패널에서 너비를 입력해도 화면에 반영되지 않음
- 원인: updateComponentProperty에서 gridColumns 변경 시 자동으로 너비를 재계산
- 해결:
1. gridColumns 변경 시 updateSizeFromGridColumns 호출 제거
2. gridColumns 변경 시 calculateWidthFromColumns 호출 제거
- 영향:
- 속성 패널에서 입력한 너비가 화면에 즉시 반영됨
- gridColumns는 더 이상 너비를 자동으로 조정하지 않음
- 문제: 너비 입력 시 onChange에서 즉시 업데이트되어 30에서 3을 지우기 어려움
- 해결:
1. localWidth 상태 추가
2. onChange: 로컬 상태만 업데이트 (완전 자유 입력)
3. onBlur/Enter: 실제 업데이트 + 10px 단위 스냅
4. useEffect로 컴포넌트 변경 시 localWidth 동기화
- 영향:
- 30 입력 시 3, 0 모두 자유롭게 지우고 입력 가능
- 포커스 아웃 시에만 10px 단위로 정렬
- 문제: 너비/높이 입력 시 즉시 10px 단위로 스냅되어 자유 입력 불가
- 해결:
1. 너비: onChange에서는 입력값 그대로 반영, onBlur에서 10px 단위로 스냅
2. 높이: 로컬 상태로 자유 입력 허용, onBlur/Enter 시 10px 단위로 스냅
3. step을 10에서 1로 변경하여 자유 입력 가능
- 영향:
- 입력 중에는 원하는 값 입력 가능
- 입력 완료 시(포커스 아웃 또는 Enter) 자동으로 10px 단위로 정렬
- 문제: 속성 패널에서 너비/높이 입력 시 격자 시스템이 자동으로 값을 변경
- 원인: updateComponentProperty에서 size.width/height 변경 시 무조건 격자 스냅 적용
- 해결: 직접 입력 시에는 격자 스냅을 적용하지 않도록 로직 주석 처리
- 영향:
- 속성 패널에서 원하는 크기로 자유롭게 설정 가능
- 드래그/리사이즈 시에는 별도 로직에서 격자 스냅 처리
- 디버깅 로그 제거
- 문제: adjustGridColumnsFromSize 등 gridUtils 함수들이 import되지 않아 런타임 오류 발생
- 해결:
1. gridUtils에서 필요한 함수들 import 추가
2. 3개 파라미터를 받는 snap 함수 호출을 올바른 함수로 변경
- snapSizeTo10px -> snapSizeToGrid
- snapPositionTo10px -> snapToGrid
- 영향: 컴포넌트 크기/위치 조정 시 격자 스냅 기능 정상 작동
- 문제: 버튼 컴포넌트 클릭 시 버튼 동작이 실행되어 선택되지 않음
- 해결:
1. ButtonPrimaryComponent에서 디자인 모드일 때 <button> 대신 <div>로 렌더링
2. ScreenDesigner의 ScreenPreviewProvider에서 isPreviewMode를 false로 설정
3. 디자인 모드에서는 버튼 액션이 실행되지 않고 onClick만 전달되도록 수정
- 영향: button-primary 타입 버튼이 화면 편집기에서 정상적으로 선택 가능
- 드래그 드롭으로 배치되는 인풋 필드 기본 높이 30px로 변경
- 날짜 입력 컴포넌트의 모든 외부 div에 h-full 추가
- 모든 input 요소에 min-h-full 추가하여 부모 높이를 제대로 따르도록 수정
- daterange, year 타입도 동일하게 적용
주요 변경사항:
- Dialog/DialogContent를 ResizableDialog/ResizableDialogContent로 변경
- DialogTitle을 ResizableDialogTitle로 변경
- 내부 컨텐츠 컨테이너를 유연한 크기(w-full h-full)로 변경
- minWidth/minHeight 사용으로 최소 크기 보장
참고:
- 컴포넌트 레이아웃이 화면관리에서 설정된 대로 정확히 렌더링됨
- 레이아웃 자체의 문제는 화면관리에서 재설계 필요
파일 변경:
- frontend/components/screen/SaveModal.tsx
주요 변경사항:
- 드래그앤드롭 컬럼의 라벨 숨김 및 placeholder로 라벨명 표시
- 기본 높이 30px로 변경
- 5개 시스템 컬럼(id, created_date, updated_date, writer, company_code) 숨김
- AI-개발자 협업 작업 수칙 문서 작성 및 .cursorrules에 통합
파일 변경:
- frontend/components/screen/ScreenDesigner.tsx
* getDefaultHeight(): 기본 높이를 30px로 변경
* handleDrop(): labelDisplay false, placeholder 추가
- frontend/components/screen/panels/TablesPanel.tsx
* hiddenColumns Set으로 시스템 컬럼 필터링
- .cursor/rules/ai-developer-collaboration-rules.mdc (신규)
* 확인 우선, 한 번에 하나, 철저한 마무리 원칙
* 데이터베이스 검증, 코드 수정, 테스트, 커뮤니케이션 규칙
- .cursorrules
* 필수 확인 규칙 섹션 추가
* 모든 작업 시작/완료 시 협업 규칙 확인 강제화
- 채번 규칙 scope_type을 table로 단순화
- 화면의 테이블명을 자동으로 감지하여 채번 규칙 필터링
- TextInputConfigPanel에 screenTableName prop 추가
- getAvailableNumberingRulesForScreen API로 테이블 기반 조회
- NumberingRuleDesigner에서 자동으로 테이블명 설정
- webTypeConfigConverter 유틸리티 추가 (기존 화면 호환성)
- AutoGenerationConfig 타입 개선 (enabled, options.numberingRuleId)
- 채번 규칙 선택 UI에서 ID 제거, 설명 추가
- 불필요한 console.log 제거
Backend:
- numberingRuleService: 테이블 기반 필터링 로직 구현
- numberingRuleController: available-for-screen 엔드포인트 수정
Frontend:
- TextInputConfigPanel: 테이블명 기반 채번 규칙 로드
- NumberingRuleDesigner: 적용 범위 UI 제거, 테이블명 자동 설정
- ScreenDesigner: webTypeConfig → autoGeneration 변환 로직 통합
- DetailSettingsPanel: autoGeneration 속성 매핑 개선
- 카테고리 타입 컬럼이 테이블 리스트/플로우 위젯에서 코드값 대신 라벨로 표시되도록 수정
- InteractiveDataTable: categoryMappings 상태 추가 및 formatCellValue에서 카테고리 라벨 변환
- FlowWidget: categoryMappings 상태 추가 및 formatValue에서 카테고리 라벨 변환
- TableListComponent: categoryMappings 상태 추가 및 formatCellValue에서 카테고리 라벨 변환
- FlowWidget 런타임 에러 수정
- formatValue 함수를 categoryMappings 상태 선언 이후로 이동
- useCallback 의존성 배열 오류 해결
- Dialog 컴포넌트 빌드 오류 수정
- CopyScreenModal: DialogFooter → ResizableDialogFooter 태그 일치
- MenuAssignmentModal: 모든 Dialog 컴포넌트를 ResizableDialog 버전으로 변경
- Dialog → ResizableDialog
- DialogContent → ResizableDialogContent
- DialogFooter → ResizableDialogFooter
- DialogHeader → ResizableDialogHeader
- DialogTitle → ResizableDialogTitle
- DialogDescription → ResizableDialogDescription
- 불필요한 console.log 제거
- InteractiveDataTable, FlowWidget, TableListComponent에서 디버깅 로그 정리
- 문제: 높이 입력 시 10 단위로만 입력 가능 (예: 1080 입력 불가)
- 원인: 격자 스냅 로직이 onChange마다 높이를 10/20 단위로 강제 반올림
- 해결:
1. 모든 number input 필드에 step="1" 추가
2. ScreenDesigner.tsx의 격자 스냅 로직 수정 (높이 스냅 제거)
3. UnifiedPropertiesPanel.tsx에 로컬 상태 추가하여 입력 중 스냅 방지
4. onBlur/Enter 시에만 실제 값 업데이트
수정 파일:
- frontend/components/screen/ScreenDesigner.tsx
- frontend/components/screen/panels/UnifiedPropertiesPanel.tsx
- frontend/components/screen/panels/PropertiesPanel.tsx
- frontend/components/screen/panels/ResolutionPanel.tsx
- frontend/components/screen/panels/RowSettingsPanel.tsx
- frontend/components/screen/panels/webtype-configs/NumberTypeConfigPanel.tsx
- frontend/components/screen/panels/webtype-configs/TextTypeConfigPanel.tsx
; Please enter a commit message to explain why this merge is necessary,
; especially if it merges an updated upstream into a topic branch.
;
; Lines starting with ';' will be ignored, and an empty message aborts
; the commit.
주요 변경사항:
- 격자 설정을 편집 탭에서 항상 표시 (해상도 설정 하단)
- 그리드 컬럼 수 동적 조정 가능 (1-24)
- 컴포넌트 생성 시 현재 그리드 컬럼 수 기반 자동 계산
- 컴포넌트 너비가 설정한 컬럼 수대로 정확히 표시되도록 수정
수정된 파일:
- ScreenDesigner: 컴포넌트 드롭 시 gridColumns와 style.width 동적 계산
- UnifiedPropertiesPanel: 격자 설정 UI 통합, 차지 컬럼 수 설정 시 width 자동 계산
- RealtimePreviewDynamic: getWidth 우선순위 수정, DOM 크기 디버깅 로그 추가
- 8개 컴포넌트: componentStyle.width를 항상 100%로 고정
* ButtonPrimaryComponent
* TextInputComponent
* NumberInputComponent
* TextareaBasicComponent
* DateInputComponent
* TableListComponent
* CardDisplayComponent
문제 해결:
- 컴포넌트 내부에서 component.style.width를 재사용하여 이중 축소 발생
- 해결: 부모 컨테이너(RealtimePreviewDynamic)가 width 제어, 컴포넌트는 항상 100%
- 결과: 파란 테두리와 내부 콘텐츠가 동일한 크기로 정확히 표시
변경사항:
- 검색 필터 입력 필드를 필터 설정/그룹 설정 버튼과 동일한 Y좌표에 배치
- 한 줄 레이아웃: [검색입력들...] [초기화] ... [필터설정] [그룹설정]
- ml-auto로 설정 버튼들 오른쪽 정렬
- 검색 필드는 왼쪽부터, 설정 버튼은 오른쪽에 배치
- 중복된 검색 필터 입력 영역 제거
UI 개선:
- 모든 컨트롤이 하나의 수평선상에 위치
- 공간 효율성 극대화
- 사용자가 요청한 레이아웃 정확히 구현
변경사항:
- 검색 필터 입력 필드를 버튼과 같은 Y좌표에 배치
- Label 제거 (placeholder로 충분)
- flex-wrap으로 여러 필터 자동 줄바꿈
- 고정 너비(w-40)로 일관된 입력 필드 크기
- 초기화 버튼 ml-auto로 오른쪽 정렬
- grid 레이아웃 제거하고 flex로 변경
UI 개선:
- TableListComponent와 동일한 스타일 적용
- 공간 절약 및 깔끔한 인터페이스
- 필터 설정, 그룹 설정, 검색 입력이 모두 같은 영역에 위치
- Fragment(<>)로 그룹 표시 배지와 검색 필터 영역 감싸기
- stepDataColumns.length > 0 조건 내부로 모든 관련 UI 통합
- 닫는 태그 구조 수정
빌드 오류 해결:
- Expected '</>', got '{' 에러 해결
- JSX 중첩 구조 정상화
변경사항:
- 스텝 이름 복원 (탭 영역에 표시되므로 필요)
- 데이터 테이블 위 헤더 영역 제거
- 스텝 이름 중복 표시 제거
- '총 N건의 데이터' 표시 제거
- 필터링/선택 건수 표시 제거
- 필터 설정 및 그룹 설정 버튼은 유지
- justify-end로 버튼 오른쪽 정렬
UI 개선:
- 데이터 영역 확대로 더 많은 정보 표시
- 중복 정보 제거로 깔끔한 인터페이스
- 필요한 설정 버튼만 간결하게 배치
- 스텝 이름(stepName) 표시 영역 완전 제거
- 데이터 건수만 표시하도록 간소화
- 하단 선택 바와 건수만으로 스텝 구분
- 패딩 조정 (pb-5 -> pb-3, pb-6 -> pb-4)
UI 개선:
- 스텝 영역 높이 감소로 공간 절약
- 더 많은 데이터 표시 공간 확보
- 시각적으로 더 간결한 인터페이스
- TableListComponent: showHeader 조건부 렌더링 제거
- 타이틀 표시 영역 삭제
- 공간 절약을 위해 헤더 완전 제거
- FlowWidget: 플로우 제목 및 설명 영역 제거
- flowData.name 표시 영역 삭제
- flowData.description 표시 영역 삭제
- 더 많은 데이터 표시 공간 확보
UI 개선:
- 불필요한 헤더 제거로 컨텐츠 영역 확대
- 더 많은 데이터를 한 화면에 표시 가능
- TableListComponent와 동일한 그룹핑 기능 적용
- 다중 컬럼 선택으로 계층적 그룹화 지원
- 그룹 설정 다이얼로그 추가
- 그룹별 데이터 펼치기/접기 기능
- 그룹 헤더에 항목 개수 표시
- localStorage에 그룹 설정 저장/복원
- 그룹 해제 버튼 추가
- 그룹 표시 배지 UI
주요 기능:
- 플로우 스텝 데이터에 그룹화 적용
- filteredData와 stepData 모두 지원
- 그룹 없을 때는 기존 페이지네이션 유지
- 그룹 있을 때는 모든 그룹 데이터 표시
✨ 새로운 기능
- 플로우 위젯과 동일한 검색 필터 설정 기능 구현
- 사용자가 원하는 컬럼만 선택하여 검색 가능
- localStorage 기반 필터 설정 저장/복원
🎨 UI 추가
- '검색 필터 설정' 버튼 (FlowWidget 스타일)
- 선택된 컬럼의 동적 검색 입력 필드
- 필터 개수 뱃지 표시
- 체크박스 기반 필터 설정 다이얼로그
🔧 기술적 구현
- searchFilterColumns 상태로 선택된 컬럼 관리
- searchValues 상태로 각 컬럼별 검색값 관리
- useAuth 훅으로 사용자별 필터 설정 저장
- Grid 레이아웃으로 검색 필드 반응형 배치
📝 변경된 파일
- frontend/components/screen/templates/DataTableTemplate.tsx
✅ 테스트 완료
- 필터 설정 저장/복원
- 동적 검색 필드 생성
- 반응형 레이아웃
- 미리보기 모드에서 비활성화
- 테이블 헤더와 데이터 셀 모두에 whitespace-nowrap 적용
- 모바일에서도 텍스트가 2줄로 깨지지 않음
- overflow-hidden + text-ellipsis로 긴 텍스트 처리
- TableListComponent와 InteractiveDataTable 모두 적용
이제 화면을 줄여도 텍스트가 항상 1줄로 유지됨
- 모든 테이블 헤더를 가운데 정렬 (text-center)
- 숫자 타입(number, decimal) 데이터를 우측 정렬
- TableListComponent: inputType 기반 숫자 판단
- InteractiveDataTable: widgetType 기반 숫자 판단
- 체크박스는 기존대로 가운데 정렬 유지
- 일반 텍스트는 좌측 정렬 유지
더 읽기 쉬운 테이블 레이아웃 완성