TRENDSHIFT #21 딥다이브 · 2026-06-04

Flowsint 딥다이브
— 엔티티를 그래프로 잇는 오픈소스 OSINT 수사 플랫폼

도메인 하나, 이메일 하나, 닉네임 하나에서 출발해 연결된 단서들을 그래프로 펼쳐 보여주는 자체 호스팅 조사 도구입니다. 점(노드)을 찍으면 엔리처(enricher)가 자동으로 관련된 점들을 캐내 선으로 잇고, 화면 위에서 수사 보드가 살아있는 관계도처럼 자라납니다. 사이버보안 분석가·기자·사기 조사팀을 위해 만들어졌고, 모든 데이터는 내 컴퓨터에만 저장됩니다. (저장소: reconurge/flowsint · TypeScript+Python · ★4,986 · TrendShift 21위 · Apache-2.0)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

이 레포가 무엇을 하는 물건인가.

핵심 메시지

"형사 드라마의 벽에 붙은 사진과 빨간 실 —
그걸 코드로, 자동으로 만들어주는 도구."

수사물에서 형사가 용의자·장소·전화번호 사진을 벽에 붙이고 실로 잇는 장면을 떠올려 보세요. Flowsint는 바로 그 보드를 디지털로 옮긴 것입니다. 다만 실을 사람이 직접 잇는 대신, "이 도메인과 연결된 IP를 찾아줘" 같은 자동 도구(엔리처)가 새 단서를 캐내 선을 그어줍니다.

Flowsint는 OSINT (Open Source Intelligence, 공개 출처 정보) 조사를 위한 그래프 기반 수사 플랫폼입니다. OSINT란 누구나 접근할 수 있는 공개된 정보(WHOIS 등록 정보, DNS 기록, 공개 SNS 계정, 유출된 데이터베이스 목록 등)를 모아 의미 있는 그림을 그리는 활동을 말합니다. 해킹이 아니라, 이미 공개된 조각들을 잘 엮는 것이 핵심입니다.

사용 방식은 단순합니다. 화면에 도메인·이메일·IP 같은 엔티티(entity, 조사 대상이 되는 객체) 노드를 하나 놓고, 그 노드에서 엔리처를 실행하면 관련된 새 노드들이 그래프에 붙습니다. 이 과정을 반복하면 처음엔 점 하나였던 화면이 수백 개의 노드와 관계선으로 이루어진 관계 지도로 자라납니다.

용어
Enricher (엔리처 · "단서 증식기")
엔티티 하나를 입력받아 관련된 다른 엔티티들을 찾아 그래프에 추가하는 자동 모듈. 예를 들어 도메인을 넣으면 그 도메인의 서브도메인·IP·등록자 정보를 캐냅니다. "씨앗 하나를 심으면 가지가 뻗는다"는 비유가 가장 가깝습니다.

2왜 주목받는가

트렌딩 이유 · 경쟁 대비 장점.

OSINT 그래프 도구의 대명사는 오랫동안 상용 소프트웨어인 Maltego였습니다. 강력하지만 비싸고, 데이터가 외부 서버를 거치는 구조라 민감한 조사에는 부담이 있었습니다. Flowsint는 완전 오픈소스 + 자체 호스팅(self-hosted)으로 이 빈자리를 노립니다 — 내 컴퓨터에서 Docker로 띄우면 끝이고, 데이터는 한 발짝도 밖으로 나가지 않습니다.

두 번째 강점은 확장성입니다. 엔리처가 도메인·IP·ASN·이메일·전화번호·암호화폐 지갑·SNS 닉네임 등 30종 이상 내장돼 있고, 모듈식 구조라 새 엔리처를 코드로 쉽게 추가할 수 있습니다. 세 번째는 성능 — 프론트엔드가 WebGL 렌더링(pixi.js)을 써서 노드가 수천 개로 불어나도 화면이 버벅이지 않습니다.

