# n8n 서버 아키텍처 분석

**TypeScript, 2019~**

TypeScript 기반 워크플로우 자동화 플랫폼. Robota와 동일 기술 스택(TypeScript, pnpm 모노레포). 200+ 내장 통합, Bull Queue 분산 실행, AI 에이전트 루프 지원.

## 레이어 분리

```
CLI Server (Express)              ← HTTP + WebSocket 인프라, @RestController 데코레이터
  │
  ├── WorkflowRunner              ← 모든 실행의 중앙 디스패치 (모드 결정)
  │     │
  │     ├── [Regular Mode]        ← WorkflowExecute 인프로세스 실행
  │     └── [Queue Mode]          ← Bull Queue (Redis) → Worker 프로세스
  │
  ├── WorkflowExecute             ← 핵심 실행 엔진 (노드 그래프 순회)
  │     │
  │     ├── nodeExecutionStack    ← 실행 대기 노드 스택
  │     └── waitingExecution      ← 멀티 입력 대기 맵
  │
  ├── ScalingService              ← Bull 큐 래핑, 워커 분산 관리
  │
  ├── NodeTypes Registry          ← 노드 타입 발견/등록 (package.json 스캔)
  │
  └── Push Service                ← WebSocket/SSE 실시간 스트리밍
```

### 패키지 구조 (pnpm 모노레포)

| 패키지 | 역할 |
|--------|------|
| `@n8n/config` | 데코레이터 기반 환경 변수 매핑 (`GlobalConfig`) |
| `@n8n/db` | TypeORM 엔티티, 리포지토리, 마이그레이션 |
| `@n8n/backend-common` | 라이선스, 에러 처리 등 공유 유틸리티 |
| `@n8n/api-types` | 프론트엔드 설정, API 계약 타입 |
| `n8n-workflow` | `Workflow`, `INode`, `INodeExecutionData` 인터페이스 |
| `@n8n/task-runner` | JS VM 및 Python 서브프로세스 샌드박스 |

### TypeScript 구현 특성

- 전체 백엔드가 TypeScript (pnpm 모노레포)
- 데코레이터 패턴: `@RestController`, `@Service`, `@Get`, `@Post`
- TypeORM으로 데이터 영속성 관리
- DI(의존성 주입) 패턴 사용
- `ControllerRegistry`가 데코레이터 클래스 자동 발견 및 라우트 매핑

## DAG/워크플로우 정의 모델

JSON 워크플로우 — UI에서 편집. 트리거 + 일반 노드 + AI 노드.

```json
{
  "nodes": [
    { "id": "node1", "type": "n8n-nodes-base.httpRequest", "parameters": {...} }
  ],
  "connections": {
    "node1": { "main": [[{ "node": "node2", "type": "main", "index": 0 }]] }
  }
}
```

- 노드와 연결(connections)로 구성
- 연결은 출력 인덱스별 배열 → 대상 노드/입력 인덱스 매핑
- 버전 관리, draft/published 개념 없음 (저장 = 활성)

## 노드/태스크 모델

### INodeType 인터페이스

모든 노드는 `n8n-workflow` 패키지의 `INodeType` 인터페이스를 구현:

```typescript
interface INodeType {
  description: INodeTypeDescription;

  // 일반 노드 실행
  execute?(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;

  // AI 서브노드용 - 에이전트에 기능 공급
  supplyData?(this: ISupplyDataFunctions): Promise<SupplyData>;
}
```

- `execute()`: 일반 노드 실행. 입력 데이터 처리 → 출력 반환.
- `supplyData()`: AI 클러스터 노드의 서브노드 전용. LLM/메모리/도구 기능 공급.

### 노드 유형

| 유형 | 설명 |
|------|------|
| 일반 노드 | `execute()` 구현. 데이터 변환, API 호출 등 |
| 트리거 노드 | 외부 이벤트(웹훅, 크론, 메시지 등)으로 워크플로우 시작 |
| AI 서브노드 | `supplyData()` 구현. LLM, 메모리, 도구를 에이전트에 제공 |

### 노드 등록

- `package.json`의 `n8n.nodes` 배열을 스캔하여 동적 발견
- `NodeTypes` 레지스트리가 런타임에 노드 구현체 접근 제공
- npm 패키지로 커뮤니티 노드 확장 가능

## 실행 모델

### 스택 기반 실행

핵심 데이터 구조:

```typescript
executionData: {
  nodeExecutionStack: IExecuteData[];   // 실행 대기 노드 큐
  waitingExecution: Record<string, IWaitingExecution>;  // 멀티 입력 대기
  waitingExecutionSource: Record<string, IWaitingExecutionSource>;
}
```

### v0 vs v1 실행 순서

