본문으로 건너뛰기

데이터 시각화 예제

이 예제는 문법과 렌더링 패턴을 설명합니다. 새 덱에는 현재 Canvas 정책과 테마 토큰을 적용합니다. 규모가 크거나 그룹이 있는 아키텍처에는 HTML/CSS를 사용합니다. 예제 지표는 설명용입니다.

Remarp에서 KPI 카드, 차트와 대시보드 레이아웃을 활용하는 데이터 시각화 기법을 설명합니다.

아래 Chart.js 예제에는 별도로 제공한 라이브러리가 필요하며, 발표 프레임워크에 내장되어 있지 않습니다. 해당 예제를 사용하기 전에 설정을 완료합니다.

디자인 시스템 원칙​

글자 계층​

요소크기굵기용도
대표 통계3.5rem+700핵심 지표 하나를 강조
KPI 값2.4rem700대시보드 카드 값
카드 제목1.1rem600섹션 제목
본문1rem400설명
레이블0.85rem500축 레이블, 캡션

의미별 색상​

목적변수용도
긍정--green (#00b894)상승 추세, 성공
부정--red (#e17055)하락 추세, 오류
경고--yellow (#fdcb6e)알림, 대기
주요 강조--accent (#6c5ce7)핵심 지표

전체 예제: 지표 대시보드​

---
remarp: true
version: 1
title: "Data Visualization Demo"
author: "Cloud Skills Team"
date: 2026-03-22
lang: en

blocks:
- name: data-viz
title: "Data Visualization"
duration: 8

theme:
accent: "#6c5ce7"

transition:
default: fade
duration: 300
---

---
remarp: true
block: data-viz
---

# Metrics Dashboard
Data visualization patterns in Remarp

:::notes
{timing: 30s}
Overview of dashboard capabilities.
:::

---

## KPI Cards

:::html
<div class="kpi-grid">
<div class="kpi-card fragment" data-fragment-index="1">
<div class="kpi-label">Monthly Active Users</div>
<div class="kpi-value">2.4M</div>
<div class="kpi-trend positive">+12.5%</div>
</div>
<div class="kpi-card fragment" data-fragment-index="2">
<div class="kpi-label">API Requests/sec</div>
<div class="kpi-value">45.2K</div>
<div class="kpi-trend positive">+8.3%</div>
</div>
<div class="kpi-card fragment" data-fragment-index="3">
<div class="kpi-label">P99 Latency</div>
<div class="kpi-value">142ms</div>
<div class="kpi-trend negative">+15ms</div>
</div>
<div class="kpi-card fragment" data-fragment-index="4">
<div class="kpi-label">Error Rate</div>
<div class="kpi-value">0.02%</div>
<div class="kpi-trend positive">-0.01%</div>
</div>
</div>
:::

:::css
.kpi-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1.5rem;
padding: 2rem;
}
.kpi-card {
background: var(--surface);
border-radius: 12px;
padding: 1.5rem;
text-align: center;
border: 1px solid var(--border);
}
.kpi-label {
font-size: 0.85rem;
color: var(--text-secondary);
margin-bottom: 0.5rem;
}
.kpi-value {
font-size: 2.4rem;
font-weight: 700;
font-family: var(--font-mono);
color: var(--text-primary);
}
.kpi-trend {
font-size: 0.9rem;
font-weight: 600;
margin-top: 0.5rem;
}
.kpi-trend.positive { color: var(--green); }
.kpi-trend.negative { color: var(--red); }
:::

:::notes
{timing: 2min}
KPI cards with semantic color coding for trends.
:::

---

## Hero Metric

:::html
<div class="hero-metric">
<div class="hero-label">Total Revenue</div>
<div class="hero-value">$4.2M</div>
<div class="hero-subtitle">Q1 2026</div>
<div class="hero-comparison">
<span class="positive">+24%</span> vs Q4 2025
</div>
</div>
:::

:::css
.hero-metric {
text-align: center;
padding: 4rem 2rem;
}
.hero-label {
font-size: 1.2rem;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.1em;
}
.hero-value {
font-size: 5rem;
font-weight: 700;
color: var(--accent-light);
text-shadow: 0 0 30px var(--accent-glow);
font-family: var(--font-mono);
margin: 0.5rem 0;
}
.hero-subtitle {
font-size: 1.5rem;
color: var(--text-muted);
}
.hero-comparison {
margin-top: 1rem;
font-size: 1.1rem;
}
.hero-comparison .positive { color: var(--green); font-weight: 600; }
:::

:::notes
{timing: 1min}
Hero metrics for maximum visual impact.
:::

---

## Chart.js Bar Chart

:::html
<div class="chart-container">
<canvas id="revenue-chart"></canvas>
</div>
:::

:::css
.chart-container {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
:::

:::script
const ctx = document.getElementById('revenue-chart').getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: 'Revenue ($K)',
data: [650, 720, 810, 780, 890, 950],
backgroundColor: 'rgba(108, 92, 231, 0.8)',
borderColor: 'rgba(108, 92, 231, 1)',
borderWidth: 1,
borderRadius: 4
}]
},
options: {
responsive: true,
plugins: {
legend: { display: false },
title: {
display: true,
text: 'Monthly Revenue 2026',
color: '#e0e0e0',
font: { size: 18, weight: '600' }
}
},
scales: {
y: {
beginAtZero: true,
grid: { color: 'rgba(255,255,255,0.1)' },
ticks: { color: '#a0a0a0' }
},
x: {
grid: { display: false },
ticks: { color: '#a0a0a0' }
}
}
}
});
:::