비교 항목기존 방식 (Maltego 등 상용)Flowsint의 접근
비용/접근유료 라이선스 · 클라우드 의존오픈소스(Apache-2.0) · 무료 · 자체 호스팅
데이터 프라이버시외부 서버 경유 가능전부 내 머신에 저장 — 외부 유출 없음
확장플러그인 SDK(폐쇄적일 수 있음)모듈식 파이썬 엔리처 — 코드로 자유 추가
대규모 그래프노드 많아지면 느려짐WebGL(pixi.js) 렌더로 수천 노드도 매끄럽게
기존 방식의 한계
민감한 조사일수록 "데이터를 어디 두느냐"가 문제

기자나 사기 조사팀이 다루는 단서는 그 자체가 극도로 민감합니다. 조사 내용이 제3자 클라우드를 거치면, 누가 무엇을 조사 중인지가 새어나갈 위험이 생깁니다.

Flowsint의 해결
"전부 내 컴퓨터에" — 프라이버시 우선 설계

Docker로 로컬에 통째로 띄우는 구조라, PostgreSQL·Neo4j·조사 데이터가 모두 내 디스크에만 남습니다. README도 "OSINT 조사엔 높은 수준의 프라이버시가 필요하다"고 명시하며 이 점을 전면에 내세웁니다.

3기술 스택 전체 지도

프론트엔드·백엔드·데이터·인프라를 한눈에.

Flowsint는 TypeScript 프론트엔드 + Python 백엔드의 조합입니다. 언어 비중도 거의 반반(TS 약 153만 줄, Python 약 128만 줄)이라 어느 한쪽이 곁다리가 아니라 둘 다 본체입니다. 가장 독특한 점은 데이터베이스를 둘 쓴다는 것 — 관계형 DB(PostgreSQL)와 그래프 DB(Neo4j)를 역할에 따라 나눠 씁니다.

레이어기술 / 버전역할
프론트엔드React 19 + Vite 5화면 렌더링·빌드. React Compiler로 자동 최적화.
그래프 UI@xyflow/react · react-force-graph-2d · pixi.js노드/엣지 편집 + 힘기반 자동 배치 + WebGL 고속 렌더.
UI 부품Radix UI · Tailwind 4 · framer-motion접근성 좋은 컴포넌트 + 스타일 + 애니메이션.
상태/데이터TanStack Query · Zustand · Zod서버 데이터 캐싱 · 전역 상태 · 스키마 검증.
보조 도구Monaco · Tiptap · xterm.js · AI SDK코드 에디터 · 노트 · 터미널 · AI 조사 보조 채팅.
백엔드 APIFastAPI (Python)REST API·인증·이벤트 스트리밍. uvicorn으로 구동.
비동기 작업Celery + Redis오래 걸리는 스캔을 백그라운드에서 실행.
타입/모델Pydantic엔티티(도메인·IP·이메일…) 데이터 모델 정의.
데이터 (관계형)PostgreSQL 15계정·인증·메타데이터. Alembic으로 마이그레이션.
데이터 (그래프)Neo4j 5 + APOC엔티티 간 관계. Cypher 쿼리로 탐색.
인프라Docker Compose · Make전 서비스 컨테이너화 · 명령 단축.
용어
Graph Database (그래프 데이터베이스 · Neo4j)
데이터를 "표의 행"이 아니라 "점(노드)과 선(관계)"으로 저장하는 DB. "A가 B를 소유한다", "이 IP가 저 도메인을 가리킨다" 같은 연결이 1급 시민입니다. OSINT처럼 "누가 누구와 어떻게 엮여 있나"가 본질인 데이터에 딱 맞습니다. 표 기반 DB에서 이런 관계를 따라가려면 JOIN을 수십 번 해야 하지만, 그래프 DB는 선을 따라 걷기만 하면 됩니다.
용어
Celery + Redis (작업 큐 · "주문 접수대와 주방")
서브도메인 열거나 유출 DB 조회 같은 작업은 수 초~수 분이 걸립니다. 이걸 웹 요청 안에서 처리하면 화면이 멈춥니다. 그래서 Celery(일꾼)가 Redis(주문판)에 쌓인 작업을 하나씩 꺼내 백그라운드에서 처리하고, 끝나면 결과만 화면에 흘려보냅니다. 식당으로 치면 주문을 접수대(Redis)에 붙여두고 주방(Celery worker)이 차례로 요리하는 구조입니다.
용어
React Flow (@xyflow/react · 노드 그래프 편집기)
드래그로 옮기고 선으로 잇는 "노드 캔버스"를 만들어주는 React 라이브러리. Flowsint의 수사 보드 화면이 이 위에서 돌아갑니다. 노드가 아주 많아질 때를 대비해 pixi.js(WebGL) 렌더링을 함께 써서 속도를 확보합니다.