| 버전 | 전략 | 스택 동작 | 특성 |
|------|------|----------|------|
| v0 (레거시) | BFS (너비 우선) | LIFO (후입선출) | 각 브랜치의 첫 노드 → 두번째 노드 → ... |
| v1 (n8n 1.0 기본) | DFS (깊이 우선) | FIFO (선입선출, `shift()`) | 각 브랜치를 완전히 실행 후 다음 브랜치 |

### 실행 루프 (`processRunExecutionData`)

1. `nodeExecutionStack`에서 노드 꺼냄
2. `nodeExecuteBefore` 훅 발화
3. 크리덴셜 로드 및 컨텍스트 준비
4. `node.execute()` 또는 `node.supplyData()` 실행
5. 선택적으로 진행 상태 DB 저장 (수동 실행 시)
6. `nodeExecuteAfter` 훅 발화
7. 후속 노드를 `nodeExecutionStack`에 push
8. 필수 입력 누락 노드는 스택에 재push → 지연 실행

### Regular vs Queue 모드

**Regular Mode**:
- `WorkflowRunner.runMainProcess()` → `WorkflowExecute` 인스턴스화 → 현재 프로세스에서 실행

**Queue Mode** (Bull + Redis):

| 프로세스 | 명령어 | 역할 |
|----------|--------|------|
| Main | `n8n start` | UI, REST API, 웹훅, 큐에 작업 엔큐 |
| Worker | `n8n worker` | BullMQ 작업 소비, 워크플로우 격리 실행 |
| Webhook | `n8n webhook` | 프로덕션 HTTP 요청 처리 후 엔큐 |

**Redis Pub/Sub 채널**:
- 커맨드: Main → Workers (실행 중지, 라이선스 리로드)
- 워커 응답: Workers → Main (커맨드 승인)

**동시성**: 워커당 `concurrency` 플래그 (기본 10, 권장 5+). PostgreSQL 필수.

## 데이터 흐름

### INodeExecutionData

```typescript
interface INodeExecutionData {
  json: IDataObject;            // JSON 페이로드 (핵심 데이터)
  binary?: IBinaryKeyData;      // 바이너리 참조 (파일시스템 또는 S3)
  pairedItem?: IPairedItemData; // 소스 아이템 추적 { item, input }
  error?: Error;                // 에러 정보
  metadata?: ITaskMetadata;     // 실행 메타데이터
}
```

- 노드 간 데이터: `INodeExecutionData[][]` (출력 인덱스별 아이템 배열)
- `json`: 구조화된 데이터 (`Record<string, unknown>` 유사)
- `binary`: 바이너리는 참조로 관리 (파일시스템/S3)
- `pairedItem`: 입력↔출력 아이템 매핑 추적 (데이터 리니지)

### waitingExecution (멀티 입력)

- 복수 입력 노드(Merge 등)가 모든 입력을 수신할 때까지 대기
- 입력 도착 시 `waitingExecution` 엔트리에 저장
- 모든 필수 입력 충족 → `nodeExecutionStack`으로 이동

### Robota 대비 데이터 흐름 비교

| 관점 | n8n | Robota |
|------|-----|--------|
| 데이터 단위 | `INodeExecutionData` (JSON + binary + pairedItem) | `TPortPayload` (Record<string, TPortValue>) |
| 바이너리 | `IBinaryKeyData` (파일시스템/S3 참조) | `IPortBinaryValue` (kind, mimeType, uri, assetId) |
| 연결 | connections 맵 (출력 인덱스 → 대상 노드/입력 인덱스) | `IDagEdgeDefinition` (bindings: outputKey → inputKey) |
| 리니지 추적 | `pairedItem` (아이템 레벨) | 엣지 바인딩 (포트 레벨) |

## 상태 관리

명시적 상태 머신 없음. `IRunExecutionData`에 실행 상태 저장:

```
new → running → success / error / canceled
           ↕
        waiting (Wait 노드에 의한 일시 정지)
```

- `resultData.runData`: 노드별 실행 결과 저장
- `waitingExecution`: 멀티 입력 대기 맵
- DB에 실행 상태 저장 (running 마킹 → 완료 시 갱신)

## 스토리지/영속성

| 대상 | 저장소 |
|------|--------|
| 워크플로우 정의 | SQLite 또는 PostgreSQL (TypeORM) |
| 실행 결과 | SQLite 또는 PostgreSQL |
| 자격 증명 | SQLite 또는 PostgreSQL (암호화) |
| 바이너리 데이터 | 파일시스템 또는 S3 |
| 큐 (Queue 모드) | Redis (BullMQ) |

- TypeORM 엔티티, 리포지토리, 마이그레이션 관리
- 큐 모드에서는 PostgreSQL 필수 (SQLite 미지원)

## 서버 API

### 데코레이터 기반 REST API

3티어 패턴: `@RestController('/path')` → `@Service` (비즈니스 로직) → TypeORM Repository

