1. 관리자 UI 개요
DXCMS 관리자 UI는 dxb-css(Tailwind 호환 런타임 CSS 엔진) + 컴포넌트 라이브러리(admin/style.css)의 이중 레이어로 구성됩니다. 빌드 도구 없이 PHP 서버만으로 동작하며, 반응형(모바일•태블릿•데스크톱)을 완전 지원합니다.
1.1 UI 스택 구성
| 레이어 |
기술 |
역할 |
| 1계층 (정적 컴포넌트) |
admin/style.css (v3.2.0) |
★ 최우선 로드. 관리자 전용 디자인 시스템 — 디자인 토큰(CSS 변수), 레이아웃, 공통 컴포넌트, 대시보드, 반응형 유틸리티 포함 |
| 2계층 (동적 유틸리티) |
dxb-css.js (v4.5.0) |
Tailwind 호환 런타임 엔진. MutationObserver로 DOM 변경 감지, 동적으로 생성되는 클래스를 실시간 처리. 빌드 도구 불필요 |
| 3계층 (폰트) |
Pretendard (CDN) |
한국어 최적화 UI 폰트. 본문 텍스트 전반에 사용 |
| 4계층 (디스플레이 폰트) |
Space Grotesk (Google Fonts) |
숫자·영문 강조 폰트. KPI 수치, 통계 숫자에 사용 |
| 5계층 (아이콘) |
Font Awesome 6.5 (CDN) |
아이콘 라이브러리. 사이드바 메뉴, 버튼, 대시보드 아이콘 |
| 6계층 (JS 유틸) |
jQuery 3.7.1 (CDN) |
사이드바 토글, 이벤트 처리 |
1.2 style.css vs dxb-css.js 역할 분담
style.css : 정적 pre-compile 유틸리티 클래스 (빌드 시 결정된 클래스)
dxb-css.js : 동적 클래스 처리 (JS 실행 시 DOM에서 새로 발견되는 클래스)
로드 순서가 핵심 — style.css를 dxb-css.js보다 반드시 먼저 로드해야
첫 paint 전에 스타일이 적용되어 CLS(레이아웃 흔들림)가 발생하지 않습니다.
<!-- ① style.css 최우선 로드 -->
<link rel="stylesheet" href="admin/style.css">
<!-- ② dxb-css.js — <style> 태그를 파싱 즉시 head에 삽입 -->
<script data-dxb="1" src="assets/js/dxb-css.js"></script>
2. 디자인 토큰 (CSS 변수)
모든 색상, 크기, 간격, 그림자는 CSS 변수(:root)로 중앙 관리됩니다. 다크모드나 테마 변경 시 이 변수들만 수정하면 전체 UI가 일관성 있게 변경됩니다.
2.1 브랜드 색상
| CSS 변수 |
값 |
사용처 |
| --dx-primary |
#6366f1 (Indigo 500) |
주요 버튼, 활성 메뉴, 링크, 포커스 링, 배지 |
| --dx-primary-dark |
#4f46e5 (Indigo 600) |
버튼 호버, 강조 텍스트 |
| --dx-primary-light |
#eff0fe |
버튼 호버 배경, 아이콘 배경, 입력 포커스 배경 |
| --dx-primary-ring |
rgba(99,102,241,.18) |
버튼 box-shadow, 입력 포커스 링 |
2.2 중립 색상 (배경•테두리)
| CSS 변수 |
값 |
사용처 |
| --dx-bg |
#f0f2f8 |
페이지 전체 배경색 |
| --dx-surface |
#ffffff |
카드, 모달, 입력 필드 배경 |
| --dx-border |
#e4e9f2 |
카드 테두리, 테이블 테두리, 구분선 |
| --dx-border-2 |
#f1f5f9 |
테이블 행 구분선, 카드 내부 구분선 (더 연한 선) |
2.3 텍스트 계층
| CSS 변수 |
값 |
사용처 |
| --dx-text-1 |
#0f172a (Slate 900) |
페이지 제목, KPI 수치, 강조 텍스트 |
| --dx-text-2 |
#334155 (Slate 700) |
본문 텍스트, 테이블 내용, 카드 내용 |
| --dx-text-3 |
#64748b (Slate 500) |
라벨, 보조 설명, 테이블 헤더 |
| --dx-text-4 |
#94a3b8 (Slate 400) |
플레이스홀더, 날짜, 비활성 메뉴, 힌트 |
2.4 상태 색상 및 레이아웃 토큰
| CSS 변수 |
값 |
사용처 |
| --dx-success |
#10b981 (Emerald 500) |
성공 알림, 활성 배지, 성공 버튼 |
| --dx-warning |
#f59e0b (Amber 500) |
경고 알림, 주의 배지 |
| --dx-danger |
#ef4444 (Red 500) |
오류 알림, 삭제 버튼, 위험 배지 |
| --dx-info |
#3b82f6 (Blue 500) |
정보 알림, 안내 배지 |
| --dx-sidebar-w |
240px |
사이드바 너비 (태블릿: 200px, 모바일: 260px) |
| --dx-topbar-h |
58px |
상단바 높이 (모바일: 52px) |
| --dx-radius |
14px |
카드, 버튼 기본 border-radius |
| --dx-radius-sm |
9px |
버튼 small, 입력 필드 border-radius |
| --dx-radius-lg |
20px |
대형 카드, 모달 border-radius |
| --dx-ease |
cubic-bezier(.4,0,.2,1) |
모든 transition 타이밍 함수 (Material Design 표준) |
3. 레이아웃 구조
관리자 UI는 고정 사이드바 + 스크롤 가능한 메인 영역의 2열 레이아웃입니다. 사이드바는 position:fixed로 항상 화면에 고정되고, 메인 영역은 좌측에 사이드바 너비만큼 margin이 적용됩니다.
3.1 HTML 구조 다이어그램
<body class="adm-body">
<!-- 모바일 오버레이 배경 -->
<div id="adm_navi_overlay"></div>
<!-- ① 사이드바 (position:fixed, width:240px) -->
<aside id="adm_navi_sidebar">
<div class="adm-sb-profile"> <!-- 관리자 프로필 (아바타+이름+이메일) -->
<nav class="adm-sb-nav" id="adm_navi_nav"> <!-- 메뉴 (스크롤) -->
<div class="adm-sb-section">섹션명</div>
<a class="adm-sb-link [active]">메뉴항목</a>
</nav>
<div class="adm-sb-footer"> <!-- 사이트보기 + 로그아웃 + 버전 -->
</aside>
<!-- ② 메인 래퍼 (margin-left:240px) -->
<div id="adm_navi_wrap">
<!-- 상단바 (position:sticky, top:0, height:58px) -->
<header id="adm_navi_top">
<button id="adm_navi_btn"> <!-- 햄버거 (모바일만 표시) -->
<nav class="adm-breadcrumb"> <!-- 브레드크럼 -->
<div class="adm-topbar-right"> <!-- 날짜 + 사이트보기 -->
</header>
<!-- 본문 (padding:26px) -->
<main>
<div id="adm-nav-pos"> <!-- 앵커 점프 방지용 -->
[dx_admin_top 훅]
[모듈 콘텐츠 require]
[dx_admin_bottom 훅]
</main>
<!-- 푸터 -->
<footer id="adm_navi_footer">버전 정보</footer>
</div>
</body>
3.2 레이아웃 CSS 핵심 규칙
| 선택자 |
핵심 CSS 속성 |
| #adm_navi_sidebar |
position:fixed; top:0; left:0; bottom:0; width:240px; z-index:300; background:linear-gradient(180deg,#0c1220,#151c2e,#1a2035) |
| #adm_navi_wrap |
margin-left:240px; min-height:100vh; display:flex; flex-direction:column |
| #adm_navi_top |
position:sticky; top:0; z-index:200; height:58px; background:rgba(255,255,255,.97); backdrop-filter:blur(16px) |
| #adm_navi_wrap > main |
flex:1; padding:26px |
| .adm-sb-nav |
flex:1; overflow-y:auto; padding:10px 8px (스크롤 가능 영역) |
| .adm-sb-footer |
flex-shrink:0; border-top:1px solid rgba(255,255,255,.05) (항상 하단 고정) |
| #adm_navi_overlay |
position:fixed; inset:0; background:rgba(0,0,0,.5); backdrop-filter:blur(3px); z-index:290 (모바일 전용) |
4. 사이드바(Sidebar) UI
사이드바는 짙은 네이비 그라데이션 배경에 세 영역(프로필•내비•하단)으로 구성됩니다. 다크 테마 사이드바와 라이트 테마 본문의 대비는 관리자 전용 UI임을 시각적으로 명확히 구분해 줍니다.
4.1 사이드바 3개 영역
| 영역 |
클래스 |
내용 및 CSS 특징 |
| 프로필 영역 |
.adm-sb-profile |
관리자 이름(첫 글자 아바타) + 이름 + 이메일. flex-shrink:0으로 항상 상단 고정. border-bottom:1px solid rgba(255,255,255,.06)으로 구분 |
| 내비 영역 |
.adm-sb-nav |
flex:1로 나머지 공간 모두 차지. overflow-y:auto로 메뉴 스크롤 가능. sessionStorage로 스크롤 위치 저장/복원 |
| 하단 영역 |
.adm-sb-footer |
flex-shrink:0으로 항상 하단 고정. 사이트보기 링크 + 로그아웃 버튼(#f87171 빨간색) + 버전 정보 |
4.2 아바타 컴포넌트
/* .adm-sb-avatar — 관리자 이름 첫 글자 표시 */
.adm-sb-avatar {
width:40px; height:40px;
border-radius:12px;
background:linear-gradient(135deg, var(--dx-primary), #8b5cf6);
/* Indigo → Violet 그라데이션 */
color:#fff; font-weight:800; font-size:1rem;
box-shadow:0 2px 10px rgba(99,102,241,.4);
}
/* PHP에서 첫 글자 추출 */
$_admInitial = dx_mb_substr($_admName, 0, 1);
// → 관리자 이름이 "홍길동"이면 아바타에 "홍" 표시
4.3 메뉴 링크 컴포넌트
/* .adm-sb-link — 기본 상태 */
.adm-sb-link {
display:flex; align-items:center; gap:10px;
padding:9px 12px; border-radius:10px;
font-size:.84rem; font-weight:500;
color:#7a91a8; /* 비활성: 회청색 */
transition:all .18s var(--dx-ease);
}
/* 호버: 배경 밝아지고 텍스트 밝아짐 + 2px 오른쪽 이동 */
.adm-sb-link:hover {
background:rgba(255,255,255,.06);
color:#e2e8f0;
transform:translateX(2px);
}
/* 활성 메뉴: Indigo 반투명 그라데이션 배경 */
.adm-sb-link.active {
background:linear-gradient(135deg,
rgba(99,102,241,.25),
rgba(139,92,246,.18));
color:#a5b4fc; /* Indigo 300 */
font-weight:700;
box-shadow:inset 0 0 0 1px rgba(99,102,241,.25);
}
/* 섹션 구분자 */
.adm-sb-section {
padding:14px 10px 4px;
font-size:.6rem; font-weight:800;
color:#3d5068;
text-transform:uppercase; letter-spacing:.12em;
}
4.4 active 판정 로직
// admin/index.php — adm_nav() 함수
function adm_nav($label, $path, $icon, $cur) {
$active = (
rtrim($cur, '/') === rtrim($path, '/')
// 정확히 같은 경로
|| strpos($cur, $path.'/') === 0
// 하위 경로 포함 (/admin/boards/5 → /admin/boards active)
);
$cls = 'adm-sb-link' . ($active ? ' active' : '');
// #adm-nav-pos: 앵커로 본문 점프 방지
echo '<a href="'.$base.'#adm-nav-pos" class="'.$cls.'" data-nav-link="1">...';
}
// $currentPath = strtok(dx_request_uri(), '?');
// 예: /admin/boards/5 → boards 메뉴 active
// /admin/boards?page=2 → 쿼리 제거 후 boards 메뉴 active
5. 상단바(Top Bar) UI
상단바는 position:sticky로 스크롤해도 항상 상단에 고정됩니다. backdrop-filter:blur(16px)로 반투명 유리 효과를 줍니다. 좌측 햄버거(모바일) + 브레드크럼, 우측 날짜 + 사이트보기 버튼으로 구성됩니다.
5.1 상단바 CSS
/* #adm_navi_top — 유리 효과 상단바 */
#adm_navi_top {
position:sticky; top:0; z-index:200;
height:58px;
background:rgba(255,255,255,.97); /* 97% 불투명 */
backdrop-filter:blur(16px) saturate(180%);
/* → 뒤 콘텐츠가 흐릿하게 비쳐 보이는 유리 효과 */
border-bottom:1px solid var(--dx-border);
box-shadow:var(--dx-shadow-sm);
display:flex; align-items:center;
padding:0 24px; gap:14px;
}
5.2 브레드크럼 구조
브레드크럼은 🏠 홈 아이콘 → 구분자(›) → 현재 페이지명 [→ 서브페이지명] 순으로 출력됩니다. $_admActionLabels 배열에서 action 키에 해당하는 한글 레이블을 찾아 표시합니다.
/* 브레드크럼 CSS */
.adm-breadcrumb {
flex:1; display:flex; align-items:center;
gap:6px; font-size:.82rem; color:var(--dx-text-4);
overflow:hidden; min-width:0;
}
.adm-breadcrumb-sep { font-size:.48rem; color:#dde2ec; }
.adm-breadcrumb-cur {
color:var(--dx-text-1); font-weight:700;
overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* PHP 출력 예시: /admin/boards/5 */
// 🏠 › 게시판 관리 › 5
// 레이블 매핑 배열 (25개 action)
$_admActionLabels = [
'dashboard' => '대시보드',
'boards' => '게시판 관리',
'members' => '회원 목록',
'settings' => '사이트 설정',
// ... 21개 더
];
5.3 상단바 우측 요소
| 요소 |
CSS 및 동작 |
| 현재 날짜/시간 |
.adm-topbar-time { font-size:.73rem; color:var(--dx-text-4) } PHP: date('Y.m.d H:i') — 페이지 로드 시점 기준 |
| "사이트 보기" 버튼 |
.adm-topbar-site-btn — 배경:#f0f2f8, 호버 시 Indigo 계열로 변환. target="_blank"로 새 탭에서 사이트 열기 |
| 햄버거 버튼 |
.adm-topbar-hamburger — 데스크톱: display:none, 모바일(≤768px): display:flex. 클릭 시 사이드바 .on 클래스 토글 |
6. 공통 UI 컴포넌트
admin/style.css에 정의된 재사용 가능한 UI 컴포넌트 클래스들입니다. 모든 관리자 모듈에서 일관된 디자인을 유지하기 위해 이 클래스들을 사용합니다.
6.1 카드 컴포넌트 (.adm-card)
/* 기본 카드 */
.adm-card {
background:var(--dx-surface); /* 흰색 */
border-radius:var(--dx-radius); /* 14px */
border:1px solid var(--dx-border);
overflow:hidden;
box-shadow:var(--dx-shadow-sm);
transition:box-shadow .2s;
}
.adm-card:hover { box-shadow:var(--dx-shadow); }
/* 카드 헤더 */
.adm-card-header {
display:flex; align-items:center; justify-content:space-between;
padding:15px 20px;
border-bottom:1px solid var(--dx-border-2);
}
.adm-card-title {
font-size:.88rem; font-weight:700;
color:var(--dx-text-1);
display:flex; align-items:center; gap:8px;
}
/* 카드 본문 */
.adm-card-body { padding:20px; }
/* 사용 예 */
<div class="adm-card">
<div class="adm-card-header">
<span class="adm-card-title">게시판 목록</span>
<a class="adm-card-link">더보기</a>
</div>
<div class="adm-card-body"> ... </div>
</div>
6.2 버튼 컴포넌트 (.adm-btn)
| 클래스 |
색상 계열 |
CSS 특징 |
| .adm-btn-primary |
Indigo (주요) |
background:var(--dx-primary); box-shadow:0 2px 8px var(--dx-primary-ring); 호버 시 translateY(-1px) |
| .adm-btn-secondary |
회색 (보조) |
background:var(--dx-bg); border:1.5px solid var(--dx-border); 호버 시 Indigo 계열로 변환 |
| .adm-btn-danger |
Red (삭제/위험) |
background:#fff1f2; color:#e11d48; border:#fecdd3 |
| .adm-btn-success |
Green (성공/확인) |
background:#f0fdf4; color:#16a34a; border:#bbf7d0 |
| .adm-btn-ghost |
투명 (텍스트형) |
background:transparent; 호버 시 배경색 추가 |
| .adm-btn-sm |
소형 |
padding:5px 11px; font-size:.77rem |
| .adm-btn-lg |
대형 |
padding:11px 24px; font-size:.9rem |
| .adm-btn-icon |
정사각형 아이콘 |
width:36px; height:36px; padding:0; justify-content:center |
6.3 입력 폼 컴포넌트
/* .adm-input — 텍스트 입력 필드 */
.adm-input {
width:100%; padding:9px 13px;
border:1.5px solid var(--dx-border);
border-radius:var(--dx-radius-sm); /* 9px */
font-size:.875rem;
background:var(--dx-surface);
transition:border-color .18s, box-shadow .18s;
}
.adm-input:focus {
border-color:var(--dx-primary);
box-shadow:0 0 0 3px var(--dx-primary-ring); /* 포커스 링 */
}
/* .adm-label — 폼 라벨 */
.adm-label {
display:block; font-size:.78rem; font-weight:700;
color:var(--dx-text-2); margin-bottom:6px;
}
/* .adm-field-hint — 도움말 텍스트 */
.adm-field-hint { font-size:.72rem; color:var(--dx-text-4); margin-top:5px; }
/* .adm-form-group — 폼 그룹 래퍼 */
.adm-form-group { margin-bottom:18px; }
/* 사용 예 */
<div class="adm-form-group">
<label class="adm-label">사이트명</label>
<input class="adm-input" type="text" name="site_name">
<span class="adm-field-hint">브라우저 타이틀에 표시됩니다.</span>
</div>
6.4 테이블 컴포넌트
/* .adm-table-wrap — 수평 스크롤 래퍼 */
.adm-table-wrap {
overflow-x:auto; -webkit-overflow-scrolling:touch;
border-radius:var(--dx-radius); border:1px solid var(--dx-border);
}
/* .adm-table — 기본 테이블 */
.adm-table { width:100%; border-collapse:collapse; }
.adm-table thead tr {
background:#f8fafd;
border-bottom:2px solid var(--dx-border);
}
.adm-table th {
padding:10px 16px; font-size:.7rem; font-weight:800;
color:var(--dx-text-3);
text-transform:uppercase; letter-spacing:.07em;
}
.adm-table td {
padding:11px 16px; font-size:.86rem;
border-bottom:1px solid var(--dx-border-2);
}
.adm-table tbody tr:hover { background:#f8fafd; }
6.5 알림 컴포넌트 (.adm-alert)
| 클래스 |
색상 |
CSS 배경/테두리/텍스트 |
| .adm-alert-success |
초록 (성공) |
background:#f0fdf4; border:#bbf7d0; color:#166534 |
| .adm-alert-error |
빨강 (오류) |
background:#fff1f2; border:#fecdd3; color:#be123c |
| .adm-alert-warn |
노랑 (경고) |
background:#fffbeb; border:#fde68a; color:#92400e |
| .adm-alert-info |
파랑 (안내) |
background:#eff6ff; border:#bfdbfe; color:#1e40af |
6.6 배지 컴포넌트 (.adm-badge)
| 클래스 |
색상 |
사용 예 |
| .adm-badge-primary |
Indigo |
활성화 상태, 현재 선택 |
| .adm-badge-success |
Green |
활성(active), 정상, 승인 |
| .adm-badge-danger |
Red |
비활성, 오류, 금지 |
| .adm-badge-warn |
Yellow |
경고, 검토 필요 |
| .adm-badge-neutral |
회색 |
기본, 일반, 미확인 |
6.7 탭 컴포넌트 (.adm-tabs)
/* .adm-tabs — 탭 컨테이너 */
.adm-tabs {
display:flex; gap:2px;
background:var(--dx-bg); border-radius:12px;
padding:4px; width:fit-content;
margin-bottom:20px;
}
/* .adm-tab — 개별 탭 */
.adm-tab {
padding:7px 16px; border-radius:9px;
font-size:.82rem; font-weight:600;
color:var(--dx-text-3);
transition:all .18s;
}
.adm-tab.active {
background:var(--dx-surface); /* 흰색 배경 */
color:var(--dx-primary); /* Indigo 텍스트 */
font-weight:700;
box-shadow:var(--dx-shadow-sm);
}
/* 사용 예 */
<div class="adm-tabs">
<a href="?tab=all" class="adm-tab active">전체</a>
<a href="?tab=active" class="adm-tab">활성</a>
<a href="?tab=inactive" class="adm-tab">비활성</a>
</div>
7. 대시보드 UI 구조
대시보드는 CSS Grid 기반 4개 영역으로 구성됩니다. KPI 카드(4열) → 서브 통계(3열) → 메인 콘텐츠(1fr + 300px) → 하단 2열 구조입니다.
7.1 대시보드 그리드 레이아웃
| 클래스 |
grid-template-columns |
내용 |
| .dash-kpi-grid |
repeat(4, 1fr) 태블릿:repeat(2,1fr) 모바일:1fr 1fr |
게시글·회원·댓글·오늘방문 4개 KPI 카드 |
| .dash-sub-grid |
repeat(3, 1fr) |
오늘고유방문·인기게시판·검색어 3개 미니 통계 |
| .dash-main-grid |
1fr 300px 태블릿:1fr |
최근 게시글 목록 + 최근 회원 목록 사이드 |
| .dash-bottom-grid |
1fr 1fr 모바일:1fr |
최근댓글 + 인기글 TOP 8 |
| 하단 2열 |
grid-cols-1 lg:grid-cols-2 |
빠른실행(2×3그리드) + 인기검색어(바 차트) |
7.2 KPI 카드 (.adm-kpi)
/* .adm-kpi — KPI 카드 */
.adm-kpi {
background:var(--dx-surface);
border-radius:var(--dx-radius);
padding:20px 22px;
display:flex; align-items:center; gap:16px;
position:relative; overflow:hidden;
transition:all .2s var(--dx-ease);
}
/* 호버 시 상단 컬러 바 나타남 */
.adm-kpi::before {
content:''; position:absolute;
top:0; left:0; right:0; height:3px;
background:linear-gradient(90deg, var(--dx-kpi-color), transparent);
opacity:0; transition:opacity .2s;
}
.adm-kpi:hover::before { opacity:1; }
/* KPI 아이콘 컨테이너 (48×48, 13px 반경) */
.adm-kpi-icon { width:48px; height:48px; border-radius:13px; }
/* KPI 숫자 — Space Grotesk 폰트 */
.adm-kpi-num {
font-family:'Space Grotesk', sans-serif;
font-size:1.9rem; font-weight:800;
color:var(--dx-text-1); line-height:1;
letter-spacing:-.02em;
}
/* KPI 트렌드 */
.adm-kpi-trend.up { color:var(--dx-success); }
.adm-kpi-trend.down { color:var(--dx-danger); }
.adm-kpi-trend.flat { color:var(--dx-text-4); }
각 KPI 카드는 PHP에서 $kpis 배열로 정의되어 foreach로 렌더링됩니다. 색상은 --dx-kpi-color CSS 변수를 인라인 style로 주입합니다.
7.3 미니 통계 카드 (.adm-mini-stat)
/* .adm-mini-stat — 소형 통계 카드 */
.adm-mini-stat {
background:var(--dx-surface);
border-radius:var(--dx-radius);
padding:14px 18px;
display:flex; align-items:center; gap:13px;
}
.adm-mini-stat-icon { width:38px; height:38px; border-radius:10px; }
.adm-mini-stat-num {
font-family:'Space Grotesk', sans-serif;
font-size:1.3rem; font-weight:800;
}
7.4 대시보드 게시글 행 (.dash-post-row)
/* .dash-post-row — CSS Grid 4열 레이아웃 */
.dash-post-row {
display:grid;
grid-template-columns:110px 1fr 56px 54px;
/* [게시판명] [제목] [조회수] [날짜] */
padding:9px 20px;
border-bottom:1px solid var(--dx-border-2);
}
.dash-post-board {
/* 게시판명 배지 — Indigo 계열 */
background:var(--dx-primary-light); color:var(--dx-primary);
font-size:.68rem; font-weight:700;
padding:2px 8px; border-radius:5px;
}
.dash-post-title:hover { color:var(--dx-primary); }
7.5 빠른 실행 그리드 (.dash-quick-grid)
/* .dash-quick-item — 빠른 실행 아이템 */
.dash-quick-item {
display:flex; align-items:center; gap:10px;
padding:11px 14px; border-radius:10px;
background:var(--dx-bg); border:1px solid var(--dx-border);
transition:all .18s var(--dx-ease);
}
.dash-quick-item:hover {
background:var(--dx-primary-light);
border-color:var(--dx-primary);
transform:translateX(2px); /* 오른쪽 슬라이드 효과 */
}
/* 빠른 실행 아이콘 — 호버 시 12도 회전 */
.group:hover .group-hover\:rotate-12 { transform:rotate(12deg); }
/* 6개 항목: 게시판생성 / 회원관리 / 통계보기 */
// 사이트설정 / 플러그인 / 테마설정 */
8. dxb-css v4.5.0 — 런타임 CSS 엔진
dxb-css는 Tailwind CSS와 동일한 유틸리티 클래스를 빌드 도구 없이 브라우저 런타임에서 처리합니다. PHP 서버만 있으면 되므로 저가형 호스팅에서도 동작합니다.
8.1 동작 원리
// dxb-css.js — 핵심 동작 (즉시 실행 함수)
(function() {
// ① <style id="dxb-css-dynamic"> 태그를 즉시 head에 삽입
// (스크립트 파싱 즉시 실행 → DOMContentLoaded 불필요)
const styleEl = document.createElement('style');
styleEl.id = 'dxb-css-dynamic';
document.head.appendChild(styleEl);
const generated = new Set(); // 이미 처리된 클래스 추적
// ② 클래스 이름 → CSS 규칙 변환
function processClass(cls) {
if (generated.has(cls)) return;
const rule = generateRule(cls);
if (rule) {
styleEl.textContent += rule;
generated.add(cls);
}
}
// ③ 요소의 클래스 목록 처리
function processElement(el) {
el.classList.forEach(processClass);
}
// ④ MutationObserver: DOM 변경 감지
// attributeFilter:['class'] — class 속성 변경만 감지
const observer = new MutationObserver(mutations => {
mutations.forEach(m => {
if (m.type === 'attributes') processElement(m.target);
if (m.type === 'childList') {
m.addedNodes.forEach(n => {
if (n.nodeType === 1) processElement(n);
});
}
});
});
observer.observe(document.body, {
subtree:true, childList:true,
attributes:true, attributeFilter:['class']
});
// ⑤ 초기 DOM 전체 스캔
document.querySelectorAll('[class]').forEach(processElement);
})();
8.2 지원 색상 팔레트
dxb-css.js는 다음 색상 팔레트를 지원합니다. bg-{color}-{shade}, text-{color}-{shade}, border-{color}-{shade} 형식으로 사용합니다.
| 계열 |
지원 Shade 목록 |
| slate |
50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950 |
| sky |
500, 600 |
| indigo |
100, 500, 600 |
| rose |
500 |
| emerald |
500 |
| amber |
400, 500 |
| blue |
100, 400, 500, 600, 700 |
| red |
50, 100, 400, 500, 600, 700 |
| orange |
400, 500 |
| green |
400, 500, 600 |
| teal |
500 |
| cyan |
500 |
| purple |
500 |
| pink |
500 |
| violet |
500, 600 |
8.3 반응형 프리픽스
// dxb-css 반응형 브레이크포인트
const screens = {
'sm': '640px', // @media (min-width: 640px)
'md': '768px', // @media (min-width: 768px)
'lg': '1024px', // @media (min-width: 1024px)
'xl': '1280px', // @media (min-width: 1280px)
'2xl':'1536px', // @media (min-width: 1536px)
};
// 사용 예: lg:grid-cols-4 → 1024px 이상에서 4열 그리드
// 사용 예: md:flex-row → 768px 이상에서 행 방향 flex
// 사용 예: sm:grid-cols-3 → 640px 이상에서 3열 그리드
9. 반응형 UI — 브레이크포인트별 동작
DXCMS 관리자 UI는 데스크톱(>1024px), 태블릿(769px~1024px), 모바일(≤768px), 소형 모바일(≤480px)의 4단계 반응형을 지원합니다.
9.1 브레이크포인트별 레이아웃 변화
| 브레이크포인트 |
범위 |
주요 UI 변화 |
| 데스크톱 |
>1024px |
사이드바 고정(240px) + margin-left:240px. 대시보드 4열 KPI + 3열 서브 + 2열 메인. 상단바 우측(날짜+버튼) 표시 |
| 태블릿 |
769~1024px |
사이드바 200px로 축소. margin-left:200px. 대시보드 2열 KPI. 본문 padding 18px. 사이드바 글씨 약간 축소 |
| 모바일 |
≤768px |
사이드바 숨김(translateX(-100%)). 햄버거 버튼 표시. 오버레이 배경(blur). 대시보드 1~2열. 상단바 우측 숨김. 테이블 수평 스크롤 |
| 소형 모바일 |
≤480px |
본문 padding 10px. 대시보드 전체 1열. KPI 숫자 1.4rem. 버튼/입력 패딩 축소. 탭 flex-wrap |
9.2 모바일 사이드바 토글
/* 모바일: 사이드바 슬라이드 애니메이션 */
#adm_navi_sidebar {
width:260px; /* 모바일은 데스크톱보다 약간 넓게 */
transform:translateX(-100%); /* 기본: 화면 밖 */
transition:transform .28s cubic-bezier(.4,0,.2,1),
box-shadow .28s;
}
#adm_navi_sidebar.on {
transform:translateX(0) !important; /* 열림 */
box-shadow:4px 0 32px rgba(0,0,0,.35);
}
/* JS: 햄버거 클릭 → 사이드바 토글 */
$('#adm_navi_btn').on('click touchend', function(e) {
e.preventDefault();
$('#adm_navi_sidebar').addClass('on');
$('#adm_navi_overlay').addClass('on');
$('body').css('overflow', 'hidden'); // 배경 스크롤 방지
});
/* 오버레이 클릭 / ESC → 사이드바 닫기 */
$(document).on('keydown', e => { if(e.key==='Escape') admClose(); });
9.3 모바일 유틸리티 클래스
| 클래스 |
동작 (≤768px) |
| .mob-stack |
flex-direction:column — 가로 배치를 세로로 변환 |
| .mob-full |
width:100% — 너비를 전체로 확장 |
| .mob-hide |
display:none — 모바일에서 숨김 |
| .mob-p0 |
padding:0 — 패딩 제거 |
| .mob-scroll |
overflow-x:auto — 가로 스크롤 활성화 (테이블 등) |
10. 그림자 시스템 및 트랜지션
10.1 그림자 3단계
| CSS 변수 |
값 |
사용처 |
| --dx-shadow-sm |
0 1px 3px rgba(15,23,42,.06), 0 1px 2px rgba(15,23,42,.04) |
기본 카드, 테이블, 입력 필드 |
| --dx-shadow |
0 4px 16px rgba(15,23,42,.08), 0 1px 4px rgba(15,23,42,.04) |
카드 호버, 활성 요소 |
| --dx-shadow-lg |
0 12px 40px rgba(15,23,42,.12), 0 4px 12px rgba(15,23,42,.06) |
모달, 드롭다운, 토스트 |
10.2 트랜지션 패턴
/* 표준 트랜지션 (모든 속성) */
transition: all .18s var(--dx-ease);
/* --dx-ease: cubic-bezier(.4,0,.2,1) — Material Design 표준 */
/* 색상만 트랜지션 (성능 최적화) */
transition: color .15s, background-color .15s;
/* 레이아웃 변경 시 (사이드바) */
transition: transform .28s var(--dx-ease), box-shadow .28s;
/* hover 마이크로 인터랙션 */
.adm-btn-primary:hover { transform:translateY(-1px); }
.adm-sb-link:hover { transform:translateX(2px); }
.adm-kpi:hover { transform:translateY(-1px); }
.dash-quick-item:hover { transform:translateX(2px); }
/* → 버튼: 위 1px 상승 / 메뉴•퀵항목: 오른쪽 2px 이동 */
11. 관리자 UI 구조 전체 요약
관리자 UI 구조도
┌─ admin/style.css (v3.2.0) ─────────────────────────────┐
│ 1. CSS 변수 (디자인 토큰) │
│ --dx-primary:#6366f1 --dx-bg:#f0f2f8 │
│ --dx-sidebar-w:240px --dx-topbar-h:58px │
│ │
│ 2. 레이아웃 │
│ #adm_navi_sidebar (fixed, 240px, 다크 그라데이션) │
│ #adm_navi_wrap (margin-left:240px) │
│ #adm_navi_top (sticky, 58px, 유리 효과) │
│ │
│ 3. 공통 컴포넌트 │
│ .adm-card .adm-btn-* .adm-input .adm-table │
│ .adm-alert-* .adm-badge-* .adm-tabs .adm-tab │
│ │
│ 4. 대시보드 전용 │
│ .dash-kpi-grid (4열) .dash-main-grid (1fr+300px) │
│ .adm-kpi .adm-mini-stat .dash-post-row │
│ │
│ 5. 반응형 │
│ >1024px: 데스크톱 풀레이아웃 │
│ 769~1024px: 태블릿 (사이드바 200px) │
│ ≤768px: 모바일 (사이드바 숨김, 햄버거 표시) │
│ ≤480px: 소형 모바일 (1열, 패딩 축소) │
└─────────────────────────────────────────────────────────┘
┌─ dxb-css.js (v4.5.0) ──────────────────────────────────┐
│ Tailwind 호환 런타임 CSS 엔진 │
│ MutationObserver → 동적 클래스 실시간 처리 │
│ 89개 규칙 + 컬러 팔레트 + 반응형 프리픽스 │
│ 빌드 도구 불필요 — PHP 서버만 있으면 동작 │
└─────────────────────────────────────────────────────────┘
┌─ 외부 리소스 ──────────────────────────────────────────┐
│ Pretendard : 한국어 UI 폰트 │
│ Space Grotesk: 숫자•영문 디스플레이 폰트 (KPI 수치) │
│ Font Awesome 6.5: 아이콘 라이브러리 │
│ jQuery 3.7.1 : 사이드바 토글 등 │
└─────────────────────────────────────────────────────────┘
✅ 핵심 설계 원칙 요약
1) 토큰 중심 디자인: 모든 색상•크기•간격은 CSS 변수(:root)로 중앙 관리
2) 이중 CSS 레이어: style.css(정적) + dxb-css.js(동적) 분리
3) 로드 순서: style.css → dxb-css.js 순서 필수 (CLS 방지)
4) 다크 사이드바 + 라이트 본문: 관리자 영역 시각적 구분
5) 유리 상단바: backdrop-filter:blur(16px)로 콘텐츠와 구분
6) Space Grotesk: KPI 숫자에 전용 폰트 적용 (가독성 극대화)
7) 마이크로 인터랙션: 버튼 -1px, 메뉴 +2px translateX 호버 효과
8) 4단계 반응형: 데스크톱>태블릿>모바일>소형 모바일 완전 지원