4아키텍처 심화 분석

데이터가 어디서 어디로 흐르는가.

Flowsint는 다섯 개의 독립 모듈로 쪼갠 모듈식 모노레포(modular monorepo)입니다. 하나의 저장소 안에 여러 패키지를 두되, 서로의 의존 방향을 한 줄기로 고정한 것이 특징입니다. 위층은 아래층을 알지만 아래층은 위층을 모릅니다 — 덕분에 엔리처(아래층)를 고쳐도 화면(위층)이 깨지지 않습니다.

┌──────────────────────────────────────────────────────────┐ │ Flowsint │ │ │ │ flowsint-app ─── 화면(React 19 + React Flow + WebGL) │ │ │ REST / 이벤트 스트림 │ │ ▼ │ │ flowsint-api ─── FastAPI 서버(라우트·인증·스키마) │ │ │ 작업 의뢰 │ │ ▼ │ │ flowsint-core ─── 오케스트레이터·Celery·Vault·DB 연결 │ │ │ 엔리처 호출 │ │ ▼ │ │ flowsint-enrichers ─ 스캔 로직(WHOIS·DNS·Maigret·유출…) │ │ │ 타입 사용 │ │ ▼ │ │ flowsint-types ─── Pydantic 모델(도메인·IP·이메일…) │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Postgres │ │ Neo4j │ │ Redis │ ← 데이터 계층 │ │ │ (계정) │ │ (그래프) │ │ (작업큐) │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └──────────────────────────────────────────────────────────┘

구조가 한눈에 안 들어와도 괜찮습니다. 흐름 한 줄기를 끝까지 따라가 보면 전체가 잡힙니다. "사용자가 도메인 노드에서 '서브도메인 찾기' 엔리처를 실행했다"는 가장 흔한 동작 하나를 추적해 봅시다.

해피 패스 추적

도메인 → 서브도메인 캐기, 7단계

① 화면(app): 그래프에서 도메인 노드를 우클릭 → "Subdomain Discovery" 선택. React Flow가 클릭을 받아 API로 요청을 보냅니다.

② API(api): FastAPI가 요청을 받아 인증을 확인하고, "이 작업을 시작해달라"고 core에 넘깁니다.

③ 오케스트레이터(core): 작업을 Celery 태스크로 만들어 Redis 큐에 넣습니다. API는 여기서 바로 응답 — 화면은 멈추지 않습니다.

④ 일꾼(core/Celery worker): 큐에서 작업을 꺼내 해당 엔리처를 실행합니다.

⑤ 엔리처(enrichers): 실제 서브도메인 열거 로직이 돌며 결과(새 엔티티 목록)를 만듭니다. 이때 외부 API 키가 필요하면 Vault에서 복호화해 꺼냅니다.

⑥ 그래프 저장(Neo4j): 찾은 서브도메인들을 노드로, "이 도메인의 하위"라는 관계를 엣지로 Neo4j에 기록합니다.

⑦ 화면 갱신(app): 결과 이벤트가 스트리밍으로 프론트에 도착하고, 그래프에 새 노드가 스르륵 붙습니다. 한 점이 여러 점으로 번집니다.