- `ControllerRegistry`: 데코레이터 클래스 자동 발견, 라우트 매핑, 미들웨어 체인
- 미들웨어 체인: 인증 → 인가 → 레이트 리미팅 → 라이선스 검사 (라우트별)
- `InstanceSettings.instanceType`('main', 'worker', 'webhook')에 따라 엔드포인트 선택적 노출

### 주요 엔드포인트 그룹

- 워크플로우 CRUD
- 실행 트리거/조회
- 자격 증명 관리
- 사용자/권한 관리
- 태그, 변수 관리

## 이벤트/진행 보고

### Push Service

- `N8N_PUSH_BACKEND`: SSE 또는 WebSocket 선택 (n8n 1.0부터 WebSocket 기본)
- `Push` 서비스가 브라우저에 실시간 업데이트 전달
- `MessageEventBus`가 실행 로그/노드 출력 스트리밍

### sendChunk API

```typescript
sendChunk(details: SendChunkInput)
```

**청크 타입**:
- `begin` / `end`: 실행 시작/종료
- `node-execute-before` / `node-execute-after`: 노드 실행 전/후
- `error`: 에러 발생
- `item`: 아이템 데이터
- `tool-call-start` / `tool-call-end`: AI 도구 호출 시작/종료

**큐 모드**: 워커가 `send-chunk` 메시지를 ScalingService(Bull pubsub)를 통해 메인으로 전달.

## 에러 처리 & 재시도

### continueOnFail (노드별)

| 설정 | 동작 |
|------|------|
| `Continue` | 에러 발생해도 일반 출력으로 계속 |
| `Continue (using error output)` | 에러 출력 경로로 분기 |
| (기본) | 워크플로우 중단 |

**주의**: "On Error"가 Continue면 Retry on Fail 설정이 무시됨.

### Error Workflow

- 별도 에러 워크플로우 (Error Trigger 노드)로 실패 포착
- `WorkflowExecutionService.executeErrorWorkflow()`로 실행
- try/catch로 카스케이딩 실패 방지
- `Stop And Error` 노드로 의도적 실패 트리거 가능

### AbortController 기반 취소

- `ActiveExecutions` 서비스가 실행 중 워크플로우 추적/취소
- 큐 모드: Main → Worker로 `abort-job` 커맨드 전송

### 타임아웃

- 워크플로우 레벨 타임아웃 설정 가능
- 타임아웃 초과 시 강제 중단

## 캐싱

**명시적 캐싱 없음** — 매 실행마다 전체 수행.

- 실행 결과 캐싱/재사용 메커니즘 없음
- 크리덴셜, 노드 메타데이터 등은 메모리 캐싱

## 특이점

### AI 에이전트 루프 (EngineRequest/Response)

에이전트 노드가 도구를 사용해야 할 때의 실행 패턴:

```
Agent 실행 → EngineRequest 반환 (도구 실행 요청)
  → 실행 엔진이 인터셉트
  → handleRequest()로 도구 스케줄링/실행
  → 도구 결과를 EngineResponse로 수집
  → 에이전트에 전달하여 재개
  → 최종 출력 (또는 추가 EngineRequest로 루프)
```

**클러스터 노드 구조**:
- 루트 노드: Tools Agent (`agentLangchain`) — LangChain 기반
- 서브노드들이 `AiTool` 커넥션으로 연결:
  - LLM 모델 노드 → `supplyData()`로 모델 제공
  - 메모리 노드 → `supplyData()`로 대화 컨텍스트 제공
  - 도구 노드 → `supplyData()`로 외부 API/함수 제공

### Robota와의 공통점

1. TypeScript + pnpm 모노레포
2. JSON 기반 워크플로우 정의
3. UI에서 편집 → 서버에서 실행
4. 바이너리 데이터 참조 방식
5. WebSocket/SSE 실시간 스트리밍

### Robota와의 차이점

| 관점 | n8n | Robota |
|------|-----|--------|
| 아키텍처 추상화 | 직접적, 암묵적 레이어 | 포트/어댑터, 명시적 계약 |
| 상태 머신 | 없음 (이벤트 기반 추적) | 명시적 FSM (DagRun, TaskRun) |
| 에러 모델 | 예외 기반 + continueOnFail | Result<T,E> 기반 (No Fallback) |
| 분산 실행 | Bull Queue + Redis (프로덕션 검증) | IQueuePort 추상화 (구현체 교체 가능) |
| 노드 등록 | package.json 스캔 + 동적 임포트 | INodeManifest + Registry |
| DI | 데코레이터 기반 서비스 주입 | 생성자 기반 포트 주입 |
| 캐싱 | 없음 | 없음 (동일) |
| 비용 추정 | 없음 | estimateCost + RunCostPolicyEvaluator |
| AI 지원 | EngineRequest/Response 루프 | 없음 (노드 레벨에서 처리) |
