+ {/* 배치 리스트 - 자체 스크롤 */}
+
{loading && batchConfigs.length === 0 && (
@@ -549,7 +565,7 @@ export default function BatchManagementPage() {
)}
- {filteredBatches.map((batch) => {
+ {pagedBatches.map((batch) => {
const batchId = batch.id!;
const isExpanded = expandedBatch === batchId;
const isExecuting = executingBatch === batchId;
@@ -674,6 +690,29 @@ export default function BatchManagementPage() {
})}
+ {/* 페이지네이션 — 리스트 영역 아래 고정 */}
+ {!loading && (
+
+
{
+ setItemsPerPage(size);
+ setCurrentPage(1);
+ }}
+ showPageSizeSelector
+ pageSizeOptions={[10, 20, 50, 100]}
+ />
+
+ )}
+
{/* 배치 타입 선택 모달 */}
{isBatchTypeModalOpen && (
setIsBatchTypeModalOpen(false)}>
diff --git a/frontend/app/(main)/admin/automaticMng/exconList/page.tsx b/frontend/app/(main)/admin/automaticMng/exconList/page.tsx
index 89ecba46..15c2dbda 100644
--- a/frontend/app/(main)/admin/automaticMng/exconList/page.tsx
+++ b/frontend/app/(main)/admin/automaticMng/exconList/page.tsx
@@ -231,15 +231,15 @@ export default function ExternalConnectionsPage() {
) },
{ key: "id", label: "연결 테스트", width: "150px", hideOnMobile: true,
render: (_v, row) => (
-
+
{ e.stopPropagation(); handleTestConnection(row); }}
disabled={testingConnections.has(row.id!)}
- className="h-9 text-sm">
+ className="h-7 px-2 text-xs">
{testingConnections.has(row.id!) ? "테스트 중..." : "테스트"}
{testResults.has(row.id!) && (
-
+
{testResults.get(row.id!) ? "성공" : "실패"}
)}
@@ -264,68 +264,68 @@ export default function ExternalConnectionsPage() {
];
return (
-
-
+
+
{/* 페이지 헤더 */}
-
-
외부 커넥션 관리
-
외부 데이터베이스 및 REST API 연결 정보를 관리합니다
+
+
외부 커넥션 관리
+
외부 데이터베이스 및 REST API 연결 정보를 관리합니다
{/* 탭 */}
-
setActiveTab(value as ConnectionTabType)}>
-
-
-
+ setActiveTab(value as ConnectionTabType)} className="flex min-h-0 flex-1 flex-col gap-3">
+
+
+
데이터베이스 연결
-
-
+
+
REST API 연결
{/* 데이터베이스 연결 탭 */}
-
+
{/* 검색 및 필터 */}
-
-
-
-
+
@@ -338,10 +338,12 @@ export default function ExternalConnectionsPage() {
isLoading={loading}
emptyMessage="등록된 연결이 없습니다"
skeletonCount={5}
+ compact
+ scrollContainer
cardTitle={(c) => c.connection_name}
cardSubtitle={(c) =>
{c.host}:{c.port}/{c.database_name} }
cardHeaderRight={(c) => (
-
+
{c.is_active === "Y" ? "활성" : "비활성"}
)}
@@ -351,7 +353,7 @@ export default function ExternalConnectionsPage() {
{ e.stopPropagation(); handleTestConnection(c); }}
disabled={testingConnections.has(c.id!)}
- className="h-9 flex-1 gap-2 text-sm">
+ className="h-7 flex-1 gap-1 text-xs">
{testingConnections.has(c.id!) ? "테스트 중..." : "테스트"}
-
+ className="h-7 flex-1 gap-1 text-xs">
+
SQL
{ e.stopPropagation(); handleEditConnection(c); }}
- className="h-9 flex-1 gap-2 text-sm">
-
+ className="h-7 flex-1 gap-1 text-xs">
+
편집
{ e.stopPropagation(); handleDeleteConnection(c); }}
- className="text-destructive hover:bg-destructive/10 hover:text-destructive h-9 flex-1 gap-2 text-sm">
-
+ className="text-destructive hover:bg-destructive/10 hover:text-destructive h-7 flex-1 gap-1 text-xs">
+
삭제
>
@@ -436,7 +438,7 @@ export default function ExternalConnectionsPage() {
{/* REST API 연결 탭 */}
-
+
diff --git a/frontend/components/admin/RestApiConnectionList.tsx b/frontend/components/admin/RestApiConnectionList.tsx
index 8ed5ea58..edd2ced1 100644
--- a/frontend/components/admin/RestApiConnectionList.tsx
+++ b/frontend/components/admin/RestApiConnectionList.tsx
@@ -219,27 +219,27 @@ export function RestApiConnectionList() {
return (
<>
{/* 검색 및 필터 */}
-
-
+
+
{/* 검색 */}
-
-
+
+
setSearchTerm(e.target.value)}
- className="h-10 pl-10 text-sm"
+ className="h-8 pl-9 text-xs"
/>
{/* 인증 타입 필터 */}
-
+
{supportedAuthTypes.map((type) => (
-
+
{type.label}
))}
@@ -248,12 +248,12 @@ export function RestApiConnectionList() {
{/* 활성 상태 필터 */}
-
+
{ACTIVE_STATUS_OPTIONS.map((option) => (
-
+
{option.label}
))}
@@ -262,79 +262,79 @@ export function RestApiConnectionList() {
{/* 추가 버튼 */}
-
- 새 연결 추가
+
+ 새 연결 추가
{/* 연결 목록 */}
{loading ? (
-
-
로딩 중...
+
) : connections.length === 0 ? (
-
+
-
등록된 REST API 연결이 없습니다
+
등록된 REST API 연결이 없습니다
) : (
-
-
-
-
- 연결명
- 회사
- 기본 URL
- 인증 타입
- 헤더 수
- 상태
- 마지막 테스트
- 연결 테스트
- 작업
+
+
+
+
+ 연결명
+ 회사
+ 기본 URL
+ 인증 타입
+ 헤더 수
+ 상태
+ 마지막 테스트
+ 연결 테스트
+ 작업
{connections.map((connection) => (
-
-
+
+
{connection.connection_name}
{connection.description && (
-
+
{connection.description}
)}
-
+
{(connection as any).company_name || connection.company_code}
-
+
{connection.base_url}
-
- {AUTH_TYPE_LABELS[connection.auth_type] || connection.auth_type}
+
+ {AUTH_TYPE_LABELS[connection.auth_type] || connection.auth_type}
-
+
{Object.keys(connection.default_headers || {}).length}
-
-
+
+
{connection.is_active === "Y" ? "활성" : "비활성"}
-
+
{connection.last_test_date ? (
-
-
{new Date(connection.last_test_date).toLocaleDateString()}
+
+
{new Date(connection.last_test_date).toLocaleDateString()}
{connection.last_test_result === "Y" ? "성공" : "실패"}
@@ -343,41 +343,41 @@ export function RestApiConnectionList() {
-
)}
-
-
+
+
handleTestConnection(connection)}
disabled={testingConnections.has(connection.id!)}
- className="h-9 text-sm"
+ className="h-7 px-2 text-xs"
>
{testingConnections.has(connection.id!) ? "테스트 중..." : "테스트"}
{testResults.has(connection.id!) && (
-
+
{testResults.get(connection.id!) ? "성공" : "실패"}
)}
-
-
+
+
handleEditConnection(connection)}
- className="h-8 w-8"
+ className="h-7 w-7"
>
-
+
handleDeleteConnection(connection)}
- className="text-destructive hover:bg-destructive/10 h-8 w-8"
+ className="text-destructive hover:bg-destructive/10 h-7 w-7"
>
-
+
diff --git a/frontend/components/common/ResponsiveDataView.tsx b/frontend/components/common/ResponsiveDataView.tsx
index 3cd8f723..4f5790d7 100644
--- a/frontend/components/common/ResponsiveDataView.tsx
+++ b/frontend/components/common/ResponsiveDataView.tsx
@@ -92,6 +92,11 @@ export function ResponsiveDataView
({
}: ResponsiveDataViewProps) {
const rowHeight = compact ? "h-10" : "h-16";
const headHeight = compact ? "h-9" : "h-12";
+ const bodyText = compact ? "text-xs" : "text-sm";
+ const headText = compact ? "text-xs" : "text-sm";
+ const cellPad = compact ? "px-3" : "";
+ const cardTitleClass = compact ? "text-sm" : "text-base";
+ const cardSubText = compact ? "text-xs" : "text-sm";
// cardFields 미지정 시 columns에서 자동 생성
function resolveCardFields(item: T): RDVCardField[] {
if (typeof cardFields === "function") return cardFields(item);
@@ -233,16 +238,20 @@ export function ResponsiveDataView({
{/* 데스크톱 테이블 (컨테이너 ≥ 48rem / 768px) */}
-
+
@@ -250,7 +259,7 @@ export function ResponsiveDataView({
{col.label}
@@ -258,7 +267,7 @@ export function ResponsiveDataView({
{renderActions && (
{actionsLabel || "작업"}
@@ -278,7 +287,7 @@ export function ResponsiveDataView({
{columns.map((col) => (
{col.render
? col.render(getNestedValue(item, col.key), item, index)
@@ -286,7 +295,7 @@ export function ResponsiveDataView({
))}
{renderActions && (
-
+
{renderActions(item)}
)}
@@ -319,11 +328,11 @@ export function ResponsiveDataView({
{/* 카드 헤더 */}
-
+
{cardTitle(item)}
{cardSubtitle && (
-
+
{cardSubtitle(item)}
)}
@@ -337,7 +346,7 @@ export function ResponsiveDataView
({
{fields.length > 0 && (
{fields.map((field, i) => (
-