Notice
Recent Posts
250x250
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
관리 메뉴

일상 코딩

[윈도우 개발 환경 설정] 10편: n8n 워크플로우 자동화 설정 본문

Windows 개발환경 세팅

[윈도우 개발 환경 설정] 10편: n8n 워크플로우 자동화 설정

polarcompass 2026. 3. 31. 22:28
728x90

10편: n8n 워크플로우 자동화 설정

시리즈: 윈도우 네이티브 개발 환경 구축 A to Z — 새 PC부터 클라우드 배포까지
이전 편: 9편에서 Docker Compose에 MinIO를 추가하고, 웹 콘솔에서 버킷과 Access Key를 생성한 뒤, Go·Python·JavaScript 세 가지 언어에서 파일 업로드·다운로드를 확인했습니다.


들어가며

서비스를 개발하다 보면 "어떤 이벤트가 발생하면 자동으로 무언가를 처리해야 하는" 상황이 반복됩니다. 사용자가 회원가입하면 환영 이메일을 보내고, 파일이 업로드되면 썸네일을 생성하고, 매일 자정에 데이터베이스에서 통계를 뽑아 슬랙으로 전송하는 식입니다.

이런 자동화 로직을 백엔드 코드 안에 직접 넣을 수도 있지만, 그러면 자동화 흐름을 바꿀 때마다 코드를 수정하고 배포해야 합니다. n8n은 이런 자동화 워크플로우를 코드 없이 웹 UI에서 노드를 연결하는 방식으로 만들 수 있게 해 주는 오픈소스 도구입니다. Zapier나 Make(Integromat)와 비슷하지만, 셀프호스팅이 가능해서 데이터가 외부 서비스를 거치지 않고 우리 인프라 안에서 처리됩니다.

이번 편에서는 Docker Compose에 n8n을 추가하고, 웹 UI에서 기본 워크플로우를 만들어 보고, Webhook 트리거로 외부 요청을 받아 처리하는 흐름을 설정한 뒤, 8편의 PostgreSQL과 9편의 MinIO를 n8n에서 연동하는 것까지 다룹니다.


1. Docker Compose에 n8n 추가

1-1. docker-compose.yml 수정

~/dev-infra/docker-compose.yml을 열고 n8n 서비스를 추가합니다.

# ~/dev-infra/docker-compose.yml

services:
  postgres:
    image: postgres:17
    container_name: dev-postgres
    restart: unless-stopped
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: devuser
      POSTGRES_PASSWORD: devpass123
      POSTGRES_DB: devdb
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./initdb:/docker-entrypoint-initdb.d

  minio:
    image: minio/minio:latest
    container_name: dev-minio
    restart: unless-stopped
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin123
    volumes:
      - minio_data:/data
    command: server /data --console-address ":9001"

  n8n:
    image: n8nio/n8n:latest
    container_name: dev-n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - N8N_HOST=localhost
      - N8N_PORT=5678
      - N8N_PROTOCOL=http
      - WEBHOOK_URL=http://localhost:5678/
      - N8N_RUNNERS_ENABLED=true
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8ndb
      - DB_POSTGRESDB_USER=devuser
      - DB_POSTGRESDB_PASSWORD=devpass123
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      - postgres

volumes:
  postgres_data:
  minio_data:
  n8n_data:

n8n 서비스의 각 설정을 설명하겠습니다.

ports: "5678:5678"은 n8n 웹 UI와 Webhook 엔드포인트가 모두 이 포트를 사용합니다.

WEBHOOK_URL=http://localhost:5678/은 n8n이 Webhook URL을 생성할 때 사용하는 기본 주소입니다. 로컬 개발 환경이므로 localhost로 설정합니다. 프로덕션에서는 실제 도메인으로 바꿔야 합니다.

N8N_RUNNERS_ENABLED=true는 n8n의 Task Runner를 활성화합니다. Code 노드 등에서 JavaScript/Python 코드를 실행할 때 필요합니다.