:::notes
{timing: 2min}
Chart.js integration for dynamic charts.
:::

---

## CSS-Only Progress Bars

:::html
<div class="progress-section">
<h3>Service Adoption</h3>

<div class="progress-item fragment" data-fragment-index="1">
<div class="progress-label">
<span>Lambda</span>
<span>92%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" style="--progress: 92%"></div>
</div>
</div>

<div class="progress-item fragment" data-fragment-index="2">
<div class="progress-label">
<span>DynamoDB</span>
<span>78%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" style="--progress: 78%"></div>
</div>
</div>

<div class="progress-item fragment" data-fragment-index="3">
<div class="progress-label">
<span>EKS</span>
<span>65%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" style="--progress: 65%"></div>
</div>
</div>

<div class="progress-item fragment" data-fragment-index="4">
<div class="progress-label">
<span>Step Functions</span>
<span>41%</span>
</div>
<div class="progress-bar">
<div class="progress-fill" style="--progress: 41%"></div>
</div>
</div>
</div>
:::

:::css
.progress-section {
max-width: 600px;
margin: 0 auto;
padding: 2rem;
}
.progress-section h3 {
margin-bottom: 2rem;
text-align: center;
}
.progress-item {
margin-bottom: 1.5rem;
}
.progress-label {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
font-size: 0.95rem;
}
.progress-bar {
height: 12px;
background: var(--surface);
border-radius: 6px;
overflow: hidden;
}
.progress-fill {
height: 100%;
width: var(--progress);
background: linear-gradient(90deg, var(--accent), var(--accent-light));
border-radius: 6px;
transition: width 0.8s ease-out;
}
:::

:::notes
{timing: 1min}
CSS-only progress bars with custom properties.
:::

---

## Comparison Table

:::html
<div class="comparison-table">
<table>
<thead>
<tr>
<th>Metric</th>
<th>Q4 2025</th>
<th>Q1 2026</th>
<th>Change</th>
</tr>
</thead>
<tbody>
<tr class="fragment" data-fragment-index="1">
<td>Users</td>
<td>2.1M</td>
<td>2.4M</td>
<td class="positive">+14.3%</td>
</tr>
<tr class="fragment" data-fragment-index="2">
<td>Requests/day</td>
<td>3.2B</td>
<td>3.9B</td>
<td class="positive">+21.9%</td>
</tr>
<tr class="fragment" data-fragment-index="3">
<td>Avg Latency</td>
<td>95ms</td>
<td>82ms</td>
<td class="positive">-13.7%</td>
</tr>
<tr class="fragment" data-fragment-index="4">
<td>Cost/request</td>
<td>$0.0012</td>
<td>$0.0009</td>
<td class="positive">-25%</td>
</tr>
</tbody>
</table>
</div>
:::

