
위협 연구를 위한 그래프 도구 키트 - 그리고 다른 것들
이 프로젝트는 대부분 "vibecoded"(직관적 코딩) 방식으로 작성되었으므로 적절한 주의가 필요합니다. 코드는 실제 프로그래머가 검토했지만, 취약점에 대해 강화되지 않았습니다. 완전한 보안 검토 없이 외부에 노출하지 마십시오.
Quantickle은 네트워크 그래프를 구축하고 탐색하기 위한 대화형 브라우저 우선 툴킷입니다. 프론트엔드(Cytoscape.js + 사용자 정의 UI)는 렌더링, 편집 및 레이아웃 실행을 담당하고, 경량 Express 서버는 UI를 제공하고 통합 호출을 프록시하며 선택적으로 그래프를 Neo4j에 저장합니다. 즉, 브라우저가 그래프 상태와 시각화를 소유하고, 서버는 필요할 때 자산과 통합을 제공하는 역할을 합니다.
bezier), 직선, 번들(unbundled-bezier), 택시, 둥근 택시 옵션을 제공합니다.haystack 및 segments 곡선 스타일도 지원합니다.다음은 Quantickle이 할 수 있는 몇 가지 예시입니다:
Quantickle은 문서 집합을 연결하는 소수의 공유 개념을 기반으로 합니다:
좌표계 및 공간 레이아웃 — Quantickle의 절대 및 깊이 인식 레이아웃은 x, y, z 좌표에 대해 0–1000 큐브를 사용합니다. 전체 공간 규칙 및 조명 동작은 COORDINATE_SYSTEM.md를 참조하십시오.
그래프 파일 관리 및 프로젝트 파일 — .qut 파일은 표준 저장 상태이며, 노드, 엣지, 메타데이터 및 컨테이너 계층을 저장합니다.
Neo4j 통합 — 서버는 메타데이터 스냅샷을 포함하여 Neo4j에서 그래프를 저장하고 검색할 수 있습니다. 구성 및 워크플로우 세부 사항은 NEO4J_INTEGRATION_README.md를 참조하십시오.
Quantickle 그래프는 레이아웃, 스타일링 및 그룹화를 구동하는 메타데이터가 있는 노드와 엣지의 집합입니다.
id와 선택적 속성(예: label, type, size, , 좌표)을 가진 정점입니다. 노드에는 마크다운 또는 통합에서 사용하는 사용자 정의 속성이 포함될 수 있습니다.colorinfosource + target 노드 ID와 선택적 label, type, weight 및 스타일링 메타데이터가 있는 관계입니다.Quantickle의 내부 그래프 JSON은 nodes와 edges 배열이 있는 평면 구조입니다. 컨테이너 관계와 클래스는 노드 메타데이터로 보존됩니다.
Quantickle은 파일 → 데이터 가져오기 메뉴와 자동화된 통합을 통해 여러 가져오기 형식을 지원합니다. 각 가져오기 도구는 .qut 프로젝트 파일을 저장할 때 사용되는 동일한 그래프 파이프라인을 사용하므로 아래 구조는 내보내기 형식도 나타냅니다.
CSV 가져오기 도구는 두 가지 레이아웃을 인식합니다:
노드 + 엣지 섹션 – Quantickle에서 사용하는 내보내기 형식으로, 데이터를 수동으로 준비할 때 가장 안전한 옵션입니다. 파일에는 노드 테이블, 빈 행, 엣지 테이블 순서로 포함됩니다: ```csv node_id,node_label,node_type,node_size,node_color,node_x,node_y srv-1,Gateway,server,40,#2dd4bf,100,250 cli-1,Analyst,client,28,#38bdf8,320,210
source,target,label,weight,type srv-1,cli-1,allows,1,connection
추가 열은 허용됩니다. 임포터는 Node Label, nodeLabel 또는 label과 같은 헤더를 정규화하고, 명시적인 color/size 값을 보존하며, 좌표가 제공된 경우 이를 유지합니다.
source 및 target 열을 포함하는 최소한의 CSV입니다. label, type, weight, source_type, target_type, source_label 또는 color와 같은 선택적 열은 있는 경우 생성된 노드와 엣지에 병합됩니다: ```csv
source,target,label,source_type,target_type
srv-1,cli-1,allows,server,client
srv-1,sensor-2,monitors,server,sensor
Quantickle은 헤더를 대소문자 구분 없이 파싱하며, snake_case와 공백이 포함된 이름을 모두 허용하고, 빈 행을 자동으로 건너뜁니다.
.edges)일반적인 공백으로 구분된 엣지 쌍을 지원하여 빠른 스켈레톤 그래프를 만들 수 있습니다. 누락된 노드는 자동으로 생성됩니다.```text srv-1 cli-1 srv-1 sensor-2
> **참고:** Excel 통합 문서(`.xlsx`)는 더 이상 지원되지 않습니다. Quantickle에 가져오기 전에 데이터를 CSV로 내보내거나 저장하세요.
#### JSON
`File → Import Data`는 Quantickle에서 생성된 JSON 내보내기 또는 원시 Cytoscape 요소 컬렉션도 허용합니다. 파일에 중첩된 `data` 항목이 있는 `elements`가 포함된 경우, 이는 Quantickle의 내부 구조로 정규화됩니다.
#### Quantickle 그래프 (`.qut`)
`.qut` 파일은 평탄화된 노드 및 엣지 객체를 포함하는 JSON 문서입니다. 최소 그래프는 다음과 같습니다:```json
{
"metadata": { "name": "My graph" },
"nodes": [
{ "id": "srv-1", "label": "Gateway", "type": "server", "size": 40 }
],
"edges": [
{ "id": "srv-1_cli-1", "source": "srv-1", "target": "cli-1", "label": "allows" }
]
}
Legacy files that store nodes/edges inside a data object are still accepted—the loader flattens them automatically and preserves coordinates, classes, and container hierarchy metadata.
When exchanging data with the HTTP API or Neo4j integration, send the same flattened shape used by .qut files:```json
{
"nodes": [
{ "id": "srv-1", "label": "Gateway", "type": "server", "size": 40 }
],
"edges": [
{ "id": "srv-1_cli-1", "source": "srv-1", "target": "cli-1", "label": "allows" }
]
}
선택적 `info` 필드는 여전히 Markdown을 지원하며 사용자 정의 속성과 함께 유지됩니다.
<a id="layouts"></a>
## 레이아웃
Quantickle은 레이아웃을 실용적인 패밀리로 그룹화하여 작업에 적합한 것을 선택할 수 있도록 합니다:
- **Force-directed** (force, cose, fcose) — 탐색적 구조 발견에 적합하며 자연스러운 클러스터링을 원할 때 사용합니다.
- **Hierarchical & flow** (breadthfirst, dagre) — 의존성 트리, 호출 그래프 또는 인과 흐름에 가장 적합합니다.
- **Grid & circle** — 대시보드, 작은 그래프 및 내보내기에 빠르고 결정적인 레이아웃입니다.
- **Time-based** (timeline, timeline-scatter, temporal-attraction) — 시간 순서나 최근성이 중요할 때 사용합니다.
- **Spatial/absolute** (absolute, depth-aware) — 알려진 좌표를 가진 지도형 또는 다이어그램형 레이아웃에 사용합니다.
- **Cluster/radial** (radial-recency) — 유형별 그룹화 또는 최근 고리(recency rings)를 원할 때 사용합니다.
### 레이아웃 옵션```javascript
// js/layouts.js
const layoutOptions = {
'force': {
name: 'force',
animate: true,
randomize: false,
infinite: false
},
'grid': {
name: 'grid',
rows: undefined,
cols: undefined
}
// ... more layouts
}
사용자 정의 timeline 레이아웃은 시간 축을 따라 노드를 배치합니다. barStyle 옵션을 통해 중앙 막대를 사용자 정의할 수 있습니다:```javascript
cy.layout({
name: 'timeline',
barStyle: {
color: '#3498db', // bar color
height: 15, // bar height in pixels
className: 'my-timeline-bar' // optional CSS class
}
}).run();
`className`이 제공되면 타임라인 막대가 해당 클래스를 받고 기본 색상 및 높이 스타일이 제거되므로 CSS로 타겟팅할 수 있습니다.
### 방사형 최근성 레이아웃
`radial-recency`를 사용하여 가장 최신 항목을 중앙에 가깝게, 오래된 항목을 바깥쪽 링에 배치합니다. 레이아웃은 각도를 보조 속성(유형/클러스터/그룹)에 매핑하여 관련 노드가 원 주위에 정렬되도록 합니다. 몇 가지 옵션으로 링을 조정할 수 있습니다:```javascript
cy.layout({
name: 'radial-recency',
ringThickness: 140, // radial spacing between time rings
minSeparation: 80, // minimum distance between neighbors along a ring
angleJitter: 0.15, // optional jitter (radians) to break perfect symmetry
angleStrategy: 'grouped' // or 'alphabetical' for deterministic ordering
}).run();
See graphs/radial_time_rings.qut for a small fixture that demonstrates concentric time bands grouped by cluster/type metadata.
timeline-scatter 레이아웃을 사용하여 타임스탬프를 x 위치에 직접 매핑하고 유사성, 카테고리 또는 커뮤니티에 따라 노드를 수직으로 분산시킵니다. 두 축에 대해 조정 가능한 스케일과 중복을 줄이기 위한 선택적 지터를 지원합니다:```javascript
cy.layout({
name: 'timeline-scatter',
xScale: 0.5, // pixels per millisecond (auto-calculated when omitted)
yScale: 60, // spread for similarity/category lanes
jitter: 4, // optional per-node jitter to minimise overlap
barStyle: { // applied when timeline bars already exist
color: '#222',
height: 12,
className: 'scatter-bar'
}
}).run();
Nodes with numeric similarity scores (`similarity`, `similarityScore`, or `similarity_score`) are centred around the mean, while categorical or community labels create evenly spaced lanes along the y-axis.
### Temporal Attraction Layout
Use timestamp distance to steer spring strengths while keeping repulsion light:```javascript
cy.layout({
name: 'temporal-attraction',
timeMode: 'gaussian', // or 'bucket'
timeSigma: 60 * 60 * 1000, // Gaussian falloff window (in ms)
bucketSize: 24 * 60 * 60 * 1000, // bucket size when using bucket mode
repulsionStrength: 12 // minimal node repulsion
}).run();
Select Layout → Temporal Attraction - Time Weighted in the UI or pass name: 'temporal-attraction' through the CLI/API layout configuration to enable it.
Quantickle은 외부 시스템에서 데이터를 가져오거나 동기화할 수 있습니다. 통합은 일반적으로 자격 증명, 프록시 규칙 또는 지속성이 필요하기 때문에 서버를 통해 이루어집니다.
http://localhost:3000으로 UI를 실행합니다.자세한 연습 및 스크린샷은 사용 가이드를 참조하세요.
.qut로 저장하여 전체 충실도 프로젝트 스냅샷(레이아웃, 메타데이터, 컨테이너)을 만듭니다.Quantickle은 js/main.js에 정의된 전역 window.QuantickleApp을 통해 초기화됩니다. DOM이 준비되면 애플리케이션이 자동으로 window.QuantickleApp.init()을 호출합니다.
// js/config.js const config = { performance: { nodeLimit: 1000, // Max nodes to render at once batchSize: 100, // Nodes to add per batch webgl: true, // Enable WebGL rendering hideEdgesOnViewport: false // Hide edges while dragging } }
<a id="api"></a>
## API
### HTTP API
Express 서버(`server.js`)는 정적 프론트엔드를 제공하며 UI에서 사용되는 여러 JSON 엔드포인트를 노출합니다. 모든 경로는 `/api` 접두사로 시작합니다:
| 메소드 및 경로 | 설명 |
| --- | --- |
| `GET /api/domain-files` | `assets/domains/`에 존재하는 JSON 도메인 정의 목록을 표시합니다. |
| `GET /api/examples` | 번들된 예제 `.qut` 그래프에 대한 메타데이터를 반환합니다. |
| `GET /api/serpapi` | Google 검색 요청을 SerpApi로 프록시합니다. 쿼리 문자열 또는 환경 변수에 `SERPAPI_API_KEY`가 필요합니다. |
| `GET /api/openai/models` | OpenAI 모델 목록 요청을 `api.openai.com`으로 프록시합니다. `Authorization: Bearer ...` 헤더가 필요합니다. |
| `GET /api/proxy?url=…` | 허용된 호스트로 HTTP/HTTPS 요청을 브라우저 유사 헤더와 함께 전달합니다. |
| `POST /api/neo4j/graph` | 그래프를 Neo4j에 저장합니다. 위에서 설명한 평탄화된 Quantickle 그래프 JSON 본문을 허용합니다. |
| `POST /api/neo4j/node-graphs` | 제공된 `labels` 배열과 일치하는 노드를 포함하는 저장된 그래프를 찾습니다. |
| `GET /api/neo4j/graphs` | Neo4j에 저장된 그래프를 요약 메타데이터와 함께 나열합니다. |
| `GET /api/neo4j/graph/:name` | 저장된 그래프를 가져와 `metadata`, `nodes`, `edges`를 반환합니다. |
| `DELETE /api/neo4j/graph/:name` | Neo4j에서 저장된 그래프를 제거합니다. |
모든 Neo4j 엔드포인트는 `X-Neo4j-Url`, `X-Neo4j-Username`, `X-Neo4j-Password` 헤더(또는 서버의 `NEO4J_URL`, `NEO4J_USER`, `NEO4J_PASSWORD` 환경 변수)를 통해 자격 증명을 허용합니다. 제공되면 `metadata` 객체가 그래프와 함께 저장되며 `savedAt` 타임스탬프가 자동으로 추가됩니다.
<a id="api-keys"></a>
### API 키
일부 기능에는 API 키가 필요합니다. 이 키는 통합 패널을 통해 브라우저의 로컬 저장소에 저장됩니다.
- **SerpAPI** — RAG 파이프라인의 웹 검색에 필요합니다. 통합 대화상자에서 키를 추가하면 클라이언트 측 RAG 파이프라인에서 사용됩니다.
- **VirusTotal** — 도메인/IP/파일/URL 노드를 보강하고 관계 그래프를 가져오는 데 사용됩니다.
- **CIRCL-LU** — MISP 피드에 필요한 경우 선택적 인증 자격 증명입니다.
명령줄 사용의 경우 환경 변수에 `SERPAPI_API_KEY`를 설정할 수도 있습니다.
<a id="backend-proxy"></a>
### 백엔드 프록시
서버는 프록시 허용 목록에 있는 호스트로 HTTP(S) 요청을 전달하는 CORS 우회 프록시를 제공합니다. URL 매개변수와 함께 `/api/proxy`를 사용하세요:```
curl "http://localhost:3000/api/proxy?url=https%3A%2F%2Fopentip.kaspersky.com%2F"
기본 허용 목록은 config/proxy-allowlist.json에 위치합니다. 서버를 시작하기 전에 이 파일을 제공하거나 쉼표로 구분된 PROXY_ALLOWLIST 환경 변수를 설정해야 합니다. 그렇지 않으면 프록시가 치명적인 구성 오류를 기록하고 모든 요청을 HTTP 403으로 거부합니다.
통합 관련 호스트(OpenAI 및 VirusTotal과 같은 백엔드 통합 어댑터용)는 config/integration-allowlist.json(또는 INTEGRATION_ALLOWLIST)에 의해 관리됩니다. 실행 시 두 허용 목록이 병합됩니다. 각 항목은 프록시가 접근할 수 있는 호스트 또는 와일드카드 패턴을 나열해야 합니다. *를 사용한 와일드카드는 항목 내 어디에서나 지원되므로 *.example.com은 example.com의 모든 하위 도메인을 허용하며, news-*와 같은 마스크도 예상대로 작동합니다. 하위 도메인은 상위 도메인의 항목을 상속받으므로 example.com을 추가하면 자동으로 www.example.com이 허용됩니다.
최소 허용 목록 파일은 다음과 같습니다:```json { "allowlist": ["otx.alienvault.com", "feeds.example.org"] }
환경 변수를 선호한다면 서버를 시작하기 전에 `PROXY_ALLOWLIST="otx.alienvault.com,feeds.example.org"`를 설정하세요.
프록시가 요청을 전달할 때 이제 브라우저와 유사한 헤더 세트(최신 Chrome `User-Agent`, `Accept`, `Accept-Language`, `Sec-Fetch-*` 값 포함)를 보내므로, 안티봇 필터 뒤에 콘텐츠를 게이트하는 사이트가 일반 페이지 로드와 동일한 방식으로 응답합니다. 이러한 헤더는 필요할 때 클라이언트 요청에서 `x-proxy-<header>` 재정의를 제공하여 재정의할 수 있습니다.
<a id="storage"></a>
## 저장소
Quantickle은 작업 중에 브라우저에 그래프 상태를 유지하다가 내보내기 또는 동기화 시 저장합니다.
- **브라우저 저장소** — 설정 및 API 키는 브라우저에 로컬로 저장됩니다.
- **프로젝트 파일(`.qut`)** — 작업 공간 폴더에 저장되어 완전한 충실도의 그래프 스냅샷을 제공합니다. 작업 공간 규칙 및 파일 수명 주기는 [GRAPH_FILE_MANAGEMENT_README.md](https://github.com/rsac-labs/quantickle/blob/main/GRAPH_FILE_MANAGEMENT_README.md)를 참조하세요.
- **Neo4j** — 협업 및 검색을 위한 선택적 서버 측 영구 저장소로, Neo4j 통합을 통해 구성됩니다.
<a id="project-structure"></a>
## 프로젝트 구조```
quantickle/
├── assets/ # Static assets
│ ├── backgrounds/ # Background graphics
│ ├── icons/ # Mostly empty now; icons are colocated with node types
│ ├── domains/ # Node type definitions
│ ├── help/ # Help pages
│ ├── examples/ # Example graphs
│ └── css/ # Stylesheets referenced by index.html
├── config/ # Proxy allowlist
├── data_retrieval/ # SerpAPI/web search helpers used by the RAG pipeline
├── graphs/ # Workspace folder for bundled and test .qut graphs
├── js/ # Front-end source modules
│ ├── main.js # Application bootstrap
│ ├── ai-input-manager.js # Currently unused
│ ├── api.js # HTTP client for server endpoints
│ ├── graph.js # Graph rendering and management
│ ├── graph-manager.js # High-level graph state orchestration
│ ├── graph-reference-resolver.js # Normalization of graph references
│ ├── layouts.js # Layout registration and options
│ ├── 3d-globe-layout.js # 3D Layout
│ ├── absolute-layout.js # Absolute coordinate layout
│ ├── custom-layouts.js # Other custom layouts
│ ├── aggressive-performance-fix.js # Aggressive Performance Fix for Large Graph Panning
│ ├── non-invasive-performance-fix.js # Non-Invasive Performance Fix for Large Graphs
│ ├── lod-system.js # Level of Detail (LOD) System
│ ├── auto-refresh.js # Auto-refresh functionality when new data arrives
│ ├── config.js # Default settings
│ ├── domain-loader.js # Loading and managing domain-specific node type configurations
│ ├── edge-editor.js # Editing edge styles
│ ├── extensions.js # Loading and registration of Cytoscape extensions
│ ├── integrations.js # Configuration and connection to external services
│ ├── rag-pipeline.js # Handles AI-assisted data ingestion
│ ├── secure-storage.js # Encrypts sensitive values in sessionStorage
│ ├── source-editor.js # Editor for the JSON graph source
│ ├── tables.js # Data table updates, filtering, and display
│ ├── ui.js # User interface interactions and notifications
│ ├── validation.js # Validation of all data inputs
│ ├── workspace-manager.js # Workspace file functionality
│ ├── utils.js # Shared browser utilities
│ ├── integrations/ # Integration-specific helpers (MISP/CIRCL-LU, etc.)
│ └── features/ # Feature modules (node editor, callouts, timeline, ...)
├── tests/ # Automated regression tests covering UI flows, imports, and APIs
├── utils/ # Node helpers (Neo4j client, readability shim, CLI scripts)
├── public/
│ ├── index.html # Static front-end
│ └── favicon.ico # Main app icon
├── package.json # Node dependencies and scripts
└── server.js # Express server exposing the HTTP API
그래프가 렌더링되지 않음
성능 저하
레이아웃 문제
이 프로젝트는 공식 저장소로 활발히 유지보수되지 않습니다. PR은 무시될 가능성이 높습니다. 그러나 피드백, 버그 신고 및 의견은 환영합니다.
이 프로젝트는 Apache 2.0 라이선스에 따라 사용 허가되었습니다. 자세한 내용은 LICENSE 파일을 참조하세요.