설계 패턴
Vault (시크릿 금고 · 엔벨로프 암호화)
엔리처들이 외부 서비스(유출 DB 조회 등)를 부르려면 API 키가 필요합니다. 이 키를 평문으로 두면 위험하니, Flowsint는 마스터 키(MASTER_VAULT_KEY_V1)로 각 키를 암호화해 보관합니다. 키 이름에 V1이 붙은 건 나중에 마스터 키를 교체(rotation)할 수 있게 버전을 매겨둔 것입니다. 은행 금고를 큰 열쇠 하나로 잠그고, 그 안에 작은 금고들을 또 넣어둔 셈입니다.
한 줄 비유

API는 접수 창구, Core는 관리실, Enrichers는 현장 요원, Neo4j는 사건 보드. 창구가 의뢰를 받아 관리실에 넘기면, 관리실이 현장 요원을 보내 단서를 캐오고, 그 단서를 사건 보드에 핀으로 꽂아 실로 잇습니다. 사용자는 보드(화면)만 보면 됩니다.

5디렉토리 구조 해부

어떤 폴더가 무슨 일을 하나.

루트에는 다섯 개의 flowsint-* 모듈과, 환경별 Docker Compose 파일 세 종, 그리고 모든 명령을 묶어주는 Makefile이 있습니다. 모듈 이름만 봐도 역할이 드러나는 설명적 작명이 이 레포의 관례입니다.

flowsint/ ├── flowsint-app/ 프론트엔드 (React 19 + Vite) ★ │ ├── src/ │ │ └── routeTree.gen.ts TanStack Router 자동 생성 라우트 │ ├── Dockerfile 프로덕션(정적 빌드 서빙) │ ├── Dockerfile.dev 개발(핫리로드) │ └── package.json ├── flowsint-api/ FastAPI 서버 ★ │ ├── app/main.py uvicorn 진입점 (포트 5001) │ ├── alembic/ PostgreSQL 마이그레이션 │ └── Dockerfile ├── flowsint-core/ 오케스트레이터·Celery·Vault·DB 연결 ★ ├── flowsint-enrichers/ 엔리처 모듈(스캔 로직·도구) ★ ├── flowsint-types/ Pydantic 타입 정의 ├── docker-compose.dev.yml 개발 스택 ├── docker-compose.prod.yml 운영 스택(로컬 빌드) ├── docker-compose.yml 기본 개발 스택(인프라 포함) ├── Makefile make dev / prod / deploy … └── ETHICS.md 책임 있는 사용 가이드라인
모듈 / 파일역할
flowsint-app/화면 전부. React Flow 그래프 캔버스, 노드 편집, AI 채팅, 노트 에디터.
flowsint-api/REST API·인증·스키마. 외부에서 들어오는 모든 요청의 관문.
flowsint-core/핵심 ★ — 작업 오케스트레이션, Celery 설정, Vault, Postgres/Neo4j 연결.
flowsint-enrichers/"단서 캐는 로직"이 모인 곳. 새 조사 능력을 더할 땐 여기에 추가.
flowsint-types/도메인·IP·이메일·지갑 등 엔티티의 데이터 모양. 모든 모듈의 공통 어휘집.
routeTree.gen.tsTanStack Router가 파일 구조를 보고 자동 생성하는 라우트 트리(직접 수정 X).

개발 워크플로도 이 구조를 그대로 따릅니다 — 새 타입은 flowsint-types에, 새 엔리처는 flowsint-enrichers에, 새 API는 flowsint-api에. 어디에 무엇을 넣을지가 폴더 이름만으로 정해지니, 초보자가 길을 잃기 어렵습니다.

6학습 포인트 (기술별)

이 레포에서 배울 만한 것 + 어디를 보면 되는지.

포인트 1

관계형 DB와 그래프 DB를 함께 쓰는 법

"왜 DB를 둘 쓰지?"는 그 자체가 좋은 설계 공부거리입니다. 계정·설정처럼 표로 떨어지는 데이터는 PostgreSQL에, 엔티티 간 관계 그물은 Neo4j에 — 데이터 모양에 맞는 도구를 고른 사례입니다. flowsint-core의 DB 연결 코드와 docker-compose의 neo4j 설정을 함께 보면 감이 옵니다.

포인트 2

Celery로 오래 걸리는 작업을 비동기로 빼기