:::css
.comparison-table {
max-width: 700px;
margin: 0 auto;
padding: 2rem;
}
.comparison-table table {
width: 100%;
border-collapse: collapse;
}
.comparison-table th,
.comparison-table td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid var(--border);
}
.comparison-table th {
font-weight: 600;
color: var(--text-secondary);
font-size: 0.9rem;
text-transform: uppercase;
}
.comparison-table td.positive { color: var(--green); font-weight: 600; }
.comparison-table td.negative { color: var(--red); font-weight: 600; }
:::

:::notes
{timing: 1min}
Tabular data with semantic color coding.
:::

---

## Mini Sparklines (CSS-only)

:::html
<div class="sparkline-grid">
<div class="sparkline-card">
<div class="sparkline-header">
<span class="sparkline-label">CPU Usage</span>
<span class="sparkline-value">68%</span>
</div>
<div class="sparkline" style="--v1:40%; --v2:55%; --v3:62%; --v4:58%; --v5:72%; --v6:68%"></div>
</div>
<div class="sparkline-card">
<div class="sparkline-header">
<span class="sparkline-label">Memory</span>
<span class="sparkline-value">82%</span>
</div>
<div class="sparkline" style="--v1:75%; --v2:78%; --v3:80%; --v4:79%; --v5:81%; --v6:82%"></div>
</div>
<div class="sparkline-card">
<div class="sparkline-header">
<span class="sparkline-label">Network I/O</span>
<span class="sparkline-value">1.2GB/s</span>
</div>
<div class="sparkline" style="--v1:30%; --v2:45%; --v3:60%; --v4:55%; --v5:70%; --v6:65%"></div>
</div>
</div>
:::

:::css
.sparkline-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
padding: 2rem;
}
.sparkline-card {
background: var(--surface);
border-radius: 8px;
padding: 1rem;
}
.sparkline-header {
display: flex;
justify-content: space-between;
margin-bottom: 0.75rem;
}
.sparkline-label { font-size: 0.85rem; color: var(--text-secondary); }
.sparkline-value { font-weight: 600; font-family: var(--font-mono); }
.sparkline {
display: flex;
align-items: flex-end;
gap: 4px;
height: 40px;
}
.sparkline::before,
.sparkline::after,
.sparkline span { content: ''; }
.sparkline {
--bar-color: var(--accent);
}
.sparkline::before { flex: 1; height: var(--v1); background: var(--bar-color); border-radius: 2px; }
.sparkline::after { flex: 1; height: var(--v6); background: var(--bar-color); border-radius: 2px; }
/* Additional bars via pseudo-elements on wrapper */
:::

:::notes
{timing: 1min}
Lightweight CSS sparklines for quick metrics overview.
:::

KPI 카드 패턴​

기본 KPI 카드​

<div class="kpi-card">
<div class="kpi-label">Metric Name</div>
<div class="kpi-value">123.4K</div>
<div class="kpi-trend positive">+5.2%</div>
</div>
.kpi-card {
background: var(--surface);
border-radius: 12px;
padding: 1.5rem;
text-align: center;
}
.kpi-value {
font-size: 2.4rem;
font-weight: 700;
font-family: var(--font-mono);
}
.kpi-trend.positive { color: var(--green); }
.kpi-trend.negative { color: var(--red); }

아이콘이 있는 KPI​

