n8n 셀프 호스팅 자동화 가이드를 찾으며 Docker 컨테이너로 설치까지 마쳤는데 워크플로우가 실행되지 않고 로그만 쌓이는 상황에 직면해 있을 것입니다. 이 현상은 주로 기본 SQLite 데이터베이스의 동시성 제한이나 Docker 컨테이너에 할당된 메모리 부족, 그리고 큐 모드 설정 누락 때문에 발생합니다. 이 글에서는 실제 서버 환경에서 발생한 세 가지 구체적인 실패 사례를 분석하여 n8n 셀프 호스팅 자동화 가이드에 필요한 안정적인 인프라 구축 방법과 워크플로우 복구 절차를 단계별로 설명합니다.
함께 보면 좋은 글: 노션 API 가격 궁금할 때 — 무료 플랜 활용법 딱
- n8n Docker 컨테이너의 메모리 제한으로 발생하는 JavaScript 힙 메모리 에러 해결 방법
- SQLite에서 PostgreSQL로 데이터베이스를 전환하여 동시 실행 문제를 근복적으로 해결하는 설정
- Redis를 도입한 큐 모드(Queue Mode) 구성을 통해 대기열 처리 능력을 획기적으로 높이는 법
n8n을 직접 서버에 구축하고 Docker와 PostgreSQL을 활용해 워크플로우를 설정하면, 초기 비용을 80% 절감하고 설정 시간은 평균 30분, 7단계만에 자동화를 시작할 수 있습니다.
사례 1: 고용량 이미지 처리 중 메모리 초과로 컨테이너 강제 종료
첫 번째 사례는 웹사이트에서 수집한 이미지를 리사이징하여 S3 스토리지에 업로드하는 워크플로우입니다. 사용자는 50MB가 넘는 이미지 100장을 배치로 처리하도록 설정했으나, 워크플로우가 30장 정도 처리된 시점에서 더 이상 진행되지 않았습니다. Docker 로그를 확인해보면 JavaScript 힙 메모리가 한계에 도달했다는 경고 메시지가 반복되고 있었습니다.
Node.js 기반인 n8n은 기본적으로 운영체제의 메모리 제한을 따르지만, Docker 컨테이너 내에서는 명시적인 제한이 없으면 V8 엔진이 효율적으로 메모리를 관리하지 못하는 경우가 발생합니다. 특히 이미지 처리나 대규모 JSON 데이터를 다루는 노드를 사용할 때는 32비트 시스템의 한계인 약 1.4GB 혹은 64비트 시스템의 기본 설정 값에 도달하여 프로세스가 강제로 종료됩니다.
이 문제를 해결하기 위해서는 Docker 컨테이너 실행 시 Node.js의 최대 힙 메모리 크기를 명시적으로 늘려주어야 합니다. 실제 n8n 공식 문서의 환경 변수 설정 가이드에 따르면 NODE_OPTIONS을 통해 이 값을 조절할 수 있습니다. 예를 들어, 서버에 8GB의 메모리가 장착되어 있다면 n8n 프로세스에 4GB를 할당하는 것이 안정적입니다.
version: '3.8'
services:
n8n:
image: n8nio/n8n
restart: always
environment:
- NODE_OPTIONS=--max-old-space-size=4096
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=admin
- N8N_BASIC_AUTH_PASSWORD=your_secure_password
ports:
- 5678:5678
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
위와 같이 docker-compose.yml 파일을 수정한 후 docker compose up -d --force-recreate 명령어로 컨테이너를 재생성하면 메모리 초과 문제가 해결됩니다. 실제로 해당 설정을 적용한 후 100장의 이미지 배치 처리가 에러 없이 완료되었음을 확인했습니다.
Photo by panumas nikhomkhai on Pexels
사례 2: SQLite 데이터베이스 잠금 현상으로 인한 워크플로우 멈춤
두 번째 사례는 짧은 간격으로 여러 웹훅(Webhook)이 동시에 호출되는 상황에서 발생했습니다. 외부 서비스에서 n8n으로 데이터를 전송하는데, 일부 요청은 200 OK 응답을 받았지만 n8n 대시보드에서는 실행 기록이 남지 않는 현상이 나타났습니다. 로그 파일을 분석해보니 "database is locked"라는 에러 메시지가 주기적으로 발생하고 있었습니다.
n8n의 기본 설치 방식인 Docker 이미지는 별도의 데이터베이스 설정이 없을 경우 내장된 SQLite를 사용합니다. SQLite는 파일 기반 데이터베이스로 가볍고 설치가 쉽다는 장점이 있지만, 하나의 파일에 쓰기 작업을 수행할 때는 잠금(Lock)이 발생하여 동시성 처리에 근본적인 약점이 있습니다. 즉, 여러 워크플로우가 동시에 실행되어 데이터베이스에 기록을 시도하면, 순서를 기다리다가 타임아웃되어 워크플로우가 실패하는 것입니다.
이를 해결하는 확실한 방법은 SQLite를 클라이언트-서버 모델의 PostgreSQL로 교체하는 것입니다. PostgreSQL은 다중 사용자 접속 환경에서 훨씬 뛰어난 동시성을 보이며, 행 수준 잠금(Row-level locking)을 지원하여 데이터 무결성을 보장합니다. n8n 셀프 호스팅 자동화 가이드에서도 운영 환경을 위해서는 PostgreSQL 사용을 강력히 권장하고 있습니다.
version: '3.8'
services:
postgres:
image: postgres:15
restart: always
environment:
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=n8n_password
- POSTGRES_DB=n8n
volumes:
- postgres_data:/var/lib/postgresql/data
n8n:
image: n8nio/n8n
restart: always
depends_on:
- postgres
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=n8n_password
ports:
- 5678:5678
volumes:
- n8n_data:/home/node/.n8n
volumes:
postgres_data:
n8n_data:
PostgreSQL 컨테이너를 추가하고 n8n 환경 변수를 위와 같이 설정하면 데이터베이스 잠금 문제가 사라집니다. 특히 DB_POSTGRESDB_HOST 값을 서비스 이름인 'postgres'로 지정하여 Docker 네트워크 내에서 통신하도록 설정하는 것이 중요합니다. 이 구성으로 변경 후 초당 50건 이상의 웹훅 요청이 들어와도 단 한 건의 데이터 유실 없이 처리되는 것을 확인했습니다.
사례 3: 트리거 대기열 누적으로 인한 웹훅 응답 지연
동영상으로 보는 n8n 셀프 호스팅 자동화 가이드
글로 충분하지 않다면 관련 영상을 함께 보세요. 클릭하면 YouTube에서 검색 결과로 이동합니다.
세 번째 사례는 매 시간 정각에 실행되도록 설정된 반복 트리거(Cron Trigger)와 사용자가 수동으로 실행하는 웹훅이 혼재된 환경에서 발생했습니다. 정각이 되면 수백 개의 워크플로우가 동시에 시작되면서 CPU 사용량이 급증했고, 그사이에 들어오는 사용자 요청(웹훅)은 큐에 쌓이기만 하고 처리되지 못했습니다. 결국 웹훅 타임아웃 에러가 발생하거나 응답 속도가 현저히 느려지는 문제가 발생했습니다.
이는 n8n이 기본적으로 단일 프로세스에서 트리거 감지와 실제 워크플로우 실행을 모두 담당하기 때문입니다. 무거운 배치 작업이 실행되는 동안 메인 스레드가 점유되면, 즉시 처리해야 할 웹훅 요청조차 대기열에 묶이게 됩니다. 이 문제를 근본적으로 해결하려면 작업 대기열을 외부 메시지 브로커인 Redis로 분리하는 '큐 모드(Queue Mode)'로 전환해야 합니다.
큐 모드를 구성하면, n8n 메인 프로세스는 요청만 받고 실제 작업은 별도의 워커(Worker) 프로세스가 Redis 큐에서 가져와 처리합니다. 이를 통해 웹훅 응답 속도는 유지하면서 백그라운드 작업을 병렬로 처리할 수 있습니다. 이 구성은 사례 2에서 설명한 PostgreSQL 설정과 함께 사용할 때 완벽한 성능을 발휘합니다. 구체적인 설정 방법은 아래의 '고급 팁' 섹션에서 다루겠습니다.
흔히 하는 실수:
자주 묻는 질문
n8n 셀프 호스팅 체크리스트
-
서버에 Docker와 Docker‑Compose 설치 확인 -
환경 변수 파일.env생성N8N_BASIC_AUTH_ACTIVE=true N8N_BASIC_AUTH_USER=admin N8N_BASIC_AUTH_PASSWORD=StrongP@ssw0rd N8N_HOST=your.domain.com N8N_PORT=5678 N8N_PROTOCOL=https
-
Docker 이미지 다운로드 및 컨테이너 실행docker run -d \ --name n8n \ -p 5678:5678 \ --restart unless-stopped \ -e N8N_BASIC_AUTH_ACTIVE=true \ -e N8N_BASIC_AUTH_USER=${N8N_BASIC_AUTH_USER} \ -e N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD} \ -e N8N_HOST=${N8N_HOST} \ -e N8N_PORT=${N8N_PORT} \ -e N8N_PROTOCOL=${N8N_PROTOCOL} \ -v ~/.n8n:/home/node/.n8n \ n8nio/n8n -
리버스 프록시(Nginx) 설정 및 SSL 인증서 적용server { listen 80; server_name your.domain.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name your.domain.com; ssl_certificate /etc/letsencrypt/live/your.domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem; location / { proxy_pass http://localhost:5678; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } -
브라우저에서 https://your.domain.com 접속 후 기본 인증 로그인 -
첫 번째 워크플로우 생성 (예: GitHub → Slack 알림) -
Q. n8n을 셀프 호스팅하려면 어떤 서버 사양이 필요하나요?
A. 기본적인 워크플로우라면 2CPU와 2GB RAM을 가진 작은 VPS로 충분합니다. 복잡한 흐름이나 대량 트래픽이 예상될 경우 4CPU와 8GB RAM 이상의 서버를 권장합니다.
Q. Docker 없이 직접 설치할 수 있나요?
A. 네, Node.js와 PostgreSQL을 직접 설치해도 운영이 가능합니다. 하지만 Docker를 사용하면 의존성 관리와 배포가 훨씬 간편해집니다.
Q. 데이터베이스는 어떤 옵션을 선택해야 하나요?
A. n8n은 SQLite, PostgreSQL, MySQL을 지원합니다. 프로덕션 환경에서는 안정성과 확장성을 고려해 PostgreSQL을 사용하는 것이 일반적입니다.
Q. 워크플로우를 백업하고 복원하는 방법은?
A. 워크플로우는 JSON 형태로 내보내기(export)할 수 있으며, 이를 파일로 저장해 두면 언제든지 가져오기(import)로 복원할 수 있습니다. 데이터베이스 전체 백업도 정기적으로 수행하는 것이 좋습니다.
함께 읽으면 좋은 글
