소스 코드를 분석하여 ByteByteDgo 스타일 아키텍처 다이어그램 HTML을 생성. Use when the user wants to generate architecture diagrams, system overview, or data flow visualization from source code. Supports detail, simple, and poster modes.
소스 코드를 자동 분석하여 ByteByteDgo 스타일의 시스템 아키텍처 다이어그램과 애니메이션 데이터 흐름을 HTML로 생성한다.
/architecture-draw [모드] [경로]
detail (기본값), simple, 또는 poster
detail: 8-11개 패널의 상세 아키텍처 문서simple: 2-3개 패널의 컴팩트 1페이지 인포그래픽 (ByteByteDgo 단일 이미지 스타일)poster: 인포그래픽 포스터 (Lucide 아이콘, S-커브 화살표, 좌표 기반 정밀 레이아웃, Opus 권장)detail로 동작출력 파일:
detail → {프로젝트}/docs/architecture.htmlsimple → {프로젝트}/docs/architecture-simple.htmlposter → {프로젝트}/docs/architecture-poster.htmlIMPORTANT: 생성되는 HTML에는 이모지를 절대 사용하지 않는다. 모든 아이콘은 인라인 SVG로 표현한다.
다음 파일들을 Glob/Read로 탐색하여 프로젝트 구조를 파악한다:
루트 빌드 파일 확인:
settings.gradle*, pom.xml, package.json, go.mod, Cargo.toml, *.sln, pyproject.toml, requirements.txt디렉토리 구조 확인:
*/ 로 1단계 서브디렉토리 목록 확인README.md 확인:
docker-compose 확인:
docker-compose*.yml 파일에서 서비스 목록과 의존성 추출판정 기준:
microservicesmonolithmonorepo각 서비스/모듈에 대해 다음 정보를 추출한다:
server.port, PORT, listen 등을 설정 파일에서 검색gateway: 이름에 gateway/proxy 포함 또는 라우팅 설정 존재frontend: package.json에 react/next/vue/angular 또는 프론트엔드 프레임워크common: 독립 실행 불가한 공유 라이브러리service: 그 외 독립 실행 가능한 서비스설정 파일과 의존성에서 인프라 컴포넌트를 추출한다.
탐색 대상:
**/application*.yml, **/application*.properties**/docker-compose*.yml**/.env*감지 패턴:
| 컴포넌트 타입 | 감지 키워드 |
|---|---|
| database | mysql, postgresql, postgres, mongodb, oracle, h2, datasource, jdbc, sqlite, mariadb |
| cache | redis, memcached, caffeine, ehcache |
| messageQueue | rabbitmq, kafka, amqp, activemq, pulsar, nats |
| discovery | consul, eureka, zookeeper, nacos |
| monitoring | grafana, prometheus, loki, datadog, alloy, jaeger, zipkin |
| secretManagement | vault, aws-secrets, azure-keyvault |
| cicd | jenkins, github-actions, gitlab-ci, circleci, argocd |
| registry | harbor, ecr, gcr, docker-hub |
각 인프라 컴포넌트에 대해 어떤 서비스가 연결되는지 매핑한다.
API 엔드포인트 추출:
@RequestMapping, @GetMapping, @PostMapping, @PutMapping, @DeleteMappingrouter.get, router.post, app.get, app.posthttp.HandleFunc, r.GET, r.POST, e.GET, e.POST@app.route, @router.get, @api_view#[get, #[post, .route(서비스 간 HTTP 통신:
RestTemplate, WebClient, @FeignClient, RestClientfetch, axios, http.request, got(http.Get, http.Post, http.NewRequestrequests.get, httpx, aiohttp메시징 통신:
@RabbitListener, RabbitTemplate, amqpTemplate@KafkaListener, KafkaTemplate, KafkaProducer, KafkaConsumer@EventListener, ApplicationEventPublisher, EventEmitterGateway 라우팅:
routes 설정services/routes 설정위에서 수집한 정보를 종합하여 주요 데이터 흐름을 구성한다:
Gateway 라우팅 기반 흐름:
서비스 간 호출 체인:
메시징 흐름:
DB/캐시 접근:
각 흐름에 이름을 부여하고 (예: "Authentication Flow", "Notification Flow") 경로를 정리한다.
분석 결과를 다음 구조로 정리한다 (실제로 JSON을 생성하지는 않고, 이 구조를 머릿속에 두고 HTML을 생성한다):
{
"projectName": "프로젝트명",
"projectType": "microservices | monolith | monorepo",
"services": [
{
"name": "서비스명",
"type": "service | gateway | frontend | common",
"port": 8080,
"techStack": ["Spring Boot", "Java"],
"description": "역할 설명"
}
],
"infrastructure": [
{
"name": "MySQL",
"type": "database | cache | messageQueue | discovery | monitoring | secretManagement | cicd | registry",
"connectedServices": ["auth-service", "user-service"]
}
],
"connections": [
{
"from": "api-gateway",
"to": "auth-service",
"type": "http | messaging | database",
"label": "설명"
}
],
"dataFlows": [
{
"name": "Authentication Flow",
"color": "#FF6B6B",
"path": ["Client", "api-gateway", "auth-service", "MySQL"]
}
]
}
컴포넌트 유형별 색상 (ByteByteGo 파스텔 스타일 — 밝은 배경 + 어두운 텍스트):
| 유형 | 배경색 (Fill) | 테두리색 (Border) | 텍스트색 | 아이콘색 | 용도 |
|---|---|---|---|---|---|
| client | #FFE0C0 | #E6C8A0 | #333333 | #E67E22 | 외부 클라이언트, User |
| gateway | #D4EFFF | #A8D8F0 | #333333 | #2980B9 | API Gateway, Proxy, Load Balancer |
| service | #D4EFFF | #A8D8F0 | #333333 | #4A9EC5 | 백엔드 서비스 |
| frontend | #E8D5F5 | #D0B8E8 | #333333 | #8E44AD | 웹 클라이언트, 모바일 앱 |
| database | #C8F7DC | #A0E0B8 | #333333 | #27AE60 | MySQL, PostgreSQL, MongoDB |
| cache | #FFF9C4 | #E8E0A0 | #333333 | #F5A623 | Redis, Memcached |
| messageQueue | #E8D5F5 | #D0B8E8 | #333333 | #8E44AD | RabbitMQ, Kafka |
| discovery | #C8F7DC | #A0E0B8 | #333333 | #1ABC9C | Consul, Eureka |
| monitoring | #FFD6E0 | #E8B0C0 | #333333 | #E74C3C | Grafana, Prometheus |
| secretManagement | #FFF9C4 | #E8E0A0 | #333333 | #F5A623 | Vault |
| cicd | #D4EFFF | #A8D8F0 | #333333 | #3498DB | Jenkins, GitHub Actions |
| registry | #C8F7DC | #A0E0B8 | #333333 | #16A085 | Harbor, ECR |
데이터 흐름 애니메이션 색상 (흐름별 순환 — 파스텔 배경 위에서 눈에 띄도록 선명한 색상):
#FF6B6B#4ECDC4#45B7D1#96CEB4#FFEAA7모든 컴포넌트 박스에 적용하는 CSS (파스텔 배경 + 어두운 텍스트):
.component-box {
border-radius: 10px;
padding: 16px 20px;
color: #333333;
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
font-size: 14px;
font-weight: 600;
border: 1.5px solid; /* 테두리색은 유형별 border color 사용 */
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
gap: 10px;
min-width: 140px;
justify-content: center;
}
SVG 내부에서는 <foreignObject> 대신 순수 SVG로 박스를 그린다:
<rect> 에 rx="10" 적용, fill은 유형별 파스텔 배경색, stroke는 유형별 테두리색, stroke-width="1.5"<text> 로 컴포넌트명 표시, fill="#333333", font-family="Segoe UI, system-ui, sans-serif", font-size="14", font-weight="600", text-anchor="middle"<filter> 로 미세한 그림자: <feDropShadow dx="0" dy="1" stdDeviation="2" flood-opacity="0.1"/>SVG <path> + <marker> 로 화살표:
#888888 (중간 회색)2.5px#888888stroke-dasharray="6 3" (비동기, REST, 메시징 등)stroke-dasharray="8 4"font-size="11", fill="#666666", font-family="Segoe UI, system-ui, sans-serif", 선 중간 지점에 배치<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#888888"/>
</marker>
</defs>
<!-- 연결선 라벨 예시 -->
<text x="{선 중간x}" y="{선 중간y - 8}" font-size="11" fill="#666666"
font-family="Segoe UI, system-ui, sans-serif" text-anchor="middle">REST API</text>
#F5F5F51600px, 중앙 정렬Segoe UI, system-ui, -apple-system, sans-serif.panel (검정 테두리, 둥근 모서리 12px, 흰색 배경) 로 감싼다stroke-dasharray="6 3", #CCCCCC).accent-bar)각 컴포넌트 박스 왼쪽에 유형별 SVG 아이콘을 표시한다. 아이콘은 24x24 viewBox, 유형별 고유 색상 (색상 팔레트의 아이콘색 참조), stroke-width="1.5". 아이콘은 단색이 아니라 컴포넌트 특성을 나타내는 고유한 색상을 사용한다.
아이콘 스타일 가이드 (ByteByteDgo 스타일):
fill 에 연한 색상 + stroke 에 진한 색상 적용opacity="0.15")을 추가하여 illustrative한 느낌을 준다아이콘을 SVG 내에서 사용할 때는 <g transform="translate(x,y)"> 로 박스 내 위치에 배치하고, 아이콘 path를 직접 인라인한다.
텍스트가 박스 밖으로 넘치는 것을 방지하기 위해 반드시 따라야 하는 규칙:
텍스트 너비 추정:
박스 크기 규칙:
SVG overflow 안전장치:
overflow="visible" 추가overflow: visible (절대 overflow: hidden 사용 금지)SVG viewBox 크기:
아이콘-텍스트 간격:
긴 텍스트 처리:
검증: HTML 생성 후 모든 텍스트 요소를 점검:
흐름(Flow) 다이어그램에서 각 단계에 번호 원형을 표시한다. ByteByteDgo 스타일의 빨간 원 + 흰색 숫자:
<!-- 단계 번호 원형 -->
<circle cx="{x}" cy="{y}" r="12" fill="#FF6B6B" stroke="none"/>
<text x="{x}" y="{y+4}" fill="#FFF" font-size="11" font-weight="700" text-anchor="middle">1</text>
#FF6B6B)| 유형 | 아이콘 형태 | 아이콘색 | SVG 내용 |
|---|---|---|---|
| client | 모니터 화면 | #E67E22 | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#E67E22" stroke-width="1.5"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg> |
| gateway | 방패 | #2980B9 | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#2980B9" stroke-width="1.5"><path d="M12 2l8 4v6c0 5.25-3.5 9.74-8 11-4.5-1.26-8-5.75-8-11V6l8-4z"/></svg> |
| service | 서버 박스 | #4A9EC5 | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#4A9EC5" stroke-width="1.5"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><circle cx="6" cy="6" r="1" fill="#4A9EC5"/><circle cx="6" cy="18" r="1" fill="#4A9EC5"/></svg> |
| frontend | 브라우저 창 | #8E44AD | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#8E44AD" stroke-width="1.5"><rect x="2" y="3" width="20" height="18" rx="2"/><line x1="2" y1="9" x2="22" y2="9"/><circle cx="6" cy="6" r="1" fill="#8E44AD"/><circle cx="10" cy="6" r="1" fill="#8E44AD"/><circle cx="14" cy="6" r="1" fill="#8E44AD"/></svg> |
| database | 원통형 | #27AE60 | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#27AE60" stroke-width="1.5"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 5v14c0 1.66-4.03 3-9 3s-9-1.34-9-3V5"/><path d="M21 12c0 1.66-4.03 3-9 3s-9-1.34-9-3"/></svg> |
| cache | 번개 | #F5A623 | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#F5A623" stroke-width="1.5"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg> |
| messageQueue | 편지봉투 | #8E44AD | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#8E44AD" stroke-width="1.5"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M22 4L12 13 2 4"/></svg> |
| discovery | 나침반 | #1ABC9C | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#1ABC9C" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88" fill="#1ABC9C" opacity="0.3"/></svg> |
| monitoring | 차트 | #E74C3C | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#E74C3C" stroke-width="1.5"><path d="M18 20V10M12 20V4M6 20v-6"/></svg> |
| secretManagement | 자물쇠 | #F5A623 | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#F5A623" stroke-width="1.5"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> |
| cicd | 순환 화살표 | #3498DB | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#3498DB" stroke-width="1.5"><path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0115-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 01-15 6.7L3 16"/></svg> |
| registry | 컨테이너 박스 | #16A085 | <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#16A085" stroke-width="1.5"><path d="M21 16V8a2 2 0 00-1-1.73l-7-4a2 2 0 00-2 0l-7 4A2 2 0 003 8v8a2 2 0 001 1.73l7 4a2 2 0 002 0l7-4A2 2 0 0021 16z"/><path d="M3.27 6.96L12 12.01l8.73-5.05"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg> |
HTML/CSS를 우선 사용한다. SVG는 복잡한 연결선, 애니메이션이 필요한 곳에만 사용한다.
HTML/CSS로 구현하는 요소:
.api-row).filter-chain).tech-grid).entity-card)SVG로 구현하는 요소:
flow-svg-container 감싸기)flow-svg-container 감싸기)animateMotion dot (SVG)SVG 사용 시 규칙:
<div class="flow-svg-container"> 로 감싼다viewBox를 사용하고, 고정 width 대신 style="width:100%;overflow:visible" 을 적용한다fill-opacity="0.3" 을 적용하여 미묘한 구분을 준다font-family="SF Mono,Fira Code,Consolas,monospace"단일 HTML 파일로 생성한다. 외부 CDN/라이브러리 의존성은 절대 사용하지 않는다. 순수 HTML + CSS + inline SVG만 사용한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{프로젝트명} - System Architecture</title>
<style>
/* 전체 스타일 인라인 */
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
background: #F5F5F5;
color: #1a202c;
--font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace;
}
.container {
max-width: 1600px;
margin: 0 auto;
padding: 40px 48px;
}
header {
text-align: left;
margin-bottom: 24px;
}
/* ByteByteGo 스타일 패널 */
.panel {
border: 2px solid #333333;
border-radius: 12px;
padding: 24px;
margin-bottom: 32px;
background: #FFFFFF;
overflow: visible;
}
.panel-title {
font-size: 16px;
font-weight: 700;
margin-bottom: 16px;
color: #333;
padding: 4px 12px;
padding-bottom: 10px;
border-bottom: 1.5px dashed #ddd;
border-radius: 6px;
display: flex;
align-items: center;
gap: 8px;
}
/* 패널 그리드: ByteByteDgo 스타일 2열 그리드 배치 */
.panels-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
margin-bottom: 32px;
}
.panels-grid .panel {
margin-bottom: 0;
}
/* 전체 너비 패널은 두 열을 모두 차지 */
.panel-full {
grid-column: 1 / -1;
}
/* 하위 패널: 패널 안에 중첩되는 서브 패널 */
.sub-panel {
border: 1.5px solid #DDD;
border-radius: 8px;
padding: 16px;
background: #FAFAFA;
}
.sub-panel-title {
font-size: 14px;
font-weight: 600;
margin-bottom: 12px;
color: #333;
}
/* 키워드 하이라이트: 제목에서 핵심 단어를 강조 */
.highlight {
background: #C8F7DC;
padding: 2px 8px;
border-radius: 4px;
}
/* Utility color classes */
.bg-blue { background: #D4EFFF; }
.bg-green { background: #C8F7DC; }
.bg-pink { background: #FFD6E0; }
.bg-yellow { background: #FFF9C4; }
.bg-purple { background: #E8D5F5; }
.bg-orange { background: #FFE0C0; }
.bg-gray { background: #F0F0F0; }
/* Badge */
.badge { display: inline-block; padding: 2px 10px; border-radius: 5px; font-size: 13px; font-weight: 700; color: #333; }
/* Header */
.header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 24px; max-width: 1600px; margin-left: auto; margin-right: auto; }
.header-title { display: flex; align-items: center; gap: 0; }
.header-title .accent-bar { width: 6px; height: 48px; background: #2ECC71; border-radius: 3px; margin-right: 14px; }
.header-title h1 { font-size: 32px; font-weight: 800; letter-spacing: -0.5px; color: #1a1a1a; }
.brand { font-size: 18px; font-weight: 700; color: #333; display: flex; align-items: center; gap: 6px; }
/* Flow SVG container */
.flow-svg-container { width: 100%; overflow: visible; }
.flow-svg-container svg { width: 100%; height: auto; overflow: visible; }
/* Entity cards */
.entity-card { flex: 1; min-width: 280px; border-radius: 10px; overflow: hidden; }
.entity-header { padding: 8px 14px; font-size: 14px; font-weight: 700; color: #333; display: flex; align-items: center; gap: 6px; }
.entity-fields { padding: 6px 14px 10px; background: #fff; border: 1.5px solid #ddd; border-top: none; border-radius: 0 0 10px 10px; }
.entity-field { display: flex; align-items: center; gap: 6px; padding: 3px 0; font-size: 12px; }
.field-name { font-family: var(--font-mono); font-weight: 600; color: #333; }
.field-type { color: #888; font-size: 11px; margin-left: auto; }
/* API endpoint rows */
.api-group { margin-bottom: 16px; }
.api-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 12.5px; }
.api-path { font-family: var(--font-mono); font-size: 12px; color: #555; }
.api-desc { color: #888; font-size: 11.5px; margin-left: auto; }
.tech-badges, .tech-grid {
display: flex;
gap: 18px;
justify-content: center;
flex-wrap: wrap;
margin-top: 12px;
}
.tech-badge {
padding: 14px 22px;
border-radius: 10px;
background: #F1F5F9;
color: #475569;
font-size: 15px;
font-weight: 500;
gap: 10px;
}
section {
margin-bottom: 48px;
}
section h2 {
font-size: 20px;
font-weight: 700;
color: #333333;
margin-bottom: 24px;
padding-bottom: 0;
border-bottom: none;
}
.flow-legend {
display: flex;
gap: 20px;
flex-wrap: wrap;
margin-bottom: 20px;
padding: 12px 16px;
background: #F8FAFC;
border-radius: 8px;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
color: #475569;
}
.legend-dot {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
}
</style>
</head>
<body>
<div class="container">
<!-- 헤더: 악센트 바 + 프로젝트명 + 브랜드 -->
<div class="header">
<div class="header-title">
<div class="accent-bar"></div>
<h1><span class="highlight">{프로젝트명}</span> Architecture</h1>
</div>
<div class="brand">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<rect x="2" y="2" width="20" height="20" rx="4" fill="#2ECC71"/>
<path d="M7 12h10M12 7v10" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/>
</svg>
architecture-draw
</div>
</div>
<header>
<p>{프로젝트 타입}: {서비스 수}개 서비스</p>
<div class="tech-badges">
<!-- 감지된 기술 스택을 배지로 나열 -->
<span class="tech-badge">{기술1}</span>
<span class="tech-badge">{기술2}</span>
</div>
</header>
<!-- 섹션들을 그리드로 배치: 독립 개념은 2열 그리드, 복잡한 흐름은 전체 너비 -->
<!-- 섹션 1: 시스템 아키텍처 (전체 너비 패널) -->
<section class="architecture">
<div class="panel panel-full">
<div class="panel-title">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4A9EC5" stroke-width="1.5"><rect x="2" y="2" width="20" height="20" rx="4"/><path d="M12 2v20M2 12h20"/></svg>
<span class="badge bg-blue">System Architecture</span>
Bird's Eye View
</div>
<svg width="1500" height="{동적 계산}" viewBox="0 0 1500 {동적 계산}">
<!-- defs: marker, filter -->
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#888888"/>
</marker>
<filter id="shadow">
<feDropShadow dx="0" dy="1" stdDeviation="2" flood-opacity="0.1"/>
</filter>
</defs>
<!-- 각 레이어별 컴포넌트 박스 + 아이콘 -->
<!-- 연결선 + 연결선 텍스트 라벨 -->
</svg>
</div>
</section>
<!-- 섹션 2: 데이터 흐름 (패널로 감싸기) -->
<section class="data-flow">
<div class="panel">
<div class="panel-title">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FF6B6B" stroke-width="1.5"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
<span class="badge bg-pink">Data Flow</span>
Animated Request Lifecycle
</div>
<div class="flow-legend">
<!-- 흐름별 범례 -->
<div class="legend-item">
<span class="legend-dot" style="background: #FF6B6B"></span>
<span>{흐름 이름}</span>
</div>
</div>
<svg width="1500" height="{동적 계산}" viewBox="0 0 1500 {동적 계산}">
<!-- 동일한 defs -->
<!-- 동일한 컴포넌트 배치 (연한 색상 또는 동일) -->
<!-- 흐름 경로 path + animateMotion dot -->
</svg>
</div>
</section>
</div>
</body>
</html>
SVG 내부에서 컴포넌트를 계층적으로 배치한다:
Layer 0 (y=60): Client (외부 클라이언트)
Layer 1 (y=180): Gateway / Load Balancer
Layer 2 (y=300): Services (가로 배열, 균등 분배)
Layer 3 (y=420): Infrastructure (DB, Cache, Queue 등 가로 배열)
Layer 4 (y=540): 외부 시스템 (Monitoring, CI/CD, Registry 등)
레이아웃 규칙:
120px1500px 내에서 균등 배치160px, 높이 50px (텍스트 길이에 따라 조정 가능)컴포넌트 박스 SVG 구성 (파스텔 배경 + 테두리 + 어두운 텍스트 + 컬러 아이콘):
<!-- 컴포넌트 박스 (예: service 타입) -->
<g transform="translate({x}, {y})" filter="url(#shadow)">
<!-- 배경 박스: 파스텔 fill + 테두리 -->
<rect width="160" height="50" rx="10" fill="#D4EFFF" stroke="#A8D8F0" stroke-width="1.5"/>
<!-- 아이콘 (박스 내 왼쪽, 유형별 컬러) -->
<g transform="translate(14, 15)">
<!-- 해당 유형의 SVG 아이콘 path (stroke=유형별 아이콘색) -->
</g>
<!-- 텍스트 (아이콘 오른쪽, 어두운 텍스트) -->
<text x="95" y="30" fill="#333333" font-size="14" font-weight="600"
font-family="Segoe UI, system-ui, sans-serif" text-anchor="middle">{서비스명}</text>
</g>
연결선 (중간 회색 + 텍스트 라벨):
<!-- 직선 연결 (dashed — 비동기/REST/메시징) -->
<line x1="{시작x}" y1="{시작y}" x2="{끝x}" y2="{끝y}"
stroke="#888888" stroke-width="2.5" stroke-dasharray="6 3" marker-end="url(#arrowhead)"/>
<!-- 연결선 라벨 -->
<text x="{중간x}" y="{중간y - 8}" font-size="11" fill="#666666"
font-family="Segoe UI, system-ui, sans-serif" text-anchor="middle">{통신 설명}</text>
<!-- 곡선 연결 (수평 이동이 필요한 경우, dashed) -->
<path d="M {시작x} {시작y} C {제어점1x} {제어점1y}, {제어점2x} {제어점2y}, {끝x} {끝y}"
fill="none" stroke="#888888" stroke-width="2.5" stroke-dasharray="6 3" marker-end="url(#arrowhead)"/>
<!-- 곡선 연결 라벨 -->
<text x="{곡선 중간x}" y="{곡선 중간y - 8}" font-size="11" fill="#666666"
font-family="Segoe UI, system-ui, sans-serif" text-anchor="middle">{통신 설명}</text>
데이터 흐름 섹션에서는 아키텍처와 동일한 컴포넌트 배치를 사용하되, 흐름 경로를 따라 움직이는 원(dot) 애니메이션을 추가한다.
구현 방법:
<path>로 정의한다stroke-dasharray="8 4" + opacity="0.6" 를 적용하여 점선으로 표시한다 (흐름별 고유 색상 사용)<circle r="6">)에 <animateMotion>을 적용하여 경로를 따라 이동시킨다<rect>)보다 먼저 그린다. SVG는 코드 순서가 z-order이므로, dot을 먼저 그려야 박스 뒤로 지나간다. 단, 번호 ball과 겹치는 화살표는 ball을 화살표 뒤에 그려서 ball이 화살표 위에 표시되게 한다.orient="auto" 마커는 line 방향에 맞춰 자동 회전하므로, 역방향 line (x1 > x2)에도 정방향 마커(M0,0 L8,4 L0,8)를 사용한다. 별도의 역방향 마커(swimArrowBack)를 만들면 이중 반전되어 화살표가 반대로 표시된다.dur 속성은 경로 길이에 비례하여 설정한다. 짧은 흐름은 dur="3s", 긴 스윔 레인은 dur="10~12s".repeatCount="indefinite"로 무한 반복한다<!-- 흐름 경로 정의 -->
<path id="flow-1" d="M {시작} L {중간1} L {중간2} L {끝}"
fill="none" stroke="#FF6B6B" stroke-width="2.5"
stroke-dasharray="8 4" opacity="0.5"/>
<!-- 움직이는 dot -->
<circle r="6" fill="#FF6B6B" opacity="0.9">
<animateMotion dur="3s" repeatCount="indefinite">
<mpath href="#flow-1"/>
</animateMotion>
</circle>
흐름 경로 path의 d 속성:
인증 흐름, 핵심 비즈니스 흐름 등 복잡한 단계별 흐름은 ByteByteDgo의 Git Workflow 다이어그램 스타일의 스윔 레인으로 표현한다:
상단 행: 컴포넌트 스윔 레인
열 카테고리 헤더
수직 흐름 + 수평 화살표
액션 라벨에 흰색 배경 (CRITICAL)
<rect>를 뒤에 배치할 것fill="white", rx="4", stroke는 화살표 색상과 동일, stroke-width="0.8", stroke-dasharray="4 2"text-anchor="middle"로 중앙 정렬왼쪽 측면 단계 라벨
분기점
animateMotion 점
<circle r="6">, dur="3s", repeatCount="indefinite"데이터 흐름 섹션 상단에 HTML로 범례를 표시한다:
<div class="flow-legend">
<div class="legend-item">
<span class="legend-dot" style="background: #FF6B6B"></span>
<span>Authentication Flow</span>
</div>
<div class="legend-item">
<span class="legend-dot" style="background: #4ECDC4"></span>
<span>Order Processing Flow</span>
</div>
<!-- 흐름 수만큼 반복 -->
</div>
콘텐츠에 여러 독립적인 개념이 있을 때는 2열 그리드(panels-grid)로 배치한다. 전체 너비가 필요한 개요 다이어그램이나 복잡한 흐름에는 panel-full 클래스를 사용한다.
<div class="panels-grid">
<div class="panel"><!-- 패널 1: 내부 아키텍처 --></div>
<div class="panel"><!-- 패널 2: API 엔드포인트 --></div>
<div class="panel"><!-- 패널 3: 데이터 모델 --></div>
<div class="panel"><!-- 패널 4: 인증 흐름 --></div>
<div class="panel panel-full"><!-- 전체 너비: 시스템 개요 --></div>
</div>
하나의 문서 안에서 여러 가지 다이어그램 유형을 혼합하여 사용한다:
각 패널의 성격에 맞는 다이어그램 유형을 선택한다. 모든 패널을 동일한 유형으로 그리지 않는다.
콘텐츠가 복잡할 때는 집중된 패널로 분할한다. "Architecture at a Glance" (간단한 개요)를 항상 첫 번째 패널로 배치하고, 이후 상세 패널을 나열한다. (Simple -> Detail 흐름)
단일 서비스 분석 시 (8-11개 패널):
멀티 서비스 분석 시: 다음으로 분할:
전체 너비 필수 패널: Security Filter Chain, Tech Stack, Authentication Flows는 항상 panel-full (grid-column: 1 / -1)로 배치한다. 이들은 수평 공간이 많이 필요하다.
각 패널은 하나의 개념에 집중하며, 자체적으로 완결적이어야 한다. ByteByteDgo 스타일처럼 페이지당 8~11개 패널을 그리드 레이아웃으로 배치하는 것을 목표로 한다.
/* Security Filter Chain */
.filter-chain { display: flex; flex-wrap: nowrap; justify-content: center; }
.filter-box { padding: 16px 24px; min-width: 160px; font-size: 14px; border-radius: 12px; }
.filter-arrow { margin: 0 12px; }
/* SVG 폰트 크기 기준 */
/* Panel titles: 16px, Section headers: 13px, Box labels: 11-12px, List items: 10-10.5px, Annotations: 9px */
시각적 스타일은 ByteByteDgo의 인포그래픽 다이어그램을 기반으로 한다. 핵심 특성:
#F5F5F5) 위에 흰색 패널 — 카드가 부각되는 구조[icon] [Architecture at a Glance] Bird's Eye View).accent-bar)SF Mono, Fira Code, Consolas)데이터 흐름에는 Git Workflow 다이어그램 스타일을 따른다:
docs/ 디렉토리가 없으면 Bash로 mkdir -p {프로젝트경로}/docs 실행detail: {프로젝트경로}/docs/architecture.htmlsimple: {프로젝트경로}/docs/architecture-simple.htmlposter: {프로젝트경로}/docs/architecture-poster.htmldocs/architecture[-simple|-poster].html 파일을 생성했습니다. 브라우저에서 열어 확인하세요.simple 모드는 ByteByteDgo 단일 이미지 인포그래픽 스타일 (images/image.jpg 참조)로 생성한다:
레이아웃:
background: #fff) — 포스터/인포그래픽 느낌 (detail 모드의 #F5F5F5와 다름)max-width: 1100px — 컴팩트한 폭flex: 1.2 : 우측(텍스트 정보) flex: 1 비율 권장패널 구성:
스타일 특성:
2.5px solid #222 (detail보다 약간 두꺼움).panel-label 스타일)hsplit-divider)split-divider).tag) flex wrapSVG 규칙:
width:100% + overflow:visible 사용poster 모드는 ByteByteDgo 인포그래픽 포스터 스타일로 생성한다. 복잡한 SVG 좌표 계산이 필요하므로 Opus 모델을 권장한다.
레이아웃:
border-radius: 18px)박스 스타일:
rx: 12), 높이 64~66pxunpkg.com/lucide@latest 또는 인라인 SVG path)좌표 계획 (CRITICAL — 반드시 다이어그램 그리기 전에 수행):
각 박스의 좌표와 연결점을 먼저 계산한다:
박스: { x, y, w, h }
중심: cx = x + w/2, cy = y + h/2
연결점:
top = (cx, y)
bottom = (cx, y + h)
left = (x, cy)
right = (x + w, cy)
화살표 연결 규칙 (MUST FOLLOW):
곡선은 반드시 cubic bezier S-커브:
M sx,sy C sx,midY ex,midY ex,ey (midY = (sy+ey)/2)M sx,sy C midX,sy midX,ey ex,ey (midX = (sx+ex)/2)팬아웃 S-커브 끝에 수직 L 구간(30px) 필수:
turnY = targetY - 30
path = "M sx,sy C sx,midY tx,midY tx,turnY L tx,targetY"
화살촉 Marker 정의 (MUST INCLUDE):
<marker id="ah-색상" viewBox="0 0 10 8" refX="10" refY="4" markerWidth="7" markerHeight="6" orient="auto">
<path d="M0,0 L10,4 L0,8 Z" fill="색상코드"/>
</marker>
refX="10" 필수 (9 이하면 화살촉이 묻힘)애니메이션:
<animateMotion> path는 해당 화살표의 path d 속성과 동일해야 함begin 속성으로 시차 적용 (0.3~0.5s 간격)dur 2~2.5s, repeatCount="indefinite"패널 구성:
SVG viewBox 크기:
셀프 검증 (자동, 최대 3회):
<defs>에 정의되어 있는지marker-end 속성이 있는지HTML 생성 후 반드시 Playwright MCP로 시각 검증을 수행한다:
python3 -m http.server 8888 (docs 디렉토리에서)browser_navigate → http://localhost:8888/{파일명}browser_take_screenshot (fullPage: true)전체 페이지 스크린샷만으로는 디테일 문제를 발견할 수 없다. 반드시 각 패널을 개별로 캡쳐하여 확대 검증한다:
browser_take_screenshot(element: "Panel 이름", ref: "패널ref", type: png)
각 패널 스크린샷에서 다음을 확인:
Playwright 캡쳐 전에 HTML 소스에서 SVG 좌표를 프로그래밍적으로 검증한다:
모든 path의 끝점이 target 박스의 edge center와 일치하는지 확인:
animateMotion path가 해당 화살표 path와 동일한 경로인지 확인:
marker-end 속성이 모든 화살표 path에 있는지 확인
defs에 사용된 모든 색상의 marker가 정의되어 있는지 확인
browser_take_screenshot (fullPage: true, type: png){프로젝트경로}/docs/architecture[-simple|-poster]-screenshot.pngdocs/architecture-screenshot.png, docs/architecture-simple-screenshot.png, docs/architecture-poster-screenshot.png<foreignObject>는 사용하지 않는다. 순수 SVG 요소만 사용한다.