<div class="kpi-card">
<div class="kpi-icon">
<img src="../common/aws-icons/services/Arch_AWS-Lambda_48.svg" alt="Lambda">
</div>
<div class="kpi-label">Lambda Invocations</div>
<div class="kpi-value">12.8M</div>
<div class="kpi-sublabel">/day</div>
</div>

KPI 그리드 레이아웃​

.kpi-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
}

Chart.js 통합​

설정​

Chart.js는 별도로 준비해야 하는 의존성입니다. 검토한 특정 버전의 UMD 빌드를 제공하고, 차트를 초기화하기 전에 원본 Remarp 문서에서 실제 자산 URL을 참조합니다. 아래 경로는 직접 제공할 자산의 예시 경로이며, 생성기가 Chart.js를 자동으로 복사하거나 불러오지는 않습니다. 공식 통합 가이드를 참고합니다.

:::html
<!-- Supply this pinned, reviewed UMD asset at the URL used by your exported deck. -->
<script src="assets/chart.umd.min.js"></script>
:::

:::script
if (typeof Chart !== 'function') {
throw new Error('Load the supplied Chart.js UMD asset before initializing charts.');
}
:::

막대 차트​

new Chart(ctx, {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar'],
datasets: [{
label: 'Revenue',
data: [650, 720, 810],
backgroundColor: 'rgba(108, 92, 231, 0.8)',
borderRadius: 4
}]
},
options: {
responsive: true,
scales: {
y: { beginAtZero: true }
}
}
});

선 차트​

new Chart(ctx, {
type: 'line',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
datasets: [{
label: 'Requests',
data: [1200, 1900, 1500, 2100, 1800],
borderColor: 'rgba(108, 92, 231, 1)',
tension: 0.3,
fill: true,
backgroundColor: 'rgba(108, 92, 231, 0.1)'
}]
}
});

도넛 차트​

new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Lambda', 'EC2', 'EKS', 'Fargate'],
datasets: [{
data: [45, 25, 20, 10],
backgroundColor: [
'#6c5ce7', '#FF9900', '#00b894', '#e17055'
]
}]
},
options: {
cutout: '60%'
}
});

CSS만 사용하는 차트​

진행률 표시줄​

<div class="progress-bar">
<div class="progress-fill" style="--progress: 75%"></div>
</div>
.progress-bar {
height: 12px;
background: var(--surface);
border-radius: 6px;
}
.progress-fill {
height: 100%;
width: var(--progress);
background: linear-gradient(90deg, var(--accent), var(--accent-light));
transition: width 0.8s ease-out;
}

가로 막대 차트(CSS Grid)​

<div class="bar-chart">
<div class="bar-row">
<span class="bar-label">Lambda</span>
<div class="bar" style="--width: 92%">92%</div>
</div>
<div class="bar-row">
<span class="bar-label">EKS</span>
<div class="bar" style="--width: 65%">65%</div>
</div>
</div>
.bar-chart { display: flex; flex-direction: column; gap: 1rem; }
.bar-row { display: grid; grid-template-columns: 100px 1fr; align-items: center; gap: 1rem; }
.bar {
height: 24px;
width: var(--width);
background: var(--accent);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 0.5rem;
font-size: 0.8rem;
}

권장 사항​

  1. 의미별 색상을 사용합니다 — 긍정은 녹색, 부정은 빨간색으로 일관되게 표시합니다.
  2. 데이터 밀도를 제한합니다 — 슬라이드당 KPI 카드는 최대 4-6개로 제한합니다.
  3. 맥락을 제공합니다 — 추세, 비교나 기간을 표시합니다.
  4. 반응형 그리드를 사용합니다 — auto-fit과 minmax()로 유연한 레이아웃을 구성합니다.
  5. 점진적으로 표시합니다 — class="fragment"와 data-fragment-index로 대시보드를 단계별로 보여 줍니다.
  6. 글자 스타일을 통일합니다 — 글자 크기는 계층 표를 따릅니다.
  7. 다크 테마를 고려합니다 — 색상을 직접 고정하지 말고 CSS 변수를 사용합니다.