mviz은(는) 무엇을 하나요?
깔끔하고 데이터 중심의 차트와 대시보드를 간결한 JSON 스펙 또는 마크다운으로 생성합니다. 불필요한 차트 장식, 격자선, 장식 요소를 최소화하여 데이터-잉크 비율을 최대화합니다. 16열 그리드 레이아웃 시스템을 사용합니다.
설정
설치가 필요 없습니다. npx -y -q mviz를 사용하면 npm에서 자동으로 다운로드됩니다. -q 플래그는 npm 출력을 줄이면서 린트 오류는 계속 표시합니다.
빠른 반복 사용을 위해 전역 설치: npm install -g mviz
이 스킬이 하는 일
mviz는 두 가지입니다:
- 스펙 언어 — 구성 요소(차트, KPI, 표, 메모 등)를 설명하는 펜스 코드 블록이 포함된 마크다운입니다. 하나의 마크다운 파일(또는 단일 JSON 스펙)이 전체 시각화를 설명합니다.
- 렌더러 세트 — 해당 스펙을 다양한 표시 컨텍스트에 맞게 HTML로 변환합니다. 현재 두 가지가 있습니다:
visualize:show_widget(인라인) — claude.ai에서 시각화 도구를 사용할 수 있는 경우, mviz 스펙을widget_codeHTML 조각으로 렌더링합니다(claude.ai의 디자인 시스템 사용: Chart.js,var(--color-*)토큰). 위젯이 대화에 인라인으로 나타납니다.- mviz CLI (독립형) —
mviz dashboard.md -o report.html은 mviz 자체 디자인 시스템(mdsinabox 테마, ECharts)을 사용하여 완전한 HTML 문서를 생성합니다. 다운로드, iframe 타일, 인쇄/PDF에 적합합니다.
mviz 마크다운 스펙은 표준입니다. 렌더러는 시각화가 표시될 위치에 따라 선택됩니다. 동일한 스펙, 두 가지 렌더링. 타사에서 스펙을 변경하지 않고 다른 렌더러(Chart.js 기반 CLI, Slack 테마 렌더러 등)를 구축할 수 있습니다.
렌더러 선택
항상 mviz 마크다운 스펙을 먼저 작성하고, 인라인으로 렌더링할 때도 마찬가지입니다. 스펙은 표준 아티팩트입니다. 응답에서 펜스 코드 블록으로 내보내 사용자가 나중에 복사/재사용/CLI로 파이프할 수 있도록 합니다. 그런 다음 요청에 맞는 렌더러로 렌더링합니다.
렌더링하기 전에 어떤 렌더러가 적합한지 결정하고 추론을 명시하여 사용자가 수정할 수 있도록 합니다. 몇 가지 신호:
인라인 (visualize:show_widget):
- "X를 보여줘" / "X는 어땠어" / "X가 어떻게 변했는지" / "렌더링"
- 주변 산문과 함께 흐르는 작은 시각화(일반적으로 1–4개 구성 요소)
- 사용자가 데이터를 탐색 중이며 공유할 준비를 하는 것이 아님
- 이 대화에서
visualize:show_widget을 사용할 수 있음
독립형 (mviz CLI):
- "보고서를 만들어 줘" / "파일을 보내줘" / "PDF로 내보내기" / "저장"
- 여러 섹션으로 구성된 복합 뷰(5개 이상의 구성 요소, 구분선, 페이지 나누기, 전체 너비 표)
- 사용자가 저장, 공유, 인쇄 또는 외부 호스트(iframe 타일, 대시보드 셀)에 포함하려는 경우
visualize:show_widget을 사용할 수 없음(인라인 렌더링 표면 없음)
모호한 경우 기본값은 인라인입니다. 추론을 명시적으로 표시:
"채팅에서 보길 원하셨으므로 인라인으로 렌더링하겠습니다. 다운로드 가능한 파일을 원하시면 동일한 스펙으로 mviz CLI를 실행할 수 있습니다. 말씀만 해주세요."
사용자가 인라인 렌더링 후 파일 버전을 요청하면 스펙이 이미 대화에 있으므로 다시 작성하지 않고 mviz ... -o out.html을 통해 파이프합니다.
시각적 스타일 (mdsinabox 테마 — CLI 렌더러용)
- 폰트: Helvetica Neue, Arial (깔끔한 산세리프)
- 시그니처: 대시보드 상단의 주황색 강조선
- 팔레트: 파란색 기본, 주황색 보조, 의미 색상(녹색=긍정, 호박색=경고, 빨간색=오류)
- 배경: 종이 (
#f8f8f8라이트) / 다크 (#231f20다크) - 원칙: 높은 데이터-잉크 비율, 차트 장식 없음, 최소한의 격자선, 데이터가 스스로 말하게 함
렌더러: mviz CLI (독립형 HTML)
CLI 렌더러는 위의 mdsinabox 테마로 스타일링된 완전한 HTML 문서를 생성합니다. 출력물은 브라우저에서 직접 보기, PDF 내보내기, iframe 포함 또는 파일로 공유하기에 적합합니다.
단일 차트 (JSON)
echo '<json_spec>' | npx -y -q mviz -o chart.html
마크다운에서 대시보드
npx -y -q mviz dashboard.md -o dashboard.html
폴더에서 대시보드
npx -y -q mviz my-dashboard/ -o dashboard.html
iframe 포함 출력 (--embed)
렌더링된 HTML이 다른 제품의 iframe(mdw-turbo Prism 타일, 대시보드 셀 등) 내에 위치할 경우, --embed를 전달하여 페이지 크롬(빨간색 강조 막대, 제목 행, 테마 전환)을 제거하고 CSS 정리, 투명 배경(호스트의 카드 크롬이 비치도록), 차트가 없을 때 ECharts 스크립트 제거, marked.parse(...) 호출자가 없을 때 marked 제거, JS 최소화 등 본문을 가볍게 만드는 일련의 후처리를 적용합니다.
npx -y -q mviz dashboard.md --embed -o tile.html
임베드 모드는 완전한 HTML 문서(DOCTYPE + html + head + body가 온전함)를 내보냅니다. visualize:show_widget에는 적합한 도구가 아닙니다. 그 경우 다른 렌더러(아래 참조)를 사용하세요.
16열 그리드 시스템
구성 요소는 size=[cols,rows] 구문을 사용하여 크기가 지정됩니다:
```big_value size=[4,2]
{"value": 1250000, "label": "Revenue", "format": "currency0m"}
```
```bar size=[8,6]
{"title": "Sales", "x": "month", "y": "sales", "file": "data/sales.json"}
```
- 총 16열 너비(세로 및 가로 모두)
- 행 높이: 행 단위당 약 32px (대략적 - 차트에는 패딩이 있음)
- 페이지 용량: 세로 [16c × 30r], 가로 [16c × 22r]
- 같은 줄의 구성 요소는 행을 공유합니다.
- 빈 줄 = 새 행
높이 지침:
| 행 단위 | 대략적인 높이 | 적합한 용도 |
|---|---|---|
| 2 | ~64px | KPI, 한 줄 메모 |
| 4 | ~128px | 작은 표, 텍스트 블록 |
| 5-6 | ~160-192px | 표준 차트 |
| 8+ | ~256px+ | 조밀한 표, 상세 차트 |
카테고리가 많은 차트(막대 10개 이상, 덤벨 행 10개 이상)의 경우 압축을 방지하기 위해 행 단위를 늘립니다.
나란히 배치
중요: 구성 요소를 나란히 배치하려면 코드 블록 사이에 빈 줄이 없어야 합니다:
```bar size=[8,5]
{"title": "Chart A", ...}
```
```line size=[8,5]
{"title": "Chart B", ...}
```
이렇게 하면 차트 A와 차트 B가 같은 행에 렌더링됩니다. 그 사이에 빈 줄을 넣으면 별도의 행에 배치됩니다.
제목 및 구역 나누기
| 구문 | 효과 |
|---|---|
# H1 | 페이지 제목 |
## H2 | 섹션 제목 |
### H3 | 가벼운 인라인 헤더(미묘하고 작은 텍스트) |
--- | 시각적 구분선 |
=== | 인쇄용 페이지 나누기 |
empty_space | 보이지 않는 그리드 셀 스페이서(기본값 4열 × 2행) |
제목 지침:
- 페이지 제목은 머리말
title:또는 선행# H1중 하나로 설정하고 둘 다 사용하지 마십시오. - 페이지 내 섹션 제목에는
## H2를 사용하십시오(가장 일반적). - 흐름을 방해하지 않는 가벼운 하위 제목에는
### H3를 사용하십시오.
섹션 대 페이지 나누기:
---를 사용하여 논리적 섹션을 시각적으로 구분하십시오. 콘텐츠는 필요에 따라 다음 페이지로 자연스럽게 흐릅니다.===는 PDF 출력을 위해 장이나 주요 보고서 섹션을 분리하는 등 명시적으로 새 페이지를 강제하려는 경우에만 사용하십시오.- 기본적으로
===를 사용하지 마십시오. 사용자가 명시적으로 요청한 경우에만 페이지 나누기를 추가하십시오.
기본 크기
| 구성 요소 | 기본 크기 | 참고 |
|---|---|---|
big_value | [4, 2] | 행당 4개 맞춤 |
delta | [4, 2] | 행당 4개 맞춤 |
sparkline | [4, 2] | 간결한 인라인 차트 |
bar, line, area | [8, 5] | 반 너비 |
pie, scatter, bubble | [8, 5] | 반 너비 |
funnel, sankey, heatmap | [8, 5] | 반 너비 |
histogram, boxplot, waterfall | [8, 5] | 반 너비 |
combo | [8, 5] | 반 너비 |
dumbbell | [12, 6] | 3/4 너비 |
table | [16, 4] | 전체 너비 |
textarea | [16, 4] | 전체 너비 |
calendar | [16, 3] | 전체 너비 |
xmr | [16, 6] | 전체 너비, 높음 |
mermaid | [8, 5] | 반 너비(텍스트 아트에는 ascii: true 사용) |
alert, note, text | [16, 1] | 전체 너비, 단일 행 |
empty_space | [4, 2] | 보이지 않는 스페이서 |
권장 크기 조합
| 레이아웃 목표 | 구성 요소 | 크기 |
|---|---|---|
| 한 행에 4개 KPI | 4× big_value | 각각 [4,2] |
| 한 행에 5개 KPI | 4× big_value + 1개 더 넓게 | [3,2] + [4,2] |
| KPI + 컨텍스트 | big_value + textarea | [3,2] + [13,2] |
| KPI + 차트 | big_value + bar | [4,2] + [12,5] |
예: 조밀한 KPI 행
```big_value size=[3,2]
{"value": 1250000, "label": "Revenue", "format": "currency0m"}
```
```big_value size=[3,2]
{"value": 8450, "label": "Orders", "format": "num0k"}
```
```big_value size=[3,2]
{"value": 2400000000, "label": "Queries", "format": "num0b"}
```
```delta size=[3,2]
{"value": 0.15, "label": "MoM", "format": "pct0"}
```
```delta size=[4,2]
{"value": 0.08, "label": "vs Target", "format": "pct0"}
```
이렇게 하면 5개의 KPI(3+3+3+3+4 = 16열)가 있는 행이 생성됩니다.
예: 두 차트 나란히
```bar size=[8,6] file=data/region-sales.json
```
```line size=[8,6] file=data/monthly-trend.json
```
지원 유형
차트: bar, line, area, pie, scatter, bubble, boxplot, histogram, waterfall, xmr, sankey, funnel, heatmap, calendar, sparkline, combo, dumbbell, mermaid
UI 구성 요소: big_value, delta, alert, note, text, textarea, empty_space, table
표 서식
표는 열 수준 및 셀 수준 서식을 지원합니다:
열 옵션: bold, italic, type ("sparkline" 또는 "heatmap")
{
"type": "table",
"columns": [
{"id": "product", "title": "Product", "bold": true},
{"id": "category", "title": "Category", "italic": true},
{"id": "sales", "title": "Sales", "fmt": "currency"},
{"id": "margin", "title": "Margin", "type": "heatmap", "fmt": "pct"},
{"id": "trend", "title": "Trend", "type": "sparkline", "sparkType": "line"}
],
"data": [
{"product": "Widget", "category": "Electronics", "sales": 125000, "margin": 0.85, "trend": [85, 92, 88, 95, 102, 125]}
]
}
셀 수준 재정의: {"value": "text", "bold": true}를 사용하여 열 기본값을 재정의합니다.
히트맵: 낮은 값에서 높은 값으로 색상 그라데이션을 적용합니다. 어두운 배경에서 텍스트가 자동으로 흰색으로 전환됩니다.
스파크라인 유형: line, bar, area, pct_bar (진행률 표시줄), dumbbell (전후 비교)
정렬 및 필터:
| 필드 | 값 | 기본값 | 효과 |
|---|---|---|---|
sortable | true / false | true | 열 머리글을 클릭하여 정렬합니다. 오름차순 → 내림차순 → 꺼짐 순으로 순환합니다. 숫자 열은 원시 값을 기준으로 정렬합니다. |
filter | true / false | false | true인 경우 표 위에 "Filter by any value…" 검색 입력을 렌더링합니다. 행은 모든 셀에서 대소문자를 구분하지 않는 포함 일치를 통해 실시간으로 필터링됩니다. |
예: {"type": "table", "filter": true, "columns": [...], "data": [...]}
메모 유형
메모는 noteType을 통해 세 가지 심각도 수준을 지원합니다:
| 유형 | 테두리 색상 | 용도 |
|---|---|---|
default | 빨간색 | 중요 공지(기본값) |
warning | 노란색 | 주의, 예비 데이터 |
tip | 녹색 | 모범 사례, 전문가 팁 |
메모는 또한 굵은 접두사 텍스트를 위한 선택적 label을 지원합니다:
{"type": "note", "label": "Pro Tip:", "content": "Use keyboard shortcuts for faster navigation.", "noteType": "tip"}
특수 차트 예제
big_value — 큰 표시가 있는 영웅 메트릭:
{"type": "big_value", "value": 1250000, "label": "Revenue", "format": "currency0m"}
- 선택적
comparison객체:{"value": 10300, "format": "currency", "label": "vs last month"}는 화살표와 함께 변경 사항을 표시합니다.
dumbbell — 방향성 색상 지정이 있는 전후 비교:
{
"type": "dumbbell",
"title": "ELO Changes",
"category": "team",
"start": "before",
"end": "after",
"startLabel": "Week 1",
"endLabel": "Week 2",
"higherIsBetter": true,
"data": [
{"team": "Chiefs", "before": 1650, "after": 1720},
{"team": "Bills", "before": 1600, "after": 1550}
]
}
- 녹색 = 개선, 빨간색 = 감소, 회색 = 변경 없음
- 순위의 경우
higherIsBetter: false(낮을수록 좋음) - 레이블은 큰 숫자를 자동으로 축약합니다(7450 → "7k")
delta — 방향성 색상 지정이 있는 변경 메트릭:
{"type": "delta", "value": 0.15, "label": "MoM Growth", "format": "pct0"}
- 양수 값은 ▲와 함께 녹색으로, 음수 값은 ▼와 함께 빨간색으로 표시됩니다.
- 선택적
comparison객체:{"value": 0.05, "label": "vs Target"}
area — 누적/볼륨 데이터를 위한 채워진 선 차트:
{
"type": "area",
"title": "Daily Active Users",
"x": "date",
"y": "users",
"data": [{"date": "Mon", "users": 1200}, {"date": "Tue", "users": 1450}]
}
combo — 이중 Y축이 있는 막대 + 선:
{
"type": "combo",
"title": "Revenue vs Growth Rate",
"x": "quarter",
"y": ["revenue", "growth_rate"],
"data": [
{"quarter": "Q1", "revenue": 1000000, "growth_rate": 0.15},
{"quarter": "Q2", "revenue": 1200000, "growth_rate": 0.20}
]
}
- 첫 번째 y-필드는 막대로, 두 번째는 선으로 렌더링됩니다.
- 독립적인 스케일을 가진 이중 Y축
heatmap — 2D 행렬 시각화:
{
"type": "heatmap",
"title": "Activity by Hour",
"xCategories": ["Mon", "Tue", "Wed", "Thu", "Fri"],
"yCategories": ["9am", "12pm", "3pm", "6pm"],
"format": "num0",
"data": [[0, 0, 85], [1, 0, 90], [2, 0, 72]]
}
format옵션은 셀 레이블에 적용됩니다(예:num0k,currency0k,pct)
funnel — 전환 또는 제거 흐름:
{
"type": "funnel",
"title": "Sales Pipeline",
"format": "num0",
"data": [
{"stage": "Leads", "value": 1000},
{"stage": "Qualified", "value": 600},
{"stage": "Proposal", "value": 300},
{"stage": "Closed", "value": 100}
]
}
format옵션은 레이블/툴팁에 적용됩니다(예:currency_auto,pct,num0)
waterfall — 누적 변경 시각화:
{
"type": "waterfall",
"title": "Revenue Bridge",
"x": "item",
"y": "value",
"data": [
{"item": "Start", "value": 1000, "isTotal": true},
{"item": "Growth", "value": 200},
{"item": "Churn", "value": -50},
{"item": "End", "value": 1150, "isTotal": true}
]
}
bubble — 크기 차원이 있는 산점도. series를 사용하여 색상 그룹화를 지원합니다.
...