DB_TYPE=postgresdb와 그 아래 설정들은 n8n의 내부 데이터(워크플로우 정의, 실행 이력, 자격 증명 등)를 PostgreSQL에 저장하도록 지정합니다. 기본값은 SQLite인데, 데이터 안정성과 백업 편의를 위해 PostgreSQL을 사용하는 것이 낫습니다. DB_POSTGRESDB_HOSTpostgres인 것에 주목하세요. 이것은 같은 Compose 네트워크 안에 있는 PostgreSQL 서비스의 이름입니다. Docker Compose는 서비스 이름으로 자동 DNS 해석을 해 주기 때문에, 컨테이너끼리 통신할 때는 localhost 대신 서비스 이름을 사용합니다.

DB_POSTGRESDB_DATABASE=n8ndb는 n8n 전용 데이터베이스입니다. 8편에서 만든 devdb와 분리해서 n8n 내부 데이터와 애플리케이션 데이터가 섞이지 않도록 합니다. 이 데이터베이스는 아직 존재하지 않으므로 먼저 만들어야 합니다.

n8n_data:/home/node/.n8n은 n8n의 암호화 키, 설정 파일 등을 볼륨에 저장합니다. 이 볼륨을 잃으면 저장된 자격 증명(Credentials)을 복호화할 수 없게 되므로 주의하세요.

depends_on: postgres는 PostgreSQL 컨테이너가 먼저 시작된 뒤 n8n이 시작되도록 순서를 지정합니다.

1-2. n8n 전용 데이터베이스 생성

n8n이 사용할 n8ndb 데이터베이스를 PostgreSQL에 만들어야 합니다. 초기화 SQL 파일을 추가합니다.

~/dev-infra/initdb/02_n8n_db.sql 파일을 생성합니다.

-- ~/dev-infra/initdb/02_n8n_db.sql

CREATE DATABASE n8ndb OWNER devuser;

docker-entrypoint-initdb.d의 스크립트는 파일명 알파벳 순으로 실행되므로, 01_init.sql02_n8n_db.sql 순서로 실행됩니다.

이미 PostgreSQL 볼륨이 존재하는 상태에서는 이 스크립트가 자동 실행되지 않습니다(8편에서 설명한 것처럼 초기화 스크립트는 최초 실행 시에만 동작합니다). 기존 볼륨이 있는 경우에는 수동으로 데이터베이스를 생성합니다.

docker exec -it dev-postgres psql -U devuser -d devdb -c "CREATE DATABASE n8ndb OWNER devuser;"
CREATE DATABASE

이미 존재한다는 에러가 나오면 무시해도 됩니다.

1-3. 컨테이너 실행

cd ~/dev-infra
docker compose up -d
[+] Running 4/4
 ✔ Volume "dev-infra_n8n_data"  Created
 ✔ Container dev-postgres       Running
 ✔ Container dev-minio          Running
 ✔ Container dev-n8n            Started

n8n 로그를 확인합니다.

docker logs dev-n8n

로그에서 아래와 비슷한 메시지가 나타나면 정상입니다.

n8n ready on 0.0.0.0, port 5678
Editor is now accessible via:
http://localhost:5678

n8n은 첫 시작 시 PostgreSQL에 필요한 테이블을 자동으로 생성합니다. 별도의 마이그레이션 작업이 필요 없습니다.


2. 웹 UI 접속 & 초기 설정

브라우저에서 http://localhost:5678을 엽니다. 최초 접속 시 관리자 계정 생성 화면이 나타납니다.

Email:      admin@example.com
First Name: Admin
Last Name:  User
Password:   (원하는 비밀번호 입력)

입력을 마치면 n8n 대시보드가 나타납니다. 왼쪽 사이드바에서 워크플로우 목록, 자격 증명, 실행 이력 등을 탐색할 수 있습니다.


3. 기본 워크플로우 만들기 — Manual Trigger