웹앱이 느려지는 흔한 원인은 "느린 작업을 요청 안에서 처리"하는 것입니다. Flowsint는 스캔을 Celery 태스크로 분리해 화면을 멈추지 않게 합니다. flowsint_core.core.celery 워커 설정과 Makefile의 celery 타깃이 출발점입니다.

포인트 3

플러그인형 모듈 설계 (엔리처 패턴)

"입력 엔티티 → 처리 → 출력 엔티티"라는 한 가지 약속을 정해두면, 같은 모양의 모듈을 끝없이 찍어낼 수 있습니다. 30종 넘는 엔리처가 모두 이 패턴을 따릅니다. flowsint-enrichers의 베이스 클래스를 읽으면 "확장 가능한 구조"의 전형을 배웁니다.

포인트 4

고성능 그래프 시각화 (React Flow + WebGL)

노드 수천 개를 부드럽게 그리는 건 의외로 어렵습니다. Flowsint는 React Flow로 상호작용을, pixi.js(WebGL)로 렌더 성능을, d3-force로 자동 배치를 맡깁니다. 프론트 성능 최적화의 살아있는 교본입니다.

엔리처가 어떤 모양인지 감을 잡기 위한 개념 코드입니다(실제 코드가 아니라 패턴을 단순화한 예시):

# 모든 엔리처가 공유하는 약속: 엔티티를 받아 새 엔티티들을 돌려준다
class SubdomainEnricher(BaseEnricher):
    input_type = Domain          # 도메인을 입력으로
    output_type = Domain         # 서브도메인(역시 도메인)을 출력으로

    def run(self, entity: Domain) -> list[Domain]:
        subs = discover_subdomains(entity.name)   # 실제 스캔
        return [Domain(name=s) for s in subs]      # 그래프에 붙을 새 노드들
왜 이 패턴이 강력한가

모든 엔리처가 같은 모양의 입출구를 가지면, 오케스트레이터는 엔리처의 속을 몰라도 "넣고 → 받기"만 하면 됩니다. 콘센트 규격이 같으면 어떤 가전이든 꽂히는 것과 같습니다. 새 능력을 더하는 일이 "콘센트 규격에 맞는 기기 하나 만들기"로 줄어듭니다.

7시스템 요구사항

돌리려면 무엇이 필요한가.

좋은 소식은 전부 Docker로 묶여 있다는 점입니다. 언어 런타임을 일일이 깔 필요 없이, Docker와 Make만 있으면 make prod 한 줄로 다섯 개 서비스가 한꺼번에 뜹니다.

항목요구사항
필수 도구Docker + Make (이 둘이면 실행 끝)
로컬 개발(선택)uv(Python 의존성) · Node.js + yarn(프론트엔드)
구동 서비스PostgreSQL 15 · Neo4j 5 · Redis · API · 프론트엔드 (모두 컨테이너)
주요 포트5173(화면) · 5001(API) · 7474·7687(Neo4j) · 5433(Postgres) · 6379(Redis)
OSmacOS · Linux · Windows (Docker가 도는 곳이면 어디든)
계정기본 계정 없음 — 첫 실행 후 /register에서 직접 생성
# 설치 3줄 — README가 약속하는 가장 빠른 길
git clone https://github.com/reconurge/flowsint.git
cd flowsint
make prod   # → http://localhost:5173/register 에서 계정 생성
주의
운영 환경에선 기본 비밀번호를 꼭 바꾸세요

compose 파일의 Postgres 기본 계정은 flowsint/flowsint이고, Neo4j·인증 시크릿(AUTH_SECRET)·금고 키(MASTER_VAULT_KEY_V1)는 .env로 주입됩니다. 내 PC 실험용이면 괜찮지만, 외부에 노출되는 서버라면 이 값들을 강한 임의값으로 반드시 교체해야 합니다.

8직접 해볼 수 있는 실습 과제

난이도별로 손에 익히는 단계.

시작 전 반드시
합법적·윤리적 사용만

