본문 바로가기
🤖 1인 에이전트 구축기

n8n 동시성·배치 처리 성능 측정 설계와 기록표

by BRIEFER 2026. 6. 12.

n8n 워크플로우가 느릴 때 바로 병렬 실행을 늘리면 해결되는 것은 아닙니다. 외부 API의 제한, 데이터베이스 연결 수, 작업 순서, 재시도 정책이 함께 바뀌기 때문입니다. 이 글은 특정 배수의 성능 향상을 약속하지 않고, 동시성·배치·rate limit·오류 처리를 분리해 설계하고 동일한 조건으로 전후를 측정하는 방법을 정리합니다.

핵심은 다음 세 가지입니다.

  1. 한 번에 처리할 작업 수와 한 요청에 묶을 항목 수는 서로 다른 설정입니다.
  2. 외부 API를 호출한다면 속도보다 먼저 rate limit과 재시도·실패 처리를 정해야 합니다.
  3. 변경 효과는 TPS 하나가 아니라 처리 시간, 오류율, 재시도 수, P95/P99 지연을 같은 조건에서 비교해야 합니다.

이 원고에는 n8n 운영 인스턴스나 외부 API를 연결한 실측 결과가 없습니다. 따라서 수치 결과는 측정 필요로 남기고, 공식 문서에 나온 기능과 로컬에서 실행할 수 있는 측정 기록 형식만 제시합니다.

이 글의 범위는 동시성·배치 변경의 측정 설계와 기록표입니다. 오류 복구·재시도 예산·대체 경로 계약은 오류 처리와 대체 경로 설계에서, LLM 호출 비용·쿼터 회계는 비용 한도와 실제 사용량 정산에서 별도로 다룹니다.

1. 먼저 병목 유형을 나누기

다음 질문에 답하면 설정을 잘못 바꾸는 일을 줄일 수 있습니다.

관찰 먼저 확인할 것 가능한 대응
요청이 순서대로 오래 대기 작업을 직렬로 처리하는지 작은 배치, 독립 단계 분리
외부 API가 429를 반환 서비스별 rate limit과 Retry-After 배치·대기·재시도 조정
실행이 자주 실패 마지막 실행 노드와 오류 유형 Error Workflow, 오류 분기
데이터베이스가 병목 연결 풀·쿼리·트랜잭션 연결 수와 쿼리 계획 점검
작업 수가 늘면 전체가 불안정 n8n 실행 동시성·worker 자원 제한을 낮춘 기준선부터 측정

비동기라는 단어만으로 응답 시간이 줄어드는 것은 아닙니다. 병렬 작업이 공유 자원에서 대기하거나 재시도가 겹치면 오히려 전체 지연과 실패가 늘 수 있습니다.

2. n8n의 동시성·배치 기능을 구분하기

실행 동시성

먼저 배포 환경을 고정합니다. 아래는 n8n 공식 문서의 범위를 요약한 것이며, Cloud 계정에 self-hosted 설정을 그대로 적용한다는 뜻이 아닙니다.

  • self-hosted regular mode: 기본적으로 production 실행 수를 제한하지 않으며, N8N_CONCURRENCY_PRODUCTION_LIMIT으로 제한을 둘 수 있습니다.
  • self-hosted queue mode: worker가 동시에 처리할 작업 수를 --concurrency로 제어하며, N8N_CONCURRENCY_PRODUCTION_LIMIT과의 우선순위·적용 범위를 운영 버전의 문서에서 확인해야 합니다.
  • n8n Cloud: 이 글의 self-hosted 환경변수·worker 옵션을 적용하지 않고, 계정별 Cloud 동시성 문서를 확인합니다.

Queue mode를 선택한다면 Redis와 데이터베이스 연결, 그리고 main·worker·webhook processor에 동일한 N8N_ENCRYPTION_KEY를 설정하는 조건을 확인합니다. n8n 공식 문서는 queue 실행에 SQLite를 사용하는 구성을 권장하지 않습니다. 이 글에서는 해당 인프라를 실제로 구성하거나 측정하지 않습니다(동시성 제어 공식 문서, Queue mode 공식 문서).

동시성을 올리기 전에 다음 값을 기록합니다.

  • n8n 배포 방식과 queue mode 사용 여부
  • worker 수와 각 worker의 동시성 제한
  • 워크플로우 1회가 소비하는 외부 API 요청 수
  • 데이터베이스 연결 풀과 타임아웃
  • 기준선의 처리 시간·오류율·재시도 수