n8n의 동작 방식을 이해하기 위해 가장 간단한 워크플로우를 하나 만들어 보겠습니다. 버튼을 누르면 현재 시각을 반환하는 워크플로우입니다.

3-1. 워크플로우 생성

우측 상단의 Add workflow 버튼을 클릭합니다. 새 캔버스가 열리고 기본 트리거 노드가 배치돼 있습니다.

3-2. Manual Trigger 확인

캔버스에 이미 있는 트리거 노드를 클릭하면 Manual Trigger가 설정되어 있습니다. 이 트리거는 사용자가 직접 "Test workflow" 버튼을 누를 때 실행됩니다. 그대로 두겠습니다.

3-3. Code 노드 추가

캔버스에서 Manual Trigger 노드 오른쪽의 + 버튼을 클릭합니다. 노드 검색창이 나타나면 Code를 검색하고 Code 노드를 선택합니다.

Code 노드의 편집 패널이 열리면 Language가 JavaScript로 되어 있는지 확인하고, 코드 영역에 아래 내용을 입력합니다.

const now = new Date().toISOString();

return [
  {
    json: {
      message: "Hello from n8n!",
      timestamp: now,
    },
  },
];

n8n의 Code 노드에서 반환하는 데이터는 [{ json: { ... } }] 형태의 배열이어야 합니다. 각 배열 원소가 하나의 아이템(item)이 되어 다음 노드로 전달됩니다.

3-4. 테스트 실행

캔버스 하단의 Test workflow 버튼을 클릭합니다. Manual Trigger → Code 노드가 순서대로 실행되고, Code 노드 위에 초록색 체크 표시가 나타나면 성공입니다.

Code 노드를 클릭하면 Output 탭에서 결과를 확인할 수 있습니다.

[
  {
    "message": "Hello from n8n!",
    "timestamp": "2026-03-31T12:00:00.000Z"
  }
]

3-5. 워크플로우 저장

워크플로우 이름을 Hello World로 바꾸고 Ctrl+S로 저장합니다.


4. Webhook 트리거 — 외부 요청 받기

Manual Trigger는 테스트용으로 편리하지만, 실제 운영에서는 외부 이벤트에 반응하는 트리거가 필요합니다. 가장 범용적인 것이 Webhook 트리거입니다. 특정 URL로 HTTP 요청이 들어오면 워크플로우가 자동으로 실행됩니다.

4-1. 새 워크플로우 생성

대시보드에서 Add workflow를 클릭합니다. 워크플로우 이름을 Webhook Echo로 설정합니다.

4-2. Webhook 트리거 노드 설정

캔버스의 기본 트리거 노드를 클릭하고, 트리거 유형을 Webhook으로 변경합니다. (또는 기본 트리거를 삭제하고 새로 Webhook 노드를 추가해도 됩니다.)

Webhook 노드의 설정에서 다음을 확인합니다.

HTTP Method: POST
Path:        echo

Path를 echo로 입력하면 Webhook URL은 아래와 같이 생성됩니다.

테스트용: http://localhost:5678/webhook-test/echo
프로덕션용: http://localhost:5678/webhook/echo

테스트용 URL은 워크플로우가 비활성 상태에서도 "Test workflow"로 테스트할 때 사용합니다. 프로덕션용 URL은 워크플로우를 Active로 전환한 뒤 실제로 동작하는 URL입니다.

4-3. Respond to Webhook 노드 추가

Webhook 노드의 + 버튼을 누르고 Respond to Webhook을 검색해서 추가합니다. 이 노드는 Webhook 요청에 대한 HTTP 응답을 정의합니다.

Respond to Webhook 노드 설정에서 Respond WithAll Incoming Items로 선택합니다. 이렇게 하면 Webhook으로 들어온 요청 데이터를 그대로 응답으로 돌려보냅니다.

4-4. 사이에 Code 노드 삽입

Webhook과 Respond to Webhook 사이에 Code 노드를 추가해서 데이터를 가공해 보겠습니다. Webhook 노드와 Respond to Webhook 노드 사이의 연결선 위에 있는 + 버튼을 클릭하고 Code 노드를 추가합니다.

