Make에서 셀프호스팅 n8n으로 마이그레이션하고, 운영 통계 데이터를 자동으로 Google Spreadsheet에 기록하는 워크플로우를 구축한 경험을 공유합니다.
들어가며
운영 업무를 하다 보면 매주 반복되는 보고 작업이 있습니다. 여러 데이터 소스에서 통계를 수집하고, 스프레드시트에 정리하고, Slack으로 공유하는 일련의 과정입니다. 처음에는 Make로 자동화했지만, 셀프호스팅의 필요성과 더 유연한 커스터마이징을 위해 n8n으로 전환했습니다.
본 글에서는 운영 통계 데이터를 수집하여 Google Spreadsheet에 기록하고 Slack으로 알림을 보내는 워크플로우 구축 과정을 다룹니다.
1. Make vs n8n: 마이그레이션 이유
1.1 Make의 한계
Make는 직관적인 UI와 빠른 구축이 장점이지만, 다음과 같은 한계가 있었습니다.
무료 플랜의 제약
Make 무료 플랜은 활성 시나리오(워크플로우) 2개, 월 1,000회로 제한됩니다. 처음에는 충분했지만, 주간 보고 외에 다른 자동화 플로우가 추가되면서 무료 사용이 불가능해졌습니다.
데이터 보안 이슈
운영 통계 데이터에는 내부 시스템 정보, 사용자 통계 등 민감한 정보가 포함됩니다. Make는 클라우드 기반 서비스이기 때문에 모든 데이터가 외부 서버를 경유하게 됩니다. 내부 보안 정책상 이러한 데이터가 외부로 나가는 것을 최소화해야 했습니다.
| 항목 | Make | n8n (셀프호스팅) |
|---|---|---|
| 비용 | 실행 횟수 기반 과금 | 서버 비용만 발생 |
| 데이터 보안 | 클라우드 의존 | 내부망 운영 가능 |
| 커스터마이징 | 제한적 | Code 노드로 자유로운 로직 구현 |
| 복잡한 분기 | 다소 불편 | Switch 노드로 깔끔한 분기 처리 |
1.2 n8n 셀프호스팅 선택
운영 데이터가 외부로 나가는 것에 대한 보안 우려와, 비용, 복잡한 분기 로직을 자유롭게 구현하고 싶어서 n8n 셀프호스팅을 선택했습니다. Docker Compose로 간단하게 구축할 수 있고, 내부망에서 안전하게 운영할 수 있습니다.
n8n 설치 docker-compose.yml
volumes:
n8n_storage:
postgres_storage:
networks:
n8n_network:
driver: bridge
x-n8n: &service-n8n
image: n8nio/n8n:latest
networks: ['n8n_network']
environment:
- WEBHOOK_URL=https://xxx.xxx.com
- N8N_EDITOR_BASE_URL=https://xxx.xxx.com
- N8N_HOST=${N8N_HOST}
- N8N_CORS_ORIGINS=https://xxx.xxx.com
- TZ=Asia/Seoul
- N8N_PAYLOAD_SIZE_MAX=32
- N8N_REQUEST_MAX_SIZE=100MB
- N8N_PUSH_BACKEND=websocket
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_USER=${POSTGRES_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
- N8N_DIAGNOSTICS_ENABLED=false
- N8N_PERSONALIZATION_ENABLED=false
env_file:
- path: .env
required: true
services:
postgres:
image: postgres:16-alpine
hostname: postgres
networks: ['n8n_network']
restart: unless-stopped
environment:
- POSTGRES_USER
- POSTGRES_PASSWORD
- POSTGRES_DB
volumes:
- postgres_storage:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
interval: 5s
timeout: 5s
retries: 10
n8n-import:
<<: *service-n8n
hostname: n8n-import
container_name: n8n-import
entrypoint: /bin/sh
command:
- "-c"
- "n8n import:credentials --separate --input=/n8n_data/credentials && n8n import:workflow --separate --input=/n8n_data/workflows"
volumes:
- ./n8n/n8n_data:/n8n_data
depends_on:
postgres:
condition: service_healthy
n8n:
<<: *service-n8n
hostname: n8n
container_name: n8n
restart: unless-stopped
ports:
- "5678:5678"
volumes:
- n8n_storage:/home/node/.n8n
- ./n8n/n8n_data:/n8n_data
- ./shared:/data/shared
depends_on:
postgres:
condition: service_healthy
n8n-import:
condition: service_completed_successfully
2. 워크플로우 아키텍처
전체 워크플로우는 다음과 같은 구조입니다.

Webhook (트리거)
│
├─▶ Edit Fields (파라미터 정리)
│
├─▶ Copy File (템플릿 시트 복사)
│
├─▶ Get Sheet Info (시트 정보 조회)
│
└─▶ Switch (데이터 유형별 분기)
│
├─▶ Update Title → Spreadsheet 업데이트
├─▶ Update Year-Month → Code → Spreadsheet 업데이트
├─▶ Collect Site → Code → Spreadsheet 업데이트
├─▶ Report List → Code → Spreadsheet 업데이트
├─▶ Report Ips → Code → Spreadsheet 업데이트
├─▶ Xpath → Code → Spreadsheet 업데이트
├─▶ Statistics → Code → Spreadsheet 업데이트
└─▶ (추가 브랜치...)
│
└─▶ Slack (완료 알림)
2.1 주요 컴포넌트
n8n 기본 제공 노드
| 노드 | 역할 | 설명 |
|---|---|---|
| Webhook | 트리거 | 수동 실행 또는 외부 호출로 워크플로우 시작 |
| Edit Fields | 데이터 전처리 | 입력 파라미터 정리 및 기본값 설정 |
| Copy File | 템플릿 복사 | Google Drive에서 템플릿 시트 복사 |
| Switch | 분기 처리 | 데이터 유형별로 8개 브랜치 분기 |
| Code | 데이터 가공 | JavaScript로 API 응답 데이터 변환 |
| HTTP Request | API 호출 | Spreadsheet API 호출 |
HTTP Request 노드를 이용하여 구현
| 기능명 | 역할 | 설명 |
|---|---|---|
| Get Sheet Info | 시트 정보 조회 | 복사된 시트의 ID 및 메타데이터 획득 |
| Slack | 알림 | 완료 시 Slack 채널에 알림 전송 |
3. 핵심 구현 상세
3.1 Code 노드로 데이터 변환
Webhook 실행 시 DB에서 데이터를 가져오고 해당 데이터를 Google Spreadsheet API 형식에 맞게 변환해야 합니다. n8n에서 제공해주는 Code 노드에 아래와 같은 코드를 이용하여 형식에 맞게 변환했습니다.
const items = $input.first().json.data;
const valuesForSheet = [];
if (!items || items.length === 0) {
return [];
}
const headers = Object.keys(items[0]);
for (const item of items) {
const row = [];
for (const header of headers) {
row.push(item[header] || '');
}
valuesForSheet.push(row);
}
return {
json: {
batchData: valuesForSheet
}
};3.2 Google Spreadsheet 연동
n8n의 내장 Google Sheets 노드도 있지만, 복잡한 배치 업데이트 시에는 Google Sheets API를 사용하는 것이 더 유용합니다.
그래서 n8n에서 제공해주는 HTTP Request 노드를 이용하여 해당 호출해 Google Sheet를 업데이트 했습니다.
{{
{
"valueInputOption": "USER_ENTERED",
"data": [
{
"range": $('Report Ips').item.json.range,
"values": $('Code2').item.json.batchData
}
]
}
}}4. 마무리
n8n으로 주간 보고 자동화를 구축하면서 배운 점을 정리합니다.
셀프호스팅의 장점
Make 대비 비용 절감과 데이터 보안을 확보했습니다. 내부망에서 운영하므로 민감한 운영 데이터가 외부로 노출될 걱정이 없습니다.
Switch 노드 활용
복잡한 분기 로직을 Switch 노드로 깔끔하게 처리할 수 있었습니다. 데이터 유형별로 브랜치를 나누어 각각 독립적으로 실행되므로 유지보수가 용이합니다.
Code 노드의 유연함
내장 노드로 해결하기 어려운 데이터 변환은 Code 노드에서 JavaScript로 직접 구현했습니다. 이 유연함이 Make에서 n8n으로 전환한 가장 큰 이유입니다.