n8n의 실제 설정 이름과 지원 범위는 배포 방식과 버전에 따라 확인해야 합니다. 화면이나 환경변수를 추측해서 쓰지 말고, 운영 중인 버전의 문서를 확인합니다.

Loop Over Items와 배치

Loop Over Items (Split in Batches)는 입력 항목을 묶어 처리할 때 사용할 수 있는 노드입니다(Loop Over Items 공식 문서). 배치 크기만 바꾼다고 외부 요청 수가 자동으로 줄어드는 것은 아닙니다. downstream 노드와 대상 API가 여러 항목을 하나의 payload로 받는 계약일 때만 요청 수 변화가 생길 수 있습니다. 한 번의 실패가 영향을 주는 범위와 메모리 사용량도 함께 기록합니다.

배치 크기를 정할 때 기록할 항목:

  1. 입력 항목 수
  2. 배치 크기
  3. 배치 사이 대기 시간
  4. 요청당 payload 크기
  5. 실패한 배치의 재처리 방법
  6. API 응답의 페이지네이션·중복 처리 규칙

배치와 동시성은 함께 올리지 않습니다. 먼저 배치 크기 하나를 바꾸고, 같은 입력 fixture로 실행 결과를 비교합니다.

Rate limit과 재시도

n8n 공식 안내는 Retry On Fail 또는 Loop Over Items와 Wait 조합으로 요청 사이에 대기를 둘 수 있다고 설명합니다(rate limit 공식 안내). HTTP Request 노드의 Max Tries와 Wait Between Tries (ms)도 공식 문서에 명시되어 있습니다(HTTP Request 공통 문제).

Retry-After 해석, 지수형 대기, jitter, 상태 코드별 재시도 여부는 n8n이 모든 API에 자동 보장하는 기능이 아닙니다. 제공자 문서와 HTTP 명세를 먼저 확인하고 애플리케이션에서 별도로 구현·측정할 일반 운영 권고입니다(HTTP Retry-After 명세).

재시도는 무한한 성공 장치가 아닙니다.

  • 400 계열 입력 오류는 먼저 입력을 수정합니다.
  • 401·403은 인증·권한을 확인하고 반복 재시도를 막습니다.
  • 429는 서비스 문서의 제한과 대기 지시를 따릅니다.
  • 500·502·503·504는 제한된 횟수와 지수형 대기를 검토합니다.
  • 같은 요청을 다시 보내도 안전한지 idempotency를 확인합니다.

실패한 항목을 성공한 것처럼 표시하지 않도록 status, attempt, error_type, source_id 같은 필드를 남깁니다.

3. 안전한 변경 순서

1단계: 기준선 고정

운영 데이터 대신 합성 fixture 또는 재처리 가능한 비민감 데이터로 먼저 측정합니다.

  • 입력 항목 수를 고정합니다.
  • 같은 API 응답 fixture를 사용하거나 테스트 엔드포인트를 사용합니다.
  • worker 수와 동시성 설정을 기록합니다.
  • 캐시, 네트워크 지역, 실행 시간대처럼 결과에 영향을 주는 조건을 기록합니다.
  • warm-up 실행을 별도로 기록하고, 동일 조건에서 최소 5회 이상 반복해 중앙값과 꼬리 지연을 봅니다. 반복 횟수·timestamp·이상치 처리 규칙을 함께 기록합니다.

2단계: 한 변수만 변경

다음 중 하나만 바꿉니다.

  • 배치 크기
  • 배치 사이 대기 시간
  • 워크플로우 동시성
  • worker 수
  • retry 횟수·대기 방식

여러 값을 동시에 바꾸면 개선 원인을 설명할 수 없습니다.

3단계: 실패 예산 확인

속도가 빨라져도 오류율이나 재시도 수가 증가하면 변경을 채택하지 않습니다. 특히 외부 서비스의 제한을 초과해 다른 사용자의 요청까지 지연시키지 않는지 확인합니다.

4단계: 되돌림 조건 설정

다음 중 하나라도 발생하면 이전 설정으로 되돌립니다.

  • 오류율이 기준선보다 높아짐
  • 중복 처리 또는 누락이 발견됨
  • P95/P99 지연이 허용 범위를 넘음
  • 외부 API의 429 비율이 증가함
  • 데이터베이스 연결 고갈·메모리 압박이 발생함

4. 측정표를 먼저 만들기

항목 기록 방법
측정일시 시간대와 timezone 포함
코드/워크플로우 버전 export 해시 또는 변경 식별자
입력 수 고정된 fixture의 항목 수
동시성·배치 실제 설정값
총 처리 시간 시작·종료 timestamp 차이
처리량 성공 항목 수 / 경과 시간
오류율 실패 항목 수 / 전체 항목 수
재시도 수 attempt 합계와 분포
지연 P50·P95·P99 또는 측정 가능한 대체값
자원 CPU·메모리·DB 연결 관찰값
한계 fixture·네트워크·외부 API 차이

