## 주요 변경사항
### 1. 화면 복사 기능 강화
- 최고 관리자가 다른 회사로 화면 복사 가능하도록 개선
- 메인 화면과 연결된 모달 화면 자동 감지 및 일괄 복사
- 복사 시 버튼의 targetScreenId 자동 업데이트
- 일괄 이름 변경 기능 추가 (복사본 텍스트 제거)
- 중복 화면명 체크 기능 추가
#### 백엔드 (screenManagementService.ts)
- generateMultipleScreenCodes: 여러 화면 코드 일괄 생성 (Advisory Lock 사용)
- detectLinkedModalScreens: edit 액션도 모달로 감지하도록 개선
- checkDuplicateScreenName: 중복 화면명 체크 API 추가
- copyScreenWithModals: 메인+모달 일괄 복사 및 버튼 업데이트
- updateButtonTargetScreenIds: 복사된 모달로 버튼 targetScreenId 업데이트
- updated_date 컬럼 제거 (screen_layouts 테이블에 존재하지 않음)
#### 프론트엔드 (CopyScreenModal.tsx)
- 회사 선택 UI 추가 (최고 관리자 전용)
- 연결된 모달 화면 자동 감지 및 표시
- 일괄 이름 변경 기능 (텍스트 제거/추가)
- 실시간 미리보기
- 중복 화면명 체크
### 2. 버튼 설정 모달 화면 선택 개선
- 편집 중인 화면의 company_code 기준으로 화면 목록 조회
- 최고 관리자가 다른 회사 화면 편집 시 해당 회사의 모달 화면만 표시
- targetScreenId 문자열/숫자 타입 불일치 수정
#### 백엔드 (screenManagementController.ts)
- getScreens API에 companyCode 쿼리 파라미터 추가
- 최고 관리자는 다른 회사의 화면 목록 조회 가능
#### 프론트엔드
- ButtonConfigPanel: currentScreenCompanyCode props 추가
- DetailSettingsPanel: currentScreenCompanyCode 전달
- UnifiedPropertiesPanel: currentScreenCompanyCode 전달
- ScreenDesigner: selectedScreen.companyCode 전달
- targetScreenId 비교 시 parseInt 처리 (문자열→숫자)
### 3. 카테고리 메뉴별 컬럼 분리 기능
- 메뉴별로 카테고리 컬럼을 독립적으로 관리
- 카테고리 컬럼 추가/삭제 시 메뉴 스코프 적용
## 수정된 파일
- backend-node/src/services/screenManagementService.ts
- backend-node/src/controllers/screenManagementController.ts
- backend-node/src/routes/screenManagementRoutes.ts
- frontend/components/screen/CopyScreenModal.tsx
- frontend/components/screen/config-panels/ButtonConfigPanel.tsx
- frontend/components/screen/panels/DetailSettingsPanel.tsx
- frontend/components/screen/panels/UnifiedPropertiesPanel.tsx
- frontend/components/screen/ScreenDesigner.tsx
- frontend/lib/api/screen.ts
문제:
- 분할 패널에서 필터 입력 시 검색이 제대로 작동하지 않음
- 백엔드가 {value: '전자', operator: 'contains'} 형태를 처리하지 못함
원인:
- buildAdvancedSearchCondition이 필터 객체의 value 속성을 추출하지 않음
- 객체를 직접 문자열로 변환하여 '[object Object]'로 검색됨
해결:
1. tableManagementService.buildAdvancedSearchCondition 수정:
- {value, operator} 형태의 필터 객체 감지
- actualValue 추출 및 operator 처리
- 모든 웹타입 케이스에 actualValue 전달
2. 프론트엔드 디버깅 로그 제거:
- SplitPanelLayoutComponent의 console.log 제거
- 필터, 컬럼 가시성, API 호출 로그 정리
테스트 필요:
- 분할 패널에서 필터 입력 → 정상 검색 확인
- 텍스트, 날짜, 숫자, 코드 타입 필터 동작 확인
문제:
1. ColumnVisibilityPanel에서 순서 변경 후 onColumnOrderChange가 호출되지 않음
2. 필터 입력 시 데이터가 제대로 필터링되지 않음
3. useAuth 훅 import 경로 오류 (@/hooks/use-auth → @/hooks/useAuth)
해결:
1. ColumnVisibilityPanel.handleApply()에 onColumnOrderChange 호출 추가
2. 필터 변경 감지 및 데이터 로드 로직 디버깅 로그 추가
3. useAuth import 경로 수정
테스트:
- 거래처관리 화면에서 컬럼 순서 변경 → 실시간 반영 ✅
- 페이지 새로고침 → 순서 유지 (localStorage) ✅
- 필터 입력 → 필터 변경 감지 (추가 디버깅 필요)
문제:
- 분할 패널에서 검색 컴포넌트의 필터/그룹/컬럼 설정이 동작하지 않음
- 테이블 리스트 컴포넌트에 있던 로직이 분할 패널에는 없었음
해결:
1. 필터 처리:
- leftFilters를 searchValues 형식으로 변환
- API 호출 시 필터 조건 전달
- 필터 변경 시 데이터 자동 재로드
2. 컬럼 가시성:
- visibleLeftColumns useMemo 추가
- leftColumnVisibility를 적용하여 표시할 컬럼 필터링
- 렌더링 시 가시성 처리된 컬럼만 표시
3. 그룹화:
- groupedLeftData useMemo 추가
- leftGrouping 배열로 데이터를 그룹화
- 그룹별 헤더와 카운트 표시
4. 테이블 등록:
- columns 속성을 올바르게 참조 (displayColumns → columns)
- 객체/문자열 타입 모두 처리
- 화면 설정에 맞게 테이블 등록
테스트:
- 거래처 관리 화면에서 검색 컴포넌트 버튼 활성화
- 필터 설정 → 데이터 필터링 동작
- 그룹 설정 → 데이터 그룹화 동작
- 테이블 옵션 → 컬럼 가시성/순서 변경 동작
문제:
- displayColumns가 비어있을 때 전체 컬럼을 보여주는 오류
- 화면에 설정된 컬럼만 표시되어야 함
해결:
- displayColumns가 비어있으면 테이블을 등록하지 않음
- displayColumns에 설정된 컬럼만 검색 컴포넌트에 등록
- 화면 관리에서 설정한 컬럼 구성을 정확히 반영
테스트:
- 거래처 관리 화면에서 좌측 테이블의 displayColumns(14개) 정상 표시
- 테이블 옵션/필터 설정/그룹 설정 버튼 정상 작동
- 우측 테이블은 검색 컴포넌트에서 제외
변경 사유:
- 분할 패널은 마스터-디테일 구조로 좌측(마스터)만 독립적으로 검색 가능
- 우측(디테일)은 좌측 선택 항목에 종속되므로 별도 검색 불필요
변경 내용:
- 우측 테이블 registerTable 호출 제거 (주석 처리)
- TableSearchWidget에서 좌측 테이블만 선택 가능
- 우측 테이블 관련 상태(rightFilters, rightGrouping 등)는 내부 로직용으로 유지
효과:
- 분할 패널 사용 시 좌측 마스터 테이블만 검색 설정 가능
- 우측 디테일 테이블은 좌측 선택에 따라 자동 필터링
- 검색 컴포넌트 UI가 더 직관적으로 개선
문제:
- 분할 패널의 테이블 옵션/검색필터 설정/그룹 설정에서 모든 컬럼이 표시됨
- 우측 패널에서 rightTableColumns (전체 컬럼) 사용하여 등록
해결:
- componentConfig.rightPanel?.columns (화면 표시 컬럼)만 등록하도록 수정
- 좌측 패널과 동일한 방식으로 displayColumns 사용
- 의존성 배열도 rightTableColumns → rightPanel.columns로 수정
변경 사항:
- rightTableColumns 대신 displayColumns 사용
- 컬럼 매핑 로직 개선 (col.columnName || col.name || col)
- 화면에 실제 표시되는 컬럼만 설정 UI에 노출
- 테이블 상단 헤더 UI 전체 제거 (AdvancedSearchFilters 영역)
- 테이블 옵션, 필터 설정, 그룹 설정 버튼 제거
- 전체 개수 표시 제거
- 검색 필터 로직은 모두 유지 (상태, 함수, localStorage)
- 해당 기능은 TableSearchWidget 컴포넌트에서 제공 예정
변경 사유:
- 검색 필터 기능을 독립적인 TableSearchWidget으로 분리
- 테이블 컴포넌트와 검색 필터 UI의 관심사 분리
- 재사용 가능한 검색 필터 컴포넌트 구조로 개선
- TableListComponent: grouping 상태 변경 시 groupByColumns 자동 업데이트
- 그룹화 시 카테고리/엔티티/코드 타입 컬럼은 _name 필드 사용
- 그룹 키 생성 시 실제 이름 표시 (코드 대신)
예시:
- 이전: 상태:CATEGORY_159712 > 품번:SLI-2025-0001
- 이후: 상태:완제품 > 품번:SLI-2025-0001
- TableSearchWidgetHeightContext 추가: 위젯 높이 변화 관리
- TableSearchWidget: ResizeObserver로 높이 변화 감지 및 localStorage 저장
- 실제 화면(/screens/[screenId]/page.tsx)에서만 동작 (디자이너 제외)
- TableSearchWidget 아래 컴포넌트들의 Y 위치를 높이 차이만큼 자동 조정
- 화면 로딩 시 저장된 높이 복원 및 컴포넌트 위치 재조정
주요 변경사항:
1. 필터가 여러 줄로 wrap될 때 높이 자동 증가
2. 높이가 늘어난 만큼 아래 컴포넌트들이 자동으로 아래로 이동
3. 새로고침 후에도 설정 유지 (localStorage)
4. 화면 디자이너에서는 기존대로 동작 (영향 없음)
기술 구현:
- Context API로 위젯 높이 전역 관리
- ResizeObserver로 실시간 높이 감지
- localStorage로 사용자별 높이 설정 영구 저장
- 컴포넌트 렌더링 시 동적 Y 위치 계산
- 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 높이 변화 시 아래 컴포넌트 자동 재배치 기능 구현 예정
- 모든 필터 입력창 높이 통일 (h-9, 36px)
- 실시간 검색: 입력 시 즉시 필터 적용 (검색 버튼 제거)
- 초기화 버튼 추가: 모든 필터값을 한번에 리셋
- filters → searchValues 자동 변환 로직 추가
- select 필터: 선택된 값의 라벨 저장하여 데이터 없을 때도 표시 유지
- select 옵션 초기 로드 후 계속 유지 (dataCount 변경 시에도 유지)
주요 개선사항:
1. Input, Select, Date 등 모든 필터의 높이가 동일하게 표시
2. 사용자가 값을 입력하면 바로 테이블이 필터링됨
3. 초기화 버튼으로 간편하게 모든 필터 제거 가능
4. 필터링 결과가 0건이어도 select 박스의 선택값이 유지됨
알려진 제한사항:
- 카테고리/엔티티 필터는 현재 테이블 데이터 기반으로만 옵션 표시
(전체 정의된 카테고리 값이 아닌, 실제 데이터에 있는 값만 표시)
- TableRegistration에 getColumnUniqueValues 콜백 함수 추가
- TableListComponent에서 현재 데이터의 고유 값 추출 함수 구현
- TableSearchWidget에서 select 타입 필터의 옵션을 자동으로 로드
- 테이블 데이터가 변경되면 필터 옵션도 자동 업데이트
- 데이터 건수 표시 기능도 함께 수정 (등록 순서 문제 해결)
- TableOptionsContext 기반 테이블 자동 감지 시스템 구현
- 독립 위젯으로 드래그앤드롭 배치 가능
- 3가지 기능: 컬럼 가시성, 필터 설정, 그룹 설정
- FlowWidget, TableList, SplitPanel 등 모든 테이블 컴포넌트 지원
- 유틸리티 카테고리에 등록 (1920×80px)
- 위젯 크기 제어 가이드 룰 파일에 추가
**문제:**
- 화면 편집기에서 버튼의 스타일(색상, 폰트 등)을 변경해도 실시간으로 반영되지 않음
- 저장 후 실제 화면에서는 정상적으로 보임
**원인:**
- ButtonPrimaryComponent에서 isInteractive 모드일 때만 component.style을 적용
- 디자인 모드(isDesignMode)에서는 사용자 정의 스타일이 무시됨
**해결:**
- buttonElementStyle에 component.style을 항상 적용하도록 수정
- width/height는 레이아웃 충돌 방지를 위해 제외 유지
- 디자인 모드와 인터랙티브 모드 모두에서 스타일 실시간 반영
**영향:**
- 화면 편집기에서 버튼 스타일 변경 시 즉시 미리보기 가능
- 저장하지 않아도 시각적 피드백 제공
**주요 변경사항:**
1. **메뉴 스코프 변경 (getSiblingMenuObjids)**
- 기존: 형제 메뉴 + 모든 형제의 자식 메뉴 포함
- 변경: 자신 + 자신의 자식 메뉴만 포함
- 결과: 각 2레벨 메뉴가 완전히 독립적으로 격리됨
2. **채번 규칙 메뉴 선택 상태 유지**
- useState 초기값 함수에서 저장된 selectedMenuObjid 복원
- 속성창 닫았다 열어도 선택한 메뉴와 채번 규칙 유지
- config.autoGeneration.selectedMenuObjid에 저장
3. **로그 정리**
- 프론트엔드: 디버깅 로그 제거
- 백엔드: info 레벨 로그를 debug 레벨로 변경
- 운영 환경에서 불필요한 로그 출력 최소화
**영향:**
- 영업관리 메뉴: 영업관리의 채번 규칙/코드만 조회
- 기준정보 메뉴: 기준정보의 채번 규칙/코드만 조회
- 각 메뉴 그룹이 독립적으로 데이터 관리 가능
- 백엔드: 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 전달
이제 코드 위젯도 카테고리처럼 형제 메뉴별로 격리됩니다.
✅ 주요 변경사항:
- 백엔드: 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
- 데이터 행에 font-normal 적용하여 bold 제거
- 헤더는 font-bold 유지
- 데이터 행 상하 여백 축소 (py-2 → py-1.5)
- 행 고정 높이 제거하여 컨텐츠에 따라 자동 조정
변경된 파일:
- frontend/lib/registry/components/table-list/TableListComponent.tsx
- inputType이 date/datetime인 컬럼 yyyy-mm-dd 형식으로 표시
- format이 'date'인 경우도 동일한 형식 적용
- 생성일, 수정일 등 날짜 컬럼 가독성 개선
변경된 파일:
- frontend/lib/registry/components/table-list/TableListComponent.tsx
- 화면 편집기 컬럼 설정 기반 다운로드 (visible 컬럼만)
- 필터 조건 적용 (필터링된 데이터만 다운로드)
- 한글 라벨명 표시 (column_labels 테이블 조회)
- Entity 조인 값 표시 (writer → writer_name 등)
- 카테고리 타입 라벨 변환 (코드 → 라벨)
- 멀티테넌시 보안 강화 (autoFilter: true)
- 디버깅 로그 정리
변경된 파일:
- frontend/lib/utils/buttonActions.ts
- frontend/lib/registry/components/table-list/TableListComponent.tsx
관련 이슈: #엑셀다운로드개선
- writer 컬럼이 있는 테이블에서 자동으로 user_name 표시
- 백엔드: entityJoinService에서 writer 컬럼 감지 및 user_info 조인
- 프론트엔드: entityJoinApi 항상 사용 및 writer_name 자동 표시
- 디버깅 로그 제거
- 문제: writer 컬럼이 user_name으로 변환되지 않음
- 원인: entityJoinColumns가 없을 때 tableTypeApi 사용 (entity 조인 미지원)
- 해결: 항상 entityJoinApi.getTableDataWithJoins 사용
- 영향:
- writer 컬럼이 있는 모든 테이블에서 자동으로 writer_name 조인
- 기존 additionalJoinColumns도 정상 작동
- 백엔드의 자동 writer 조인 기능 활성화
- 문제: 테이블 리스트에서 writer 컬럼이 user_id로 표시됨
- 해결:
1. 백엔드: entityJoinService에서 writer 컬럼 자동 감지
2. writer 컬럼 발견 시 user_info 테이블과 자동 조인
3. writer_name 별칭으로 user_name 반환
4. 프론트엔드: writer 컬럼일 때 writer_name 우선 표시
- 영향:
- writer 컬럼이 있는 모든 테이블에서 자동으로 작성자명 표시
- 기존 entity 조인 설정과 충돌 없이 작동
- column_labels 설정 불필요
- 문제: 속성 패널에서 너비/높이 입력 시 격자 시스템이 자동으로 값을 변경
- 원인: updateComponentProperty에서 size.width/height 변경 시 무조건 격자 스냅 적용
- 해결: 직접 입력 시에는 격자 스냅을 적용하지 않도록 로직 주석 처리
- 영향:
- 속성 패널에서 원하는 크기로 자유롭게 설정 가능
- 드래그/리사이즈 시에는 별도 로직에서 격자 스냅 처리
- 디버깅 로그 제거
- 문제: 버튼 컴포넌트 클릭 시 버튼 동작이 실행되어 선택되지 않음
- 해결:
1. ButtonPrimaryComponent에서 디자인 모드일 때 <button> 대신 <div>로 렌더링
2. ScreenDesigner의 ScreenPreviewProvider에서 isPreviewMode를 false로 설정
3. 디자인 모드에서는 버튼 액션이 실행되지 않고 onClick만 전달되도록 수정
- 영향: button-primary 타입 버튼이 화면 편집기에서 정상적으로 선택 가능
- 드래그 드롭으로 배치되는 인풋 필드 기본 높이 30px로 변경
- 날짜 입력 컴포넌트의 모든 외부 div에 h-full 추가
- 모든 input 요소에 min-h-full 추가하여 부모 높이를 제대로 따르도록 수정
- daterange, year 타입도 동일하게 적용
- 데이터 조회 API에 회사별 자동 필터링 기능 추가
- GET /api/data/:tableName에 company_code 필터 자동 적용
- GET /api/data/join에 우측 테이블 회사별 필터링 추가
- 최고 관리자(company_code = '*')는 전체 데이터 조회 가능
- 분할 패널 레이아웃 우측 추가 시 조인 컬럼 자동 입력
- 좌측에서 선택한 항목의 조인 키 값을 우측 추가 모달에 자동 설정
- 자동 설정된 필드는 읽기 전용으로 표시 (disabled + 안내 문구)
- 사용자는 나머지 필드만 입력하면 됨
- 데이터 서비스 개선
- getJoinedData 함수에 companyCode 파라미터 추가
- checkColumnExists 함수를 public으로 변경하여 재사용성 향상
- 조인 쿼리에 DISTINCT 추가로 중복 데이터 방지
- 복합키 테이블의 레코드 삭제 지원
- 레코드 생성 시 멀티테넌시 자동 처리
- company_code와 company_name 자동 추가
- 테이블 컬럼 존재 여부 체크 후 자동 설정
- 분할 패널 설정 UI 개선
- 좌측 패널 표시 컬럼 선택 UI 추가
- 추가 폼에 표시할 컬럼 선택 기능 추가
- Primary Key 정보 자동 조회 및 표시
주요 변경사항:
- 드래그앤드롭 컬럼의 라벨 숨김 및 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 속성 매핑 개선
문제:
- 고정 높이 (h-[400px] sm:h-[500px])로 인해 데이터가 적어도 큰 공간 차지
- 하단에 빈 공간이 남는데도 스크롤이 생기는 비효율적인 UX
- overflow-y-scroll이 항상 스크롤바를 표시함
해결:
- 고정 높이 제거 → flex-1 (부모의 남은 공간 차지)
- overflow-y-scroll → overflow-y-auto (필요할 때만 스크롤)
- 데이터 양에 따라 자동으로 높이 조정
개선 사항:
✅ 데이터가 적을 때: 불필요한 공간 없이 컴팩트하게 표시
✅ 데이터가 많을 때: 자동으로 스크롤 생성
✅ 반응형 레이아웃에 자연스럽게 적응
✅ 스크롤바가 필요할 때만 표시되어 깔끔한 UI
문제:
- 그룹 헤더의 bg-muted/50 (반투명 배경)으로 인해 스크롤 시 뒤 내용이 비쳐 보임
- sticky 위치에서 가독성 저하
해결:
- bg-muted/50 → bg-muted (불투명 배경)
- hover 효과도 hover:bg-muted → hover:bg-muted/80으로 조정
- 스크롤 시 깔끔한 가림 효과 제공
개선 사항:
- sticky 그룹 헤더의 완전한 배경 덮기
- 스크롤 시 가독성 향상
- shadcn 가이드라인 준수 (단색 배경)
- 그라데이션 배경 제거하고 단색 배경 적용
- 동적 색상 기반 그림자 제거하고 표준 shadcn 그림자 적용
- hover:opacity-90 효과 추가 (부드러운 어두워짐)
- active:scale-95 효과 추가 (클릭 피드백)
- transition-colors duration-150으로 빠른 색상 전환 적용
- disabled 상태를 단색 회색으로 개선
shadcn/ui 가이드라인 준수:
- 심플하고 깔끔한 단색 디자인
- 일관된 인터랙션 패턴
- 표준화된 그림자 및 전환 효과
- 문제: 높이 입력 시 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%
- 결과: 파란 테두리와 내부 콘텐츠가 동일한 크기로 정확히 표시
문제:
- optimizedConvertCode(value, meta.codeCategory) ❌
- 함수 정의: optimizedConvertCode(categoryCode, codeValue)
- 파라미터 순서가 반대로 전달되어 카테고리 값이 표시됨
해결:
- optimizedConvertCode(meta.codeCategory, value) ✅
- 올바른 순서: (카테고리, 코드값)
- 이제 코드명이 정상적으로 표시됨
변경:
- 파라미터 순서 수정
- 주석 추가로 재발 방지
요구사항:
- DB에 저장된 코드 값(예: '001') → 코드명(예: '활성')으로 표시
구현:
- inputType === 'code'이고 codeCategory가 있을 때 변환 수행
- optimizedConvertCode를 통해 코드 값 → 코드명 변환
- 변환 성공 시 코드명 반환
- 변환 실패 시 원본 코드 값 반환
- try-catch로 에러 핸들링 추가
- 디버깅을 위한 에러 로그 추가
변경:
- 코드 변환 로직 복원
- 에러 처리 강화
- 변환 실패 시 원본 값 표시로 안전장치
문제:
- inputType이 'code'인 컬럼에서 코드 변환이 실행되어
- 실제 저장된 값 대신 코드 카테고리 값이 표시됨
- 사용자가 원하는 것은 원본 값 그대로 표시
해결:
- 코드 변환 로직 완전 제거
- inputType에 관계없이 원본 값 그대로 표시
- 숫자/날짜 등 기본 포맷팅만 유지
변경:
- optimizedConvertCode 호출 제거
- inputType === 'code' 조건 제거
- 원본 데이터 표시로 단순화
문제:
- webType과 codeCategory가 있기만 하면 무조건 코드 변환 시도
- 코드 타입이 아닌 컬럼도 코드 카테고리 값으로 변환되는 오류
해결:
- webType === 'code'일 때만 코드 변환 수행
- 다른 webType(text, number 등)은 코드 변환 건너뛰기
변경:
- meta?.webType && meta?.codeCategory
→ meta?.webType === 'code' && meta?.codeCategory
- TableListComponent: showHeader 조건부 렌더링 제거
- 타이틀 표시 영역 삭제
- 공간 절약을 위해 헤더 완전 제거
- FlowWidget: 플로우 제목 및 설명 영역 제거
- flowData.name 표시 영역 삭제
- flowData.description 표시 영역 삭제
- 더 많은 데이터 표시 공간 확보
UI 개선:
- 불필요한 헤더 제거로 컨텐츠 영역 확대
- 더 많은 데이터를 한 화면에 표시 가능
- 다중 컬럼 선택으로 계층적 그룹화 지원
- 그룹 설정 다이얼로그 추가
- 그룹별 데이터 펼치기/접기 기능
- 그룹 헤더에 항목 개수 표시
- localStorage에 그룹 설정 저장/복원
- 그룹 해제 버튼 추가
- 그룹 표시 배지 UI
주요 기능:
- 사용자가 원하는 컬럼(들)을 선택하여 그룹화
- 그룹 키: '통화:KRW > 단위:EA' 형식으로 표시
- 그룹 헤더 클릭으로 펼치기/접기
- 그룹 없을 때는 기존 렌더링 방식 유지
🎨 UI 개선
- 필터 설정 다이얼로그 스타일을 플로우 위젯과 동일하게 변경
- hover:bg-gray-50으로 호버 효과 추가
- rounded-lg, p-3, space-x-3으로 간격 및 패딩 개선
- space-y-2, py-4로 리스트 아이템 간격 조정
🐛 버그 수정
- 필터 목록에 key prop 추가 (React 경고 해결)
- Label 컴포넌트 대신 label 태그 사용 (불필요한 import 제거)
📝 변경 사항
- 플로우 위젯과 동일한 체크박스 리스트 스타일 적용
- 더 명확하고 클릭하기 쉬운 UI로 개선
✅ 결과
- 필터 설정 다이얼로그가 플로우 위젯과 일관된 스타일로 표시됨
- 테이블 헤더와 데이터 셀 모두에 whitespace-nowrap 적용
- 모바일에서도 텍스트가 2줄로 깨지지 않음
- overflow-hidden + text-ellipsis로 긴 텍스트 처리
- TableListComponent와 InteractiveDataTable 모두 적용
이제 화면을 줄여도 텍스트가 항상 1줄로 유지됨
- 모든 테이블 헤더를 가운데 정렬 (text-center)
- 숫자 타입(number, decimal) 데이터를 우측 정렬
- TableListComponent: inputType 기반 숫자 판단
- InteractiveDataTable: widgetType 기반 숫자 판단
- 체크박스는 기존대로 가운데 정렬 유지
- 일반 텍스트는 좌측 정렬 유지
더 읽기 쉬운 테이블 레이아웃 완성
- 체크박스 컬럼(__checkbox__)을 48px 고정 너비로 설정
- width, minWidth, maxWidth 모두 48px 적용
- 체크박스 컬럼에서 리사이즈 핸들 제거
- 초기 너비 측정 시 체크박스 컬럼 제외
- 테이블 헤더와 본문 셀 모두 적용
- InteractiveDataTable과 일관된 체크박스 컬럼 스타일
- ref callback에서 state 업데이트 제거
- useEffect + setTimeout으로 초기 너비 측정 (한 번만)
- hasInitializedWidths useRef로 중복 측정 방지
- columnRefs useRef로 DOM 직접 참조
- 드래그 중 리렌더링 없이 DOM만 직접 조작
- 부드럽고 정확한 리사이즈 구현 완료
✅ 해결 방법:
- 백분율 defaultWidth 제거, 초기값은 undefined로 설정
- ref callback에서 첫 렌더링 시 실제 offsetWidth 측정
- 측정한 실제 너비를 columnWidths state에 저장
- 이후 드래그로 80px까지 줄일 수 있음
✅ 적용 파일:
- TableListComponent.tsx (실제 화면)
- InteractiveDataTable.tsx (디자인 모드)
✅ 기술적 개선:
- table-layout: fixed + 동적 초기 너비 측정
- DOM 직접 조작으로 부드러운 리사이즈
- 최소 80px 보장 (Math.max)
- CSS minWidth 제거 (table-layout: fixed와 충돌)
- JavaScript에서 Math.max(80, width)로 최소 너비 보장
- 드래그 중과 마우스 업 시 모두 80px 최소값 적용
- 모든 디버그 로그 제거
- 깔끔하고 부드러운 리사이즈 완성
- 핸들 너비를 1px에서 2px로 증가
- z-index: 20 추가로 다른 요소 위에 표시
- padding과 negative margin으로 클릭 영역 확대 (좌우 4px씩)
- onClick에 stopPropagation 추가하여 정렬 클릭 방지
- 더 쉽게 클릭하고 드래그할 수 있도록 개선
- 실제 화면에서 사용되는 TableListComponent에도 리사이즈 기능 추가
- InteractiveDataTable과 동일한 리사이즈 핸들 구현
- columnWidths 상태로 각 컬럼 너비 관리
- 드래그 중 텍스트 선택 방지 및 이벤트 전파 차단
- 최소 너비 80px 보장
- TableListComponent: table_type_columns의 input_type 정보를 가져와서 숫자 포맷팅
- getColumnInputTypes API 추가로 컬럼별 입력 타입 조회
- columnMeta에 inputType 포함하여 formatCellValue에서 사용
- 테이블 관리에서 설정한 입력 타입(number/decimal)에 따라 자동으로 천 단위 콤마 표시
- 근본적인 해결: 컬럼명 기반이 아닌 실제 설정값 기반 포맷팅
- EditModal: 저장 완료 후 자동으로 닫히고 부모 테이블 새로고침
- buttonActions.ts: 저장 성공 후 closeEditModal 이벤트 발생
- InteractiveScreenViewerDynamic: onSave prop 추가하여 EditModal 연동
- InteractiveDataTable: EditModal 열 때 onSave 콜백으로 loadData 전달
- 두 가지 시나리오 모두 지원:
1. InteractiveScreenViewerDynamic 버튼의 onSave 호출
2. DynamicComponentRenderer 버튼의 buttonActions.ts 처리
✨ 새로운 기능
- 테이블 타입 관리에 테이블 복제 기능 추가
- 기존 테이블의 설정과 컬럼 정보를 복사하여 새 테이블 생성
- 최고 관리자만 사용 가능 (company_code = '*' AND userType = 'SUPER_ADMIN')
- 테이블 1개 선택 시에만 복제 버튼 활성화
🎨 UI 개선
- 테이블 목록에 '테이블 복제' 버튼 추가 (Copy 아이콘)
- CreateTableModal을 복제 모드로 재사용
- 복제 모드 시 제목/설명/버튼 텍스트 동적 변경
- 원본 테이블 정보 자동 로드
🔧 기술적 개선
- CreateTableModal에 mode/sourceTableName props 추가
- 복제 모드 감지 및 데이터 자동 로드 로직 구현
- API 타입 정의 수정 (ColumnListData 인터페이스 추가)
- 백엔드 응답 구조와 프론트엔드 타입 일치화
🐛 버그 수정
- API 응답 구조 불일치 문제 해결
- ColumnListResponse 타입 수정 (배열 → 객체)
- 데이터 파싱 로직 수정 (data.columns 접근)
- 디버그 로그 추가로 문제 추적 개선
📝 변경된 파일
- frontend/app/(main)/admin/tableMng/page.tsx
- frontend/components/admin/CreateTableModal.tsx
- frontend/lib/api/tableManagement.ts
- frontend/types/ddl.ts
- 테이블_복제_기능_구현_계획서.md (신규)
✅ 테스트 완료
- 최고 관리자 권한 체크
- 테이블 정보 로드
- 컬럼 정보 복제
- 새 테이블명 입력 및 검증
- 테이블 생성 및 목록 갱신
- frontend: screen.ts에 saveScreenLayout 함수 추가 (ScreenDesigner_new.tsx가 호출하던 누락된 함수)
- frontend: ScreenDesigner_new.tsx 저장 시 디버깅 로그 추가
- backend: screenManagementService.ts에 dataflowConfig 저장 확인 로그 추가
문제 원인:
- ScreenDesigner_new.tsx가 호출하던 screenApi.saveScreenLayout 함수가 정의되지 않음
- 이로 인해 레이아웃 저장이 실패했을 가능성
해결:
- saveScreenLayout 함수를 추가하여 정상적인 레이아웃 저장 가능
- 디버깅 로그를 통해 실제로 selectedDiagramId가 저장되는지 확인 가능
- 화면 관리 페이지에서 position.x === 0인 컴포넌트가 100% 너비로 표시되도록 수정
- 대시보드 뷰어에서 부모 컨테이너의 maxWidth 제한 제거하여 화면 전체 너비 활용
- AppLayout의 main 영역에 16px 내부 패딩 적용
- RealtimePreview 및 RealtimePreviewDynamic 컴포넌트에서 좌측 정렬 컴포넌트 너비 자동 조정
- 모바일 환경에서 화면 스케일링 비활성화 (반응형만 작동)
- table-mobile-fixed CSS 클래스 추가로 모바일 테이블 레이아웃 개선
- useResponsive 훅 추가로 반응형 감지 기능 구현
- 외부 커넥션 관리 테이블 표준화 (DB 연결, REST API 연결)
- 모든 관리자 테이블의 그림자 제거 (테이블 타입 관리 왼쪽 카드 제외)
- 테이블 타입 관리 왼쪽 카드 호버 효과 강화 (shadow-lg, bg-muted/20)
- 탭 컴포넌트 배경색 밝게 조정 (bg-muted/30)
- 탭 트리거 테두리 제거
- 모든 테이블 헤더의 회색 배경 제거 (bg-muted/50 → bg-background)
- 모든 테이블 행의 홀수 행 회색 배경 제거 (모든 행을 흰색 배경으로 통일)
- 호버 시에만 회색 배경이 나타나도록 통일
- TableListComponent, SingleTableWithSticky, 모든 관리자 테이블 컴포넌트에 적용
- 테이블 구조 표준화 문서 업데이트
- 모든 테이블 컴포넌트의 외곽 테두리(border) 제거
- 테이블 컨테이너의 라운드(rounded-lg) 제거
- 테이블 행 구분선(border-b)은 유지하여 데이터 구분
- FlowWidget과 TableListComponent에 동일한 스타일 적용
- 검색 필터 영역의 회색 배경(bg-muted/30) 제거
- 검색 필터 제목 제거
- AdvancedSearchFilters 컴포넌트의 '검색 필터' 제목 제거