# UI 디자인 시스템 (UI_DESIGN.md) > GA 수수료 정산 솔루션의 UI 표준. 모든 화면은 이 규칙을 따른다. > 기술: React 18 + Ant Design 5.x + AG Grid Community > 신입 개발자가 복붙으로 일관된 UI를 만들 수 있도록 설계. --- ## 1. Ant Design 테마 커스터마이징 ### ConfigProvider 설정 (App.tsx) ```tsx import { ConfigProvider } from 'antd'; import koKR from 'antd/locale/ko_KR'; const theme = { token: { // 브랜드 컬러 colorPrimary: '#1677FF', colorSuccess: '#0F6E56', colorWarning: '#BA7517', colorError: '#E24B4A', colorInfo: '#1677FF', // 폰트 fontFamily: "'Pretendard', -apple-system, sans-serif", fontSize: 13, fontSizeHeading1: 22, fontSizeHeading2: 18, fontSizeHeading3: 16, // 라운딩 borderRadius: 6, borderRadiusLG: 8, // 간격 padding: 16, paddingLG: 24, margin: 16, // 배경 colorBgContainer: '#ffffff', colorBgLayout: '#f5f5f5', colorBgElevated: '#ffffff', // 테이블 tablePaddingHorizontal: 12, tablePaddingVertical: 10, tableHeaderBg: '#fafafa', tableRowHoverBg: '#f5f7fa', tableBorderColor: '#f0f0f0', }, components: { // 사이드 메뉴 Menu: { itemHeight: 40, itemMarginInline: 8, itemBorderRadius: 6, subMenuItemBg: 'transparent', itemSelectedBg: '#e6f1fb', itemSelectedColor: '#185fa5', }, // 테이블 Table: { headerBg: '#fafafa', rowHoverBg: '#f5f7fa', cellPaddingBlock: 10, cellPaddingInline: 12, headerSplitColor: '#f0f0f0', }, // 버튼 Button: { controlHeight: 32, controlHeightSM: 28, paddingInline: 16, }, // 입력 Input: { controlHeight: 32, paddingInline: 10, }, Select: { controlHeight: 32, }, // 카드 Card: { paddingLG: 16, }, }, }; ``` ### 폰트 설치 (index.html) ```html ``` ### 아이콘: Tabler Icons ```bash pnpm add @tabler/icons-react ``` ```tsx import { IconUsers, IconCalculator, IconDownload } from '@tabler/icons-react'; ``` --- ## 2. 글로벌 CSS 변수 (styles/variables.css) ```css :root { /* 브랜드 */ --ga-primary: #1677FF; --ga-primary-light: #E6F1FB; --ga-primary-dark: #0C447C; /* 상태 색상 (CodeBadge 등) */ --ga-success: #0F6E56; --ga-success-bg: #E1F5EE; --ga-warning: #BA7517; --ga-warning-bg: #FAEEDA; --ga-danger: #E24B4A; --ga-danger-bg: #FCEBEB; --ga-info: #185FA5; --ga-info-bg: #E6F1FB; /* 금액 */ --ga-money-plus: #0F6E56; --ga-money-minus: #E24B4A; /* 레이아웃 */ --ga-sider-width: 220px; --ga-sider-collapsed-width: 64px; --ga-header-height: 48px; --ga-content-padding: 20px; --ga-page-max-width: 1400px; /* 간격 단위 */ --ga-spacing-xs: 4px; --ga-spacing-sm: 8px; --ga-spacing-md: 12px; --ga-spacing-lg: 16px; --ga-spacing-xl: 24px; /* 그림자 (최소한만 사용) */ --ga-shadow-card: 0 1px 2px rgba(0,0,0,0.03); --ga-shadow-dropdown: 0 4px 12px rgba(0,0,0,0.08); } ``` --- ## 3. 레이아웃 규칙 ### MainLayout 구조 ``` ┌─────────────────────────────────────────────┐ │ Header (48px) │ │ [☰] GA 정산시스템 [2026-05 ▼] [🔔3] [관리자]│ ├──────┬──────────────────────────────────────┤ │Sider │ Content │ │220px │ Breadcrumb │ │ │ ┌─────────────────────────────────┐ │ │ 메뉴 │ │ 페이지 내용 │ │ │ │ │ │ │ │ │ └─────────────────────────────────┘ │ └──────┴──────────────────────────────────────┘ ``` ### Header - 높이: 48px, 배경: 흰색, 하단 border - 왼쪽: 햄버거 메뉴(접기/펼치기) + 로고 "GA 정산시스템" - 오른쪽: 정산월 MonthPicker + 알림벨(미읽음 숫자뱃지) + 사용자 Dropdown ### Sider (사이드 메뉴) - 너비: 220px (접으면 64px, 아이콘만) - 배경: 흰색 - 메뉴 아이템: 높이 40px, 좌측 아이콘 16px + 텍스트 13px - 활성 메뉴: 배경 #E6F1FB, 텍스트 #185FA5, font-weight 500 - 서브메뉴: 좌측 30px 인덴트 - 메뉴 데이터: API에서 동적 로드 (GET /api/menus/my) ### Content - Breadcrumb: 상단 (홈 > 조직관리 > 설계사목록) - 패딩: 20px - 최대 너비: 1400px (중앙 정렬) --- ## 4. 페이지 표준 레이아웃 (3가지) ### 타입 A: 목록 페이지 (가장 많이 사용) ``` ┌──── 검색 폼 (SearchForm) ─────────────────┐ │ [설계사명 ___] [상태 ▼전체] [기간 ___~___] [조회] [초기화] │ └────────────────────────────────────────────┘ ┌──── 버튼 영역 ─────────────────────────────┐ │ [+ 등록] [⬇ 엑셀] │ └────────────────────────────────────────────┘ ┌──── 데이터 테이블 ─────────────────────────┐ │ □ 설계사명 소속 직급 수수료합계 상태│ │ □ 김영수 서울1팀 수석 12,450,000 위촉│ │ □ 이미영 경기2팀 설계사 8,320,000 위촉│ ├────────────────────────────────────────────┤ │ 총 1,234건 ‹ 1 2 3 ... › │ └────────────────────────────────────────────┘ ``` - 검색 폼: 회색 배경(#fafafa), border-radius 8px, padding 12px 16px - 검색 조건: 한 줄에 3~4개, 버튼은 우측 - 버튼 영역: 우측 정렬, 테이블 바로 위 margin-bottom 12px - 등록 버튼: Primary(파란색), 엑셀: Default(흰색) - 테이블: antd Table 또는 AG Grid ### 타입 B: 상세 페이지 ``` ┌──── 기본 정보 카드 ─────────────────────────┐ │ 설계사명: 김영수 소속: 서울1팀 상태: [위촉] │ │ 전화번호: 010-****-5678 이메일: kim@ga.com │ │ [수정] [삭제] │ └─────────────────────────────────────────────┘ ┌──── 탭 영역 ────────────────────────────────┐ │ [기본정보] [실적현황] [소속이력] [변경이력] │ ├─────────────────────────────────────────────┤ │ 탭 내용... │ └─────────────────────────────────────────────┘ ``` - 상단 카드: 흰색 배경, border, border-radius 8px - 탭: antd Tabs, 카드 안에 포함 - 버튼: 카드 우상단 ### 타입 C: 대시보드 ``` ┌──── 지표 카드 (4열) ───────────────────────┐ │ [모집 2.4억] [유지 8,200만] [환수 1,350만] [순 3.1억]│ └────────────────────────────────────────────┘ ┌─── 차트 (2:1) ──────┬─── 현황 ────────────┐ │ 월별 추이 (recharts) │ 배치 진행 상태 │ │ ▆▆▆▇█ │ ● 수신 완료 │ │ │ ● 계산 진행중... │ └─────────────────────┴──────────────────────┘ ┌──── 알림/오류 ──────────────────────────────┐ │ [대사불일치] 삼성생명 5월 3건 차이 10분 전 │ │ [파싱에러] 한화생명 12행 형식 오류 1시간 전 │ └────────────────────────────────────────────┘ ``` - 지표 카드: 배경 #fafafa, border-radius 8px, padding 12px - 숫자: 20~22px, weight 500 - 증감: ▲ 초록(양수), ▼ 빨강(음수) - 차트: recharts, 높이 200~240px --- ## 5. 공통 컴포넌트 스타일 규칙 ### CodeBadge (상태 뱃지) ```tsx // 상태값 → 색상 자동 매핑 const COLOR_MAP = { // 초록 (긍정적 완료 상태) CONFIRMED: 'success', APPROVED: 'success', ACTIVE: 'success', PAID: 'success', COMPLETED: 'success', MATCH: 'success', // 파랑 (진행 중) CALCULATED: 'info', PENDING: 'info', PROCESSING: 'info', REVIEWED: 'info', NEW: 'info', // 주황 (주의) HOLD: 'warning', SUSPEND: 'warning', MISMATCH: 'warning', PARTIAL: 'warning', // 빨강 (부정적) REJECTED: 'danger', LEAVE: 'danger', CANCEL: 'danger', FAILED: 'danger', LAPSED: 'danger', // 회색 (기본) DRAFT: 'default', READY: 'default', }; // 렌더링 {codeName} ``` ### MoneyText (금액 표시) ```tsx // 양수: 초록, 음수: 빨강, 0: 회색 // 항상 천 단위 콤마, 정수 표시 0 ? '#0F6E56' : amount < 0 ? '#E24B4A' : '#888' }}> {amount >= 0 ? '' : '-'}{Math.abs(amount).toLocaleString()} ``` ### SearchForm (검색 폼) ```tsx // 스타일 규칙 // 배경: #fafafa, border-radius: 8px, padding: 12px 16px // 조건: Row + Col (span 기준) // - 텍스트 입력: span=6 (4개/행) // - Select: span=4 (6개/행까지) // - DateRange: span=8 // - 버튼: 우측 정렬
설계사명
상태
``` ### DataTable (목록 테이블) ```tsx // 스타일 규칙 // 행 높이: 42px (compact) // 헤더: 배경 #fafafa, font-weight 500, font-size 12px // 본문: font-size 13px // hover: 배경 #f5f7fa // 금액 컬럼: 우측 정렬, MoneyText // 상태 컬럼: 중앙 정렬, CodeBadge // 이름 컬럼: font-weight 500, 클릭 시 상세 이동 // 페이지네이션: 우측, "총 N건" 좌측 `총 ${total.toLocaleString()}건`, showSizeChanger: true, pageSizeOptions: [20, 50, 100], defaultPageSize: 20, }} /> ``` ### DataGrid (AG Grid 래퍼) ```tsx // AG Grid 공통 설정 const defaultColDef = { sortable: true, resizable: true, filter: true, minWidth: 80, }; const gridOptions = { rowHeight: 36, headerHeight: 38, // 한글 로케일 localeText: AG_GRID_LOCALE_KO, // 합계행 pinnedBottomRowData: [summaryRow], // 셀 스타일 getRowStyle: (params) => { if (params.node.rowPinned) return { background: '#fafafa', fontWeight: 500 }; }, }; // AG Grid 사용 화면: 원장관리, 정산결과, 수수료율편집, 대사현황 // 나머지는 Ant Design Table ``` --- ## 6. 등록/수정 폼 규칙 ```tsx // 폼 레이아웃 규칙 // 2열 배치 (Row > Col span=12) // 레이블: 12px, color #999, 필수 표시 빨간 * // 입력: height 32px // Select: 공통코드는 CodeSelect 사용 // 하단 버튼: 우측 정렬 [취소] [저장]
``` --- ## 7. 모달/드로워 규칙 ``` // 등록/수정 폼 → Drawer (우측에서 슬라이드) // 너비: 600px (2열 폼), 400px (단순 폼) // 제목: "설계사 등록" / "설계사 수정" // 하단: 취소 + 저장 버튼 // 상세 보기 → Modal // 너비: 720px // Descriptions 컴포넌트로 상세 표시 // 확인/경고 → Modal.confirm() // "정산을 확정하시겠습니까?" [취소] [확정] // 삭제 → Modal.confirm({ type: 'warning' }) // "삭제하면 복구할 수 없습니다" [취소] [삭제] ``` --- ## 8. 화면별 상세 와이어프레임 ### 8.1 대시보드 (/) ``` 레이아웃: 타입 C (대시보드) ├── 지표 카드 4열: 모집수수료, 유지수수료, 환수금, 순지급액 │ - 이번 달 금액 (억/만 단위 자동) │ - 전월 대비 증감률 (▲초록/▼빨강) │ - 카드 클릭 → 해당 원장 페이지 이동 ├── 2열 영역 │ ├── 왼쪽(60%): 월별 추이 차트 (recharts BarChart) │ │ - X축: 최근 6개월, Y축: 금액 │ │ - 시리즈: 모집(파랑), 유지(초록), 환수(빨강) │ └── 오른쪽(40%): 배치 현황 카드 │ - Step별 상태: ● 완료(초록), ● 진행중(파랑+pulse), ○ 대기(회색) │ - 각 Step: 이름 + 완료시간/진행시간 │ - 에러 시: ● 빨강 + 에러 메시지 └── 알림/오류 패널 - 대사 불일치, 파싱 에러, 승인 대기 등 - 뱃지 색상: 에러=빨강, 경고=주황, 정보=파랑 - 클릭 → 해당 화면 이동 ``` ### 8.2 조직관리 (/org) ``` 레이아웃: 2열 (좌 300px 트리 + 우 나머지 목록) ├── 좌측: 조직 트리 (antd Tree) │ - 본사 > 지역본부 > 지점 > 팀 │ - 드래그앤드롭 정렬 (관리자만) │ - 노드 클릭 → 우측 설계사 목록 필터링 │ - 우클릭 → 추가/수정/삭제 컨텍스트메뉴 └── 우측: 설계사 목록 (타입 A) - 검색: 이름, 상태, 직급 - 테이블 컬럼: 설계사명, 직급, 상태, 위촉일, 수수료합계 - 행 클릭 → 상세 (타입 B, 탭: 기본정보/실적/이력) ``` ### 8.3 원장관리 (/ledger) ``` 레이아웃: 탭 3개 (모집/유지/예외) ├── 공통 검색: 정산월, 보험사, 설계사, 상태 ├── AG Grid (DataGrid) 사용 ← 대량 데이터 │ - 서버사이드 페이징/정렬/필터 │ - 컬럼 고정: 왼쪽(증권번호, 설계사명), 오른쪽(수수료합계) │ - 합계행: 하단 고정 (pinnedBottomRow) │ - 금액 셀: 우측 정렬, MoneyText 스타일 │ - 상태 셀: CodeBadge ├── 예외금액 탭 추가 기능: │ - [+ 등록] → Drawer (예외유형, 금액, 방향, 설명) │ - 승인 워크플로우: 작성→대기→승인/반려 │ - 승인 버튼: PermissionButton(permCode="APPROVE") └── 엑셀 다운로드: ExcelExportButton (100만건, 진행률) ``` ### 8.4 정산관리 (/settle) ``` 레이아웃: 탭 4개 (배치실행/정산결과/정산상세/대사) [배치실행 탭] ├── 정산월 선택 + [정산실행] 버튼 ├── 진행 상태: Steps 컴포넌트 (8단계) │ - 각 Step: 이름 + 처리건수 + 소요시간 + 상태아이콘 │ - 진행 중: 폴링으로 실시간 업데이트 (3초 간격) │ - 에러: Step 클릭 → 에러 상세 모달 └── 완료 시: 결과 요약 카드 (총건수, 성공, 에러, 소요시간) [정산결과 탭] ├── AG Grid: 설계사별 정산 결과 │ - 컬럼: 설계사명, 소속, 모집, 유지, 예외가산, 예외차감, 오버라이드, 환수, 세전, 세금, 순지급 │ - 합계행 │ - 상태별 필터: 계산완료/검토/확정/지급/보류 │ - 행 클릭 → 정산상세 탭으로 이동 └── 버튼: [일괄확정] [엑셀다운로드] [정산상세 탭] ├── 설계사 선택 (상단) ├── 요약 카드 4열: 모집합계, 유지합계, 예외합계, 순지급액 └── 탭 5개: 모집수수료 / 유지수수료 / 예외금액 / 오버라이드 / 환수 - 각 탭 AG Grid로 상세 내역 표시 [대사 탭] ├── 보험사별 대사 결과 테이블 │ - 보험사, 보험사건수, 시스템건수, 차이, 보험사금액, 시스템금액, 차이, 상태 │ - 상태: MATCH(초록), MISMATCH(빨강) └── 불일치 행 클릭 → 상세 모달 (건별 차이 목록) ``` ### 8.5 수수료규정 (/rules) ``` 레이아웃: 탭 4개 (수수료율/지급률/오버라이드/환수) 각 탭 공통: ├── 검색: 보험사/보험종류/적용기간 ├── AG Grid: 셀 편집 가능 (인라인 수정) │ - 수정된 셀: 노란색 배경 강조 │ - 하단: [저장] [취소] 버튼 ├── 버전 관리: │ - 규정 수정 시 → version 자동 증가 + 기존 규정 effective_to 설정 │ - [이력보기] 버튼 → 버전별 변경 내역 타임라인 └── 신규 등록: [+ 규정 등록] → Drawer ``` ### 8.6 시스템관리 (/system) #### 역할관리 (/system/roles) ``` ├── 역할 목록 테이블 └── 역할 클릭 → 권한 매트릭스 ┌──────────┬──────┬──────┬──────┬──────┬──────┬──────┐ │ 메뉴 │ 조회 │ 등록 │ 수정 │ 삭제 │ 승인 │ 엑셀 │ ├──────────┼──────┼──────┼──────┼──────┼──────┼──────┤ │ 조직관리 │ ☑ │ ☑ │ ☑ │ ☐ │ ☐ │ ☑ │ │ 정산관리 │ ☑ │ ☐ │ ☐ │ ☐ │ ☑ │ ☑ │ │ 시스템관리 │ ☑ │ ☑ │ ☑ │ ☑ │ ☐ │ ☐ │ └──────────┴──────┴──────┴──────┴──────┴──────┴──────┘ [전체선택/해제 토글] [저장] ``` #### 공통코드관리 (/system/codes) ``` 2열 레이아웃: ├── 좌측 (300px): 코드 그룹 리스트 │ - 선택 시 우측에 상세 코드 표시 │ - 시스템 코드: 🔒 아이콘 + 수정 불가 └── 우측: 상세 코드 테이블 - 코드값, 코드명, 영문명, 정렬순서, 활성여부 - 인라인 편집 가능 (시스템코드 제외) ``` #### 업로드 템플릿 관리 (/system/upload-templates) ``` 2열 레이아웃: ├── 좌측 (300px): 템플릿 목록 (카테고리별 필터) └── 우측: 컬럼 매핑 편집기 - 각 행: [엑셀 컬럼 입력] → [DB 필드 Select] → [변환규칙 Select] → [파라미터] - 드래그앤드롭 순서 변경 - [+ 행 추가] [미리보기] [저장] - 미리보기: 샘플 엑셀 업로드 → 첫 5행 매핑 결과 테이블 ``` --- ## 9. 반응형 규칙 ``` // 이 솔루션은 데스크톱 전용 (1280px 이상) // 모바일 대응 불필요 (사내 관리 시스템) // 최소 해상도: 1280 x 720 // 권장 해상도: 1920 x 1080 // 1280px 미만: Sider 자동 접힘 (아이콘만) // 1920px 이상: Content 최대 너비 1400px 중앙 정렬 ``` --- ## 10. 신입 개발자 UI 체크리스트 새 화면 만들 때 아래 항목 확인: - [ ] 검색 폼: SearchForm 컴포넌트 사용, 배경 #fafafa - [ ] 목록: 단순이면 DataTable, 대량/편집이면 DataGrid - [ ] 상태 컬럼: CodeBadge 사용 (하드코딩 색상 금지) - [ ] 금액 컬럼: MoneyText 사용 (양수 초록, 음수 빨강) - [ ] Select: CodeSelect 사용 (공통코드 연동) - [ ] 버튼: PermissionButton 사용 (권한 제어) - [ ] 엑셀: ExcelExportButton 사용 - [ ] 등록/수정: Drawer 사용 (모달 아님) - [ ] 삭제: Modal.confirm 사용 - [ ] 폼: antd Form + 2열(Col span=12) + layout="vertical" - [ ] 금액 입력: InputNumber + formatter (천단위 콤마) - [ ] 날짜: DatePicker + dayjs - [ ] 정산월: MonthPicker 공통 컴포넌트