특정 배수나 백분율 같은 성과 표현은 위의 기준선, 입력, 환경, 계산식이 공개될 때만 결과로 쓸 수 있습니다. 그런 자료가 없으면 제목과 본문 모두 측정 방법으로 표현하고 결과는 측정 필요로 남깁니다.

5. 로컬에서 측정 기록 구조 검증하기

아래 코드는 외부 서비스에 연결하지 않고, 합성 실행 기록의 처리량·오류율을 계산합니다. 실제 n8n 성능 결과를 만들어 내는 코드가 아니며, 기록 형식과 계산식을 점검하는 예제입니다.

from __future__ import annotations

from dataclasses import dataclass


@dataclass(frozen=True)
class Run:
    input_count: int
    success_count: int
    elapsed_seconds: float
    retry_count: int


def summarize(run: Run) -> dict[str, float]:
    if run.input_count <= 0:
        raise ValueError("input_count must be positive")
    if run.elapsed_seconds <= 0:
        raise ValueError("elapsed_seconds must be positive")
    if not 0 <= run.success_count <= run.input_count:
        raise ValueError("success_count must be within input_count")
    if run.retry_count < 0:
        raise ValueError("retry_count must not be negative")
    return {
        "successful_items_per_second": run.success_count / run.elapsed_seconds,
        "error_rate": (run.input_count - run.success_count) / run.input_count,
        "retry_count": float(run.retry_count),
    }


if __name__ == "__main__":
    result = summarize(Run(input_count=100, success_count=98, elapsed_seconds=20, retry_count=3))
    assert round(result["successful_items_per_second"], 2) == 4.90
    assert round(result["error_rate"], 2) == 0.02
    assert result["retry_count"] == 3.0
    print(result)

이 검증은 success_count / elapsed_seconds 산술과 입력 경계만 확인하며, 성공하지 않은 항목을 모두 실패로 간주하는 단순한 합성 예제입니다. successful_items_per_second는 n8n의 일반 TPS나 외부 API 성능을 의미하지 않습니다. P95/P99를 계산하거나 n8n 실행 데이터를 수집하려면 실행별 timestamp와 동일한 측정 조건을 추가해야 합니다.

이 예제의 합성 출력은 successful_items_per_second=4.9, error_rate=0.02, retry_count=3.0입니다. 이 값은 코드에 넣은 fixture의 산술 결과이며 운영 성능 결과가 아닙니다.

6. 오류 처리와 관찰성

n8n 공식 문서에 따르면 Error Workflow는 Workflow Settings에서 지정하고, 별도 workflow의 첫 노드는 Error Trigger여야 합니다(오류 처리 공식 문서). 이 글에서는 오류 복구 구현 자체가 아니라, 성능 측정에서 오류를 어떻게 기록할지만 다룹니다.

Error Trigger가 실행 컨텍스트에 제공할 수 있는 값과 저장 설정에 따라 달라지는 값은 n8n 버전·실행 유형별로 확인합니다. 다음 중 workflow·실패 노드·실행 식별자·원인 요약은 받을 수 있는 값으로 확인하고, retry_count, source_id, 중복 방지 키와 재처리 기준은 애플리케이션이 별도로 기록할 권장 필드로 구분합니다. API 키·개인정보·전체 payload는 보내지 않습니다.

성공과 실패를 같은 결과 테이블에 남기고, 재처리 시 원래 source_id를 기준으로 중복을 막습니다. 오류 복구·재시도 예산의 상세 설계는 entry/27을 사용하고, 이 글에서는 해당 상태의 처리 시간·재시도 수·오류율을 측정합니다.

7. 체크리스트

  • 동시성, 배치, 재시도, worker 수를 서로 다른 항목으로 기록했는가?
  • API별 rate limit과 Retry-After 의미를 확인했는가?
  • 합성 fixture로 기준선을 고정했는가?
  • 한 번에 하나의 변수만 바꿨는가?
  • 처리량뿐 아니라 오류율·재시도·꼬리 지연을 확인했는가?
  • 재시도해도 안전한 작업인지 확인했는가?
  • 개인정보·API 키가 로그와 알림에 포함되지 않는가?
  • 되돌림 조건과 재처리 기준이 있는가?
  • 결과가 없으면 측정 필요로 표시했는가?

공식 자료