Table
정렬·선택이 필요 없는 단순 표입니다. 상세 정보(키-값), 비교표, 요약 통계에 씁니다.
1. Default
머리글과 본문만 둔 기본 표입니다.
| 그룹 | 에이전트 |
|---|---|
| 영업팀 | 312 |
| 개발팀 | 184 |
HTML
<div class="tbl-wrap" style="max-width:480px">
<table class="tbl">
<thead><tr><th>그룹</th><th class="num">에이전트</th></tr></thead>
<tbody>
<tr><td>영업팀</td><td class="num">312</td></tr>
<tr><td>개발팀</td><td class="num">184</td></tr>
</tbody>
</table>
</div>CSS · .tbl-wrap, .tbl
/* JS Design System v0.6 · .tbl-wrap, .tbl · 토큰(var(--*))은 assets/style.css :root 참고 */
.tbl-wrap{overflow-x:auto;border:1px solid var(--border-default);border-radius:var(--radius-lg);background:var(--bg-surface);width:100%}
.tbl{width:100%;border-collapse:collapse;font-size:14px;margin:0}
.tbl th{text-align:left;font-weight:600;color:var(--text-tertiary);font-size:12px;height:44px;padding:0 16px;border-bottom:1px solid var(--border-default);white-space:nowrap;background:var(--bg-subtle)}
.tbl td{height:52px;padding:12px 16px;border-bottom:1px solid var(--border-default);vertical-align:middle}
.tbl tbody tr:last-child td{border-bottom:0}
.tbl tbody tr:hover td{background:var(--bg-subtle)}
.tbl tr.on td{background:var(--accent-subtle)}
.tbl tr.disabled td{color:var(--text-disabled)}
.tbl.compact td{height:44px;padding:8px 16px;font-size:14px}
.tbl.compact th{height:40px}
.tbl.zebra tbody tr:nth-child(even) td{background:var(--bg-subtle)}
.tbl th.sortable{cursor:pointer;user-select:none}
.tbl th.sortable::after{content:"";display:inline-block;width:14px;height:14px;margin-left:6px;vertical-align:-3px;opacity:.45;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sortable:hover{color:var(--text-primary)}
.tbl th.sorted{color:var(--accent-text)}
.tbl th.sorted::after{opacity:1;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sorted.desc::after{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl .num{text-align:right;}
.tbl td svg{vertical-align:middle}
.tbl .check{width:44px;padding-right:0}
.tbl .check .checkbox{vertical-align:middle}
.tbl .actions{text-align:right;white-space:nowrap}
.tbl .actions .btn{height:32px;padding:0 10px;font-size:12px}
.tbl.kv th{width:200px;height:auto;padding:12px 16px;font-size:14px;color:var(--text-secondary);font-weight:500;border-right:1px solid var(--border-default);white-space:normal;vertical-align:top}
.tbl.kv td{height:auto}
.tbl td.empty{display:table-cell;text-align:center;color:var(--text-tertiary);height:auto;padding:24px 16px;font-size:14px;border:none;border-radius:0;background:transparent}
.tbl .link{color:var(--accent-text);text-decoration:none;font-weight:500}
.tbl .link:hover{text-decoration:underline}React · @jiran/ds-react
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@jiran/ds-react";
export default function Example() {
return (
<Table wrapStyle={{ maxWidth: 480 }}>
<TableHead>
<TableRow>
<TableHeader>그룹</TableHeader>
<TableHeader num>에이전트</TableHeader>
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>영업팀</TableCell>
<TableCell num>312</TableCell>
</TableRow>
<TableRow>
<TableCell>개발팀</TableCell>
<TableCell num>184</TableCell>
</TableRow>
</TableBody>
</Table>
);
}2. Simple
| 그룹 | 에이전트 | 정책 | 최근 배포 |
|---|---|---|---|
| 영업팀 | 312 | 8 | 2026-09-06 |
| 개발팀 | 184 | 11 | 2026-09-06 |
| 인프라팀 | 48 | 14 | 2026-09-02 |
HTML
<div class="tbl-wrap" style="max-width:640px">
<table class="tbl">
<thead><tr><th>그룹</th><th class="num">에이전트</th><th class="num">정책</th><th>최근 배포</th></tr></thead>
<tbody>
<tr><td>영업팀</td><td class="num">312</td><td class="num">8</td><td>2026-09-06</td></tr>
<tr><td>개발팀</td><td class="num">184</td><td class="num">11</td><td>2026-09-06</td></tr>
<tr><td>인프라팀</td><td class="num">48</td><td class="num">14</td><td>2026-09-02</td></tr>
</tbody>
</table>
</div>CSS · .tbl-wrap, .tbl
/* JS Design System v0.6 · .tbl-wrap, .tbl · 토큰(var(--*))은 assets/style.css :root 참고 */
.tbl-wrap{overflow-x:auto;border:1px solid var(--border-default);border-radius:var(--radius-lg);background:var(--bg-surface);width:100%}
.tbl{width:100%;border-collapse:collapse;font-size:14px;margin:0}
.tbl th{text-align:left;font-weight:600;color:var(--text-tertiary);font-size:12px;height:44px;padding:0 16px;border-bottom:1px solid var(--border-default);white-space:nowrap;background:var(--bg-subtle)}
.tbl td{height:52px;padding:12px 16px;border-bottom:1px solid var(--border-default);vertical-align:middle}
.tbl tbody tr:last-child td{border-bottom:0}
.tbl tbody tr:hover td{background:var(--bg-subtle)}
.tbl tr.on td{background:var(--accent-subtle)}
.tbl tr.disabled td{color:var(--text-disabled)}
.tbl.compact td{height:44px;padding:8px 16px;font-size:14px}
.tbl.compact th{height:40px}
.tbl.zebra tbody tr:nth-child(even) td{background:var(--bg-subtle)}
.tbl th.sortable{cursor:pointer;user-select:none}
.tbl th.sortable::after{content:"";display:inline-block;width:14px;height:14px;margin-left:6px;vertical-align:-3px;opacity:.45;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sortable:hover{color:var(--text-primary)}
.tbl th.sorted{color:var(--accent-text)}
.tbl th.sorted::after{opacity:1;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sorted.desc::after{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl .num{text-align:right;}
.tbl td svg{vertical-align:middle}
.tbl .check{width:44px;padding-right:0}
.tbl .check .checkbox{vertical-align:middle}
.tbl .actions{text-align:right;white-space:nowrap}
.tbl .actions .btn{height:32px;padding:0 10px;font-size:12px}
.tbl.kv th{width:200px;height:auto;padding:12px 16px;font-size:14px;color:var(--text-secondary);font-weight:500;border-right:1px solid var(--border-default);white-space:normal;vertical-align:top}
.tbl.kv td{height:auto}
.tbl td.empty{display:table-cell;text-align:center;color:var(--text-tertiary);height:auto;padding:24px 16px;font-size:14px;border:none;border-radius:0;background:transparent}
.tbl .link{color:var(--accent-text);text-decoration:none;font-weight:500}
.tbl .link:hover{text-decoration:underline}React · @jiran/ds-react
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@jiran/ds-react";
const ROWS = [
["영업팀", "312", "8", "2026-09-06"],
["개발팀", "184", "11", "2026-09-06"],
["인프라팀", "48", "14", "2026-09-02"],
];
export default function Example() {
return (
<Table wrapStyle={{ maxWidth: 640 }}>
<TableHead>
<TableRow>
<TableHeader>그룹</TableHeader>
<TableHeader num>에이전트</TableHeader>
<TableHeader num>정책</TableHeader>
<TableHeader>최근 배포</TableHeader>
</TableRow>
</TableHead>
<TableBody>
{ROWS.map(([g, a, p, d]) => (
<TableRow key={g}>
<TableCell>{g}</TableCell>
<TableCell num>{a}</TableCell>
<TableCell num>{p}</TableCell>
<TableCell>{d}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}3. Key–Value
상세 패널의 속성 표. th 가 키.
| 정책 ID | POL-2041 |
|---|---|
| 이름 | 외부 USB 차단 |
| 적용 그룹 | 전체 (1,284대) |
| 상태 | 사용 중 |
| 최근 수정 | 2026-09-06 14:20 · admin@jiran.com |
HTML
<div class="tbl-wrap" style="max-width:560px">
<table class="tbl kv">
<tbody>
<tr><th>정책 ID</th><td>POL-2041</td></tr>
<tr><th>이름</th><td>외부 USB 차단</td></tr>
<tr><th>적용 그룹</th><td>전체 (1,284대)</td></tr>
<tr><th>상태</th><td><span class="indicator ok">사용 중</span></td></tr>
<tr><th>최근 수정</th><td>2026-09-06 14:20 · admin@jiran.com</td></tr>
</tbody>
</table>
</div>CSS · .tbl-wrap, .tbl
/* JS Design System v0.6 · .tbl-wrap, .tbl · 토큰(var(--*))은 assets/style.css :root 참고 */
.tbl-wrap{overflow-x:auto;border:1px solid var(--border-default);border-radius:var(--radius-lg);background:var(--bg-surface);width:100%}
.tbl{width:100%;border-collapse:collapse;font-size:14px;margin:0}
.tbl th{text-align:left;font-weight:600;color:var(--text-tertiary);font-size:12px;height:44px;padding:0 16px;border-bottom:1px solid var(--border-default);white-space:nowrap;background:var(--bg-subtle)}
.tbl td{height:52px;padding:12px 16px;border-bottom:1px solid var(--border-default);vertical-align:middle}
.tbl tbody tr:last-child td{border-bottom:0}
.tbl tbody tr:hover td{background:var(--bg-subtle)}
.tbl tr.on td{background:var(--accent-subtle)}
.tbl tr.disabled td{color:var(--text-disabled)}
.tbl.compact td{height:44px;padding:8px 16px;font-size:14px}
.tbl.compact th{height:40px}
.tbl.zebra tbody tr:nth-child(even) td{background:var(--bg-subtle)}
.tbl th.sortable{cursor:pointer;user-select:none}
.tbl th.sortable::after{content:"";display:inline-block;width:14px;height:14px;margin-left:6px;vertical-align:-3px;opacity:.45;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sortable:hover{color:var(--text-primary)}
.tbl th.sorted{color:var(--accent-text)}
.tbl th.sorted::after{opacity:1;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sorted.desc::after{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl .num{text-align:right;}
.tbl td svg{vertical-align:middle}
.tbl .check{width:44px;padding-right:0}
.tbl .check .checkbox{vertical-align:middle}
.tbl .actions{text-align:right;white-space:nowrap}
.tbl .actions .btn{height:32px;padding:0 10px;font-size:12px}
.tbl.kv th{width:200px;height:auto;padding:12px 16px;font-size:14px;color:var(--text-secondary);font-weight:500;border-right:1px solid var(--border-default);white-space:normal;vertical-align:top}
.tbl.kv td{height:auto}
.tbl td.empty{display:table-cell;text-align:center;color:var(--text-tertiary);height:auto;padding:24px 16px;font-size:14px;border:none;border-radius:0;background:transparent}
.tbl .link{color:var(--accent-text);text-decoration:none;font-weight:500}
.tbl .link:hover{text-decoration:underline}React · @jiran/ds-react
import { Indicator, Table, TableBody, TableCell, TableHeader, TableRow } from "@jiran/ds-react";
export default function Example() {
return (
<Table kv wrapStyle={{ maxWidth: 560 }}>
<TableBody>
<TableRow><TableHeader>정책 ID</TableHeader><TableCell>POL-2041</TableCell></TableRow>
<TableRow><TableHeader>이름</TableHeader><TableCell>외부 USB 차단</TableCell></TableRow>
<TableRow><TableHeader>적용 그룹</TableHeader><TableCell>전체 (1,284대)</TableCell></TableRow>
<TableRow><TableHeader>상태</TableHeader><TableCell><Indicator tone="ok">사용 중</Indicator></TableCell></TableRow>
<TableRow><TableHeader>최근 수정</TableHeader><TableCell>2026-09-06 14:20 · admin@jiran.com</TableCell></TableRow>
</TableBody>
</Table>
);
}4. Zebra / Compact
긴 비교표는 줄무늬로 행 추적을 돕습니다.
| 기능 | Standard | Enterprise |
|---|---|---|
| 실시간 보호 | ||
| USB 제어 | ||
| 행위 기반 탐지 | — | |
| 감사 로그 보관 | 30일 | 1년 |
| SIEM 연동 | — |
HTML
<div class="tbl-wrap" style="max-width:640px">
<table class="tbl compact zebra">
<thead><tr><th>기능</th><th>Standard</th><th>Enterprise</th></tr></thead>
<tbody>
<tr><td>실시간 보호</td><td><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12l5 5l10 -10"/></svg></td><td><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12l5 5l10 -10"/></svg></td></tr>
<tr><td>USB 제어</td><td><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12l5 5l10 -10"/></svg></td><td><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12l5 5l10 -10"/></svg></td></tr>
<tr><td>행위 기반 탐지</td><td>—</td><td><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12l5 5l10 -10"/></svg></td></tr>
<tr><td>감사 로그 보관</td><td>30일</td><td>1년</td></tr>
<tr><td>SIEM 연동</td><td>—</td><td><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12l5 5l10 -10"/></svg></td></tr>
</tbody>
</table>
</div>CSS · .tbl-wrap, .tbl
/* JS Design System v0.6 · .tbl-wrap, .tbl · 토큰(var(--*))은 assets/style.css :root 참고 */
.tbl-wrap{overflow-x:auto;border:1px solid var(--border-default);border-radius:var(--radius-lg);background:var(--bg-surface);width:100%}
.tbl{width:100%;border-collapse:collapse;font-size:14px;margin:0}
.tbl th{text-align:left;font-weight:600;color:var(--text-tertiary);font-size:12px;height:44px;padding:0 16px;border-bottom:1px solid var(--border-default);white-space:nowrap;background:var(--bg-subtle)}
.tbl td{height:52px;padding:12px 16px;border-bottom:1px solid var(--border-default);vertical-align:middle}
.tbl tbody tr:last-child td{border-bottom:0}
.tbl tbody tr:hover td{background:var(--bg-subtle)}
.tbl tr.on td{background:var(--accent-subtle)}
.tbl tr.disabled td{color:var(--text-disabled)}
.tbl.compact td{height:44px;padding:8px 16px;font-size:14px}
.tbl.compact th{height:40px}
.tbl.zebra tbody tr:nth-child(even) td{background:var(--bg-subtle)}
.tbl th.sortable{cursor:pointer;user-select:none}
.tbl th.sortable::after{content:"";display:inline-block;width:14px;height:14px;margin-left:6px;vertical-align:-3px;opacity:.45;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sortable:hover{color:var(--text-primary)}
.tbl th.sorted{color:var(--accent-text)}
.tbl th.sorted::after{opacity:1;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sorted.desc::after{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl .num{text-align:right;}
.tbl td svg{vertical-align:middle}
.tbl .check{width:44px;padding-right:0}
.tbl .check .checkbox{vertical-align:middle}
.tbl .actions{text-align:right;white-space:nowrap}
.tbl .actions .btn{height:32px;padding:0 10px;font-size:12px}
.tbl.kv th{width:200px;height:auto;padding:12px 16px;font-size:14px;color:var(--text-secondary);font-weight:500;border-right:1px solid var(--border-default);white-space:normal;vertical-align:top}
.tbl.kv td{height:auto}
.tbl td.empty{display:table-cell;text-align:center;color:var(--text-tertiary);height:auto;padding:24px 16px;font-size:14px;border:none;border-radius:0;background:transparent}
.tbl .link{color:var(--accent-text);text-decoration:none;font-weight:500}
.tbl .link:hover{text-decoration:underline}React · @jiran/ds-react
import { Icon, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@jiran/ds-react";
const yes = <Icon name="check" size={16} />;
const ROWS: [string, React.ReactNode, React.ReactNode][] = [
["실시간 보호", yes, yes],
["USB 제어", yes, yes],
["행위 기반 탐지", "—", yes],
["감사 로그 보관", "30일", "1년"],
["SIEM 연동", "—", yes],
];
export default function Example() {
return (
<Table compact zebra wrapStyle={{ maxWidth: 640 }}>
<TableHead>
<TableRow><TableHeader>기능</TableHeader><TableHeader>Standard</TableHeader><TableHeader>Enterprise</TableHeader></TableRow>
</TableHead>
<TableBody>
{ROWS.map(([f, s, e]) => (
<TableRow key={f}><TableCell>{f}</TableCell><TableCell>{s}</TableCell><TableCell>{e}</TableCell></TableRow>
))}
</TableBody>
</Table>
);
}Props
HTML 에서는 클래스와 속성으로, React(@jiran/ds-react)에서는 같은 이름의 prop(variant · size …)으로 변형·상태를 지정합니다.
| Prop / Class | Type · Values | Default | Description |
|---|---|---|---|
| .tbl-wrap | container | — | 보더 + radius + 스크롤 |
| .tbl | table | — | 기본 표 |
| .kv | boolean | false | 키-값 표(th 폭 200, 우측 보더) |
| .zebra / .compact | boolean | false | 줄무늬 / 행 44 |
| td.num | cell | — | 숫자 우측 정렬 |
Usage
React: @jiran/ds-react 패키지를 설치하고 style.css 를 한 번 import 하면 위 React 탭 코드를 그대로 쓸 수 있습니다(React Package). HTML: assets/style.css 를 연결하고(일부만 필요하면 아래 컴포넌트 CSS 복사), 동작이 필요하면 assets/ds.js 를 함께 넣습니다 — 이 페이지의 프리뷰가 그 스크립트로 동작합니다. 색은 전부 토큰(var(--accent) 등)을 참조하므로 --accent-* 만 제품 컬러로 바꾸면 됩니다.
React @jiran/ds-react
npm i @jiran/ds-react
// main.tsx — 앱 진입점에서 한 번
import "@jiran/ds-react/style.css";
// 컴포넌트
import { Table, TableHead, TableBody, TableRow, TableHeader, TableCell } from "@jiran/ds-react";HTML
<!-- 1) 토큰 + 전체 컴포넌트 스타일 한 번에 연결 -->
<link rel="stylesheet" href="assets/style.css">
<!-- 동작(드롭다운·탭·달력·표 정렬/선택·토스트 등) — 순수 JS 한 파일. React 제품은 불필요 -->
<script src="assets/ds.js" defer></script>
<!-- 2) 또는 아래 "Component CSS" 만 프로젝트 CSS 에 붙이고,
:root 토큰은 Foundations › Design Token 에서 복사 -->Component CSS .tbl-wrap, .tbl
/* JS Design System v0.6 · .tbl-wrap, .tbl · 토큰(var(--*))은 assets/style.css :root 참고 */
.tbl-wrap{overflow-x:auto;border:1px solid var(--border-default);border-radius:var(--radius-lg);background:var(--bg-surface);width:100%}
.tbl{width:100%;border-collapse:collapse;font-size:14px;margin:0}
.tbl th{text-align:left;font-weight:600;color:var(--text-tertiary);font-size:12px;height:44px;padding:0 16px;border-bottom:1px solid var(--border-default);white-space:nowrap;background:var(--bg-subtle)}
.tbl td{height:52px;padding:12px 16px;border-bottom:1px solid var(--border-default);vertical-align:middle}
.tbl tbody tr:last-child td{border-bottom:0}
.tbl tbody tr:hover td{background:var(--bg-subtle)}
.tbl tr.on td{background:var(--accent-subtle)}
.tbl tr.disabled td{color:var(--text-disabled)}
.tbl.compact td{height:44px;padding:8px 16px;font-size:14px}
.tbl.compact th{height:40px}
.tbl.zebra tbody tr:nth-child(even) td{background:var(--bg-subtle)}
.tbl th.sortable{cursor:pointer;user-select:none}
.tbl th.sortable::after{content:"";display:inline-block;width:14px;height:14px;margin-left:6px;vertical-align:-3px;opacity:.45;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M3 9l4 -4l4 4m-4 -4v14%22 /%3E%3Cpath d=%22M21 15l-4 4l-4 -4m4 4v-14%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sortable:hover{color:var(--text-primary)}
.tbl th.sorted{color:var(--accent-text)}
.tbl th.sorted::after{opacity:1;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 11l-6 -6%22 /%3E%3Cpath d=%22M6 11l6 -6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl th.sorted.desc::after{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2224%22 height=%2224%22 viewBox=%220 0 24 24%22 fill=%22none%22 stroke=%22black%22 stroke-width=%222%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22 %3E%3Cpath d=%22M12 5l0 14%22 /%3E%3Cpath d=%22M18 13l-6 6%22 /%3E%3Cpath d=%22M6 13l6 6%22 /%3E%3C/svg%3E") center/contain no-repeat}
.tbl .num{text-align:right;}
.tbl td svg{vertical-align:middle}
.tbl .check{width:44px;padding-right:0}
.tbl .check .checkbox{vertical-align:middle}
.tbl .actions{text-align:right;white-space:nowrap}
.tbl .actions .btn{height:32px;padding:0 10px;font-size:12px}
.tbl.kv th{width:200px;height:auto;padding:12px 16px;font-size:14px;color:var(--text-secondary);font-weight:500;border-right:1px solid var(--border-default);white-space:normal;vertical-align:top}
.tbl.kv td{height:auto}
.tbl td.empty{display:table-cell;text-align:center;color:var(--text-tertiary);height:auto;padding:24px 16px;font-size:14px;border:none;border-radius:0;background:transparent}
.tbl .link{color:var(--accent-text);text-decoration:none;font-weight:500}
.tbl .link:hover{text-decoration:underline}