Code 노드에 아래 내용을 입력합니다.

const items = $input.all();

return items.map((item) => {
  return {
    json: {
      received: item.json.body,
      processed_at: new Date().toISOString(),
      message: "Webhook received successfully!",
    },
  };
});

$input.all()은 이전 노드에서 넘어온 모든 아이템을 가져옵니다. Webhook 노드의 경우 HTTP 요청의 body, headers, query 등이 담겨 있습니다. 여기서는 body만 꺼내서 처리 시각과 메시지를 추가한 뒤 다음 노드로 넘깁니다.

최종 노드 연결 순서는 다음과 같습니다.

Webhook → Code → Respond to Webhook

4-5. 테스트

캔버스 하단의 Test workflow 버튼을 클릭합니다. n8n이 테스트용 Webhook URL에서 요청을 기다리는 상태가 됩니다. 화면에 "Waiting for test event" 메시지가 표시됩니다.

새 PowerShell 탭에서 요청을 보냅니다.

curl -X POST http://localhost:5678/webhook-test/echo `
  -H "Content-Type: application/json" `
  -d '{"name": "Alice", "action": "signup"}'

응답이 돌아옵니다.

[
  {
    "received": {
      "name": "Alice",
      "action": "signup"
    },
    "processed_at": "2026-03-31T12:05:00.000Z",
    "message": "Webhook received successfully!"
  }
]

n8n 캔버스에서도 각 노드에 초록색 체크가 표시되고, 각 노드를 클릭하면 입력·출력 데이터를 확인할 수 있습니다.

4-6. 워크플로우 활성화

테스트가 성공했으면 워크플로우를 저장하고, 우측 상단의 Inactive 토글을 클릭해서 Active로 전환합니다. 이제 프로덕션용 URL(http://localhost:5678/webhook/echo)로 요청을 보내면 워크플로우가 자동 실행됩니다.

curl -X POST http://localhost:5678/webhook/echo `
  -H "Content-Type: application/json" `
  -d '{"name": "Bob", "action": "login"}'

활성화된 워크플로우는 n8n 컨테이너가 실행 중인 한 계속 동작합니다.


5. PostgreSQL 연동

n8n에서 8편의 PostgreSQL에 직접 연결하면 워크플로우 안에서 데이터를 조회하거나, 새 레코드를 삽입하거나, 특정 조건에 맞는 데이터를 가져와서 다른 노드로 넘기는 것이 가능합니다.

5-1. Credential 등록

n8n에서 외부 서비스에 연결할 때는 Credential(자격 증명)을 먼저 등록합니다. 워크플로우와 분리되어 관리되므로, 여러 워크플로우에서 같은 Credential을 재사용할 수 있습니다.

왼쪽 사이드바에서 Credentials를 클릭하고 Add Credential을 클릭합니다. 검색창에서 Postgres를 찾아 선택합니다.

연결 정보를 입력합니다.

Host:     postgres
Port:     5432
Database: devdb
User:     devuser
Password: devpass123

여기서 Host가 localhost가 아닌 postgres인 점에 주목하세요. n8n 컨테이너는 Docker Compose 네트워크 안에서 실행되므로, 같은 네트워크의 PostgreSQL 컨테이너에 접근할 때는 서비스 이름인 postgres를 사용합니다. localhost를 입력하면 n8n 컨테이너 자기 자신을 가리키게 되어 연결에 실패합니다.

Test Connection을 클릭합니다. "Connection tested successfully"가 나타나면 Save를 클릭합니다. Credential 이름은 Dev PostgreSQL 등 알아보기 쉬운 이름으로 바꿔 두면 좋습니다.

5-2. PostgreSQL 조회 워크플로우

새 워크플로우를 만들고 이름을 Webhook → PostgreSQL 조회로 설정합니다.

Webhook 노드를 추가합니다. HTTP Method는 GET, Path는 users로 설정합니다.

Postgres 노드를 추가합니다. Webhook 노드 오른쪽에 연결합니다. 설정은 다음과 같습니다.

Credential:  Dev PostgreSQL (방금 만든 것)
Operation:   Execute Query
Query:       SELECT id, username, email, created_at FROM users ORDER BY id

Respond to Webhook 노드를 추가합니다. Postgres 노드 오른쪽에 연결하고, Respond With를 All Incoming Items로 설정합니다.

최종 노드 연결 순서는 다음과 같습니다.

Webhook (GET /users) → Postgres → Respond to Webhook

5-3. 테스트

Test workflow를 클릭한 뒤, PowerShell에서 요청을 보냅니다.

curl http://localhost:5678/webhook-test/users
[
  {
    "id": 1,
    "username": "alice",
    "email": "alice@example.com",
    "created_at": "2026-03-31T12:00:00.000+00:00"
  },
  {
    "id": 2,
    "username": "bob",
    "email": "bob@example.com",
    "created_at": "2026-03-31T12:00:00.000+00:00"
  }
]

n8n이 PostgreSQL에서 데이터를 조회해서 Webhook 응답으로 반환하는 것을 확인했습니다. 워크플로우를 저장하고 Active로 전환합니다.

5-4. 데이터 삽입 워크플로우

조회뿐 아니라 삽입도 해 보겠습니다. 새 워크플로우를 만들고 이름을 Webhook → PostgreSQL 삽입으로 설정합니다.

Webhook 노드: HTTP Method POST, Path users/create

Postgres 노드: 설정은 다음과 같습니다.

Credential:  Dev PostgreSQL
Operation:   Execute Query
Query:       INSERT INTO users (username, email)
             VALUES ($1, $2)
             RETURNING id, username, email, created_at

Query Parameters(Values to Send) 설정에서 Add Value를 두 번 클릭해서 파라미터를 추가합니다.

1: {{ $json.body.username }}
2: {{ $json.body.email }}

n8n에서 {{ }} 안에 Expression을 작성하면 이전 노드의 데이터를 동적으로 참조할 수 있습니다. $json.body.username은 Webhook으로 들어온 JSON body의 username 필드를 가리킵니다. $1, $2 파라미터 바인딩을 사용하면 SQL 인젝션을 방지할 수 있습니다.

Respond to Webhook 노드: Respond With All Incoming Items

Webhook (POST /users/create) → Postgres → Respond to Webhook

테스트합니다.

curl -X POST http://localhost:5678/webhook-test/users/create `
  -H "Content-Type: application/json" `
  -d '{"username": "charlie", "email": "charlie@example.com"}'
[
  {
    "id": 3,
    "username": "charlie",
    "email": "charlie@example.com",
    "created_at": "2026-03-31T12:10:00.000+00:00"
  }
]

DBeaver에서 users 테이블을 새로고침하면 charlie가 추가된 것을 확인할 수 있습니다.


6. MinIO 연동

n8n에는 S3 호환 노드가 내장되어 있어 MinIO에도 그대로 연결할 수 있습니다.

6-1. Credential 등록

왼쪽 사이드바 → CredentialsAdd CredentialS3를 검색합니다. 목록에서 S3 를 선택합니다.

연결 정보를 입력합니다.

S3 Endpoint:       http://minio:9000
Region:            us-east-1
Access Key ID:     dev-access-key
Secret Access Key: dev-secret-key-123
Force Path Style:  ON (활성화)

Host가 minio인 이유는 PostgreSQL과 같습니다. Docker Compose 네트워크 안에서 서비스 이름으로 접근해야 합니다. Region은 MinIO에서 실질적인 의미가 없지만 SDK가 요구하므로 us-east-1을 입력합니다. Force Path Style은 반드시 활성화해야 합니다. MinIO는 S3의 Virtual-hosted 스타일 URL을 사용하지 않고 Path 스타일(http://endpoint/bucket/object)을 사용하기 때문입니다.

Test Connection으로 확인한 뒤 Credential 이름을 Dev MinIO로 저장합니다.

6-2. 파일 목록 조회 워크플로우

새 워크플로우를 만들고 이름을 Webhook → MinIO 파일 목록으로 설정합니다.

Webhook 노드: HTTP Method GET, Path files

S3 노드: Webhook 뒤에 연결하고 설정은 다음과 같습니다.

Credential: Dev MinIO
Operation:  Get Many (파일 목록 조회)
Bucket:     uploads

Respond to Webhook 노드: Respond With All Incoming Items

Webhook (GET /files) → S3 → Respond to Webhook

테스트합니다.

curl http://localhost:5678/webhook-test/files

9편에서 업로드한 파일들의 목록이 반환됩니다. 각 파일의 Key(파일명), Size, LastModified 등의 정보를 확인할 수 있습니다.

6-3. 파일 업로드 워크플로우

n8n에서 MinIO에 파일을 직접 업로드하는 워크플로우도 만들 수 있습니다. 예를 들어 PostgreSQL에서 데이터를 조회한 뒤 JSON 파일로 만들어서 MinIO에 저장하는 자동화를 구성해 보겠습니다.

새 워크플로우를 만들고 이름을 DB Export → MinIO 저장으로 설정합니다.

Manual Trigger: 테스트용으로 수동 트리거를 사용합니다. 나중에 Schedule Trigger로 바꾸면 정기 실행도 가능합니다.

Postgres 노드: 전체 사용자 데이터를 조회합니다.

Credential: Dev PostgreSQL
Operation:  Execute Query
Query:      SELECT id, username, email, created_at FROM users ORDER BY id

Code 노드: 조회 결과를 JSON 문자열로 변환합니다.

const items = $input.all();
const data = items.map((item) => item.json);
const jsonString = JSON.stringify(data, null, 2);
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");

return [
  {
    json: {
      fileName: `users_export_${timestamp}.json`,
    },
    binary: {
      data: await this.helpers.prepareBinaryData(
        Buffer.from(jsonString, "utf-8"),
        `users_export_${timestamp}.json`,
        "application/json"
      ),
    },
  },
];

n8n에서 파일을 다루려면 binary 속성에 바이너리 데이터를 담아야 합니다. prepareBinaryData 헬퍼 함수가 문자열을 n8n의 바이너리 형식으로 변환해 줍니다.

S3 노드: MinIO에 업로드합니다.

Credential:   Dev MinIO
Operation:    Upload
Bucket:       reports
File Name:    {{ $json.fileName }}
Binary Data:  ON (활성화)
Input Binary Field: data
Manual Trigger → Postgres → Code → S3

Test workflow를 클릭하면 PostgreSQL에서 사용자 데이터를 조회하고, JSON으로 변환한 뒤, MinIO의 reports 버킷에 업로드합니다. MinIO 웹 콘솔(http://localhost:9001) → Object Browser → reports에서 users_export_2026-03-31T12-10-00-000Z.json 같은 파일이 생성된 것을 확인할 수 있습니다.


7. 실전 활용 시나리오

지금까지 만든 워크플로우는 기본 예제이지만, 이 패턴을 조합하면 다양한 자동화를 구현할 수 있습니다. 몇 가지 시나리오를 소개합니다.

정기 데이터 백업: Schedule Trigger를 사용해서 매일 자정에 PostgreSQL 데이터를 MinIO에 JSON으로 내보냅니다. 방금 만든 "DB Export → MinIO 저장" 워크플로우의 트리거만 Schedule로 바꾸면 됩니다.

회원가입 후처리: Go 또는 FastAPI 서버에서 회원가입 완료 후 n8n Webhook을 호출합니다. n8n에서 환영 이메일 발송, 슬랙 알림, 관리자 대시보드 갱신 등을 처리합니다. 백엔드 코드는 Webhook 하나만 호출하면 되고, 이후 처리 흐름은 n8n에서 자유롭게 수정할 수 있습니다.

파일 업로드 모니터링: MinIO에 파일이 업로드되면 Webhook으로 n8n에 알리고, n8n에서 파일 메타데이터를 PostgreSQL에 기록하거나 슬랙으로 알림을 보냅니다.

이런 시나리오들은 n8n의 400개 이상 내장 노드(Slack, Gmail, Google Sheets, HTTP Request 등)를 조합해서 구현합니다. 코드를 작성하지 않아도 노드를 드래그 앤 드롭으로 연결하는 것만으로 복잡한 자동화를 만들 수 있다는 것이 n8n의 가장 큰 장점입니다.


8. 자주 겪는 문제와 해결

n8n 시작 시 "FATAL: database "n8ndb" does not exist"

n8n 전용 데이터베이스가 없는 상태입니다. 1-2절에서 안내한 대로 수동으로 생성합니다.

docker exec -it dev-postgres psql -U devuser -d devdb -c "CREATE DATABASE n8ndb OWNER devuser;"
docker restart dev-n8n

Credential 테스트 시 "connect ECONNREFUSED 127.0.0.1:5432"

Host에 localhost를 입력한 경우 발생합니다. Docker Compose 네트워크 안에서는 서비스 이름(postgres, minio)을 사용해야 합니다.

Webhook URL로 요청을 보내도 404가 반환되는 경우

워크플로우가 Active 상태인지 확인하세요. 비활성 상태에서는 프로덕션 URL(/webhook/...)이 동작하지 않습니다. 테스트 중이라면 테스트 URL(/webhook-test/...)을 사용하고, "Test workflow" 버튼을 먼저 클릭해서 대기 상태로 만들어야 합니다.

S3 노드에서 "Access Denied" 또는 "Bucket not found"

Credential의 Force Path Style이 활성화되어 있는지 확인하세요. 또한 S3 Endpoint에 프로토콜(http://)을 포함했는지 확인합니다. minio:9000이 아니라 http://minio:9000이어야 합니다.


최종 확인 체크리스트

아래 항목을 모두 확인했다면 10편은 완료입니다.

✅ docker-compose.yml에 n8n 서비스가 추가되어 있다
✅ docker compose up -d 로 PostgreSQL, MinIO, n8n이 모두 정상 기동된다
✅ 브라우저에서 http://localhost:5678 로 n8n 웹 UI에 접속할 수 있다
✅ Manual Trigger + Code 노드로 기본 워크플로우를 만들고 실행할 수 있다
✅ Webhook 트리거로 외부 HTTP 요청을 받아 처리할 수 있다
✅ PostgreSQL Credential을 등록하고 데이터 조회·삽입이 동작한다
✅ MinIO(S3) Credential을 등록하고 파일 목록 조회·업로드가 동작한다

현재 인프라 구성 요약

10편까지 완료한 시점에서 ~/dev-infra/docker-compose.yml 하나로 아래 세 가지 인프라 컴포넌트가 모두 관리되고 있습니다.

PostgreSQL (5432)  — 관계형 데이터베이스
MinIO (9000/9001)  — S3 호환 오브젝트 스토리지
n8n (5678)         — 워크플로우 자동화 엔진

PowerShell에서 docker compose up -d 한 줄이면 전체 인프라가 올라오고, docker compose down이면 깔끔하게 내려갑니다. 이 구성이 14편에서 프로덕션용 통합 Docker Compose로 발전하게 됩니다.


다음 편 예고

로컬 개발 인프라가 모두 갖춰졌습니다. 11편: Caddy 웹 서버 & 리버스 프록시 (리눅스 서버 기준)에서는 무대를 클라우드 리눅스 서버로 옮깁니다. Caddy를 설치하고, 자동 HTTPS 인증서 발급을 설정하고, 리버스 프록시로 Go API, FastAPI, n8n, MinIO를 하나의 도메인 아래에서 서빙하는 구성을 다루겠습니다.

728x90