Flowsint는 강력한 정보 수집 도구입니다. 저장소의 ETHICS.md는 무단 감시·괴롭힘·신상털기(doxxing)를 금지합니다. 실습은 내가 소유한 도메인이나 공개 테스트용 대상에만 하세요. 남의 정보를 동의 없이 캐는 것은 불법일 수 있습니다.

실습 1

로컬에 띄우고 첫 그래프 만들기 난이도 ★☆☆ 입문

make prod로 실행 → /register에서 계정 생성 → 내 소유 도메인 노드를 하나 놓고 "DNS Resolution" 엔리처를 돌려본다. 도메인이 IP 노드로 이어지는 첫 관계선을 확인.

실습 2

엔리처 체이닝 관찰 난이도 ★★☆ 중급

도메인 → IP → ASN으로 엔리처를 연달아 실행하며 그래프가 어떻게 번지는지 본다. Neo4j 브라우저(localhost:7474)에 접속해 같은 데이터가 노드/관계로 어떻게 저장됐는지 Cypher로 직접 조회.

실습 3

소스 코드 한 흐름 추적 난이도 ★★☆ 중급

섹션 4의 "7단계 해피 패스"를 실제 코드에서 따라가 본다. flowsint-api의 라우트 → flowsint-core의 Celery 태스크 → flowsint-enrichers의 실행 로직 순으로 파일을 열어 연결고리를 눈으로 잇기.

실습 4

나만의 엔리처 추가 난이도 ★★★ 고급

flowsint-enrichers의 베이스 클래스를 상속해 간단한 엔리처를 하나 만든다(예: 이메일 → 도메인 추출). 타입은 flowsint-types에 정의하고, 테스트는 uv run pytest로. 플러그인 패턴을 몸으로 익히는 단계.

9관련 기술 심화 학습 로드맵

한 주씩 따라가는 계획.

주차주제학습 자료
1주차OSINT·그래프 사고방식 + 로컬 실행README · ETHICS.md · 실습 1
2주차그래프 DB 기초 (Neo4j · Cypher)Neo4j 공식 튜토리얼 · 실습 2
3주차FastAPI + Celery 비동기 백엔드FastAPI 문서 · flowsint-core 정독
4주차엔리처 패턴 · Pydantic 모델링flowsint-enrichers·flowsint-types · 실습 4
5주차React Flow + 대규모 그래프 시각화React Flow 문서 · pixi.js · flowsint-app
6주차Docker Compose 멀티서비스 운영3종 compose 파일 비교 · 리버스 프록시 기초

10핵심 키워드 사전

본문에 나온 용어 빠른 참조.

용어의미
OSINTOpen Source Intelligence. 공개된 정보를 모아 분석하는 조사 기법.
Enricher엔티티 하나를 받아 관련 엔티티를 캐내 그래프에 추가하는 자동 모듈.
Entity조사 대상이 되는 객체(도메인·IP·이메일·전화·지갑 등). 그래프의 노드.
그래프 DB데이터를 노드(점)와 관계(선)로 저장하는 DB. 여기선 Neo4j.
Neo4j / APOC대표적 그래프 DB와 그 확장 라이브러리(APOC). Cypher 언어로 질의.
CypherNeo4j의 질의 언어. "이 노드에서 선을 따라가라"를 패턴으로 표현.
Celery / Redis비동기 작업 큐. 오래 걸리는 스캔을 백그라운드 일꾼이 처리.
FastAPI파이썬 고속 웹 API 프레임워크. 백엔드 관문.
React Flow노드·엣지 캔버스를 만드는 React 라이브러리. 수사 보드의 토대.
Vault외부 API 키를 마스터 키로 암호화해 보관하는 시크릿 금고.
WHOIS도메인 등록자·등록일 등을 조회하는 공개 프로토콜.
ASNAutonomous System Number. 인터넷에서 IP 묶음을 운영하는 조직의 번호.
Maigret닉네임 하나로 수백 개 사이트의 계정 존재 여부를 찾는 오픈소스 도구.
self-hosted외부 클라우드가 아닌 내 서버/PC에서 직접 돌리는 방식.

11참고 링크