발행일: 2026-10-06(화) 11:44
← 목차로 돌아가기|하루 30분 n8n 시리즈 ② 실무 자동화 레시피 100
RECIPE 032

영업 파이프라인 주간 현황 리포트

  • ▸여러 Google Sheets 시트의 데이터를 하나로 병합할 수 있다
  • ▸Merge 노드와 Code 노드로 컬럼 구조가 다른 시트도 통합할 수 있다
  • ▸병합된 데이터를 통합 리포트 시트에 자동 저장할 수 있다

✅사전 준비

  • □Google Sheets 자격증명 연결 완료
  • □병합할 시트 목록과 각 시트의 컬럼 구조 파악
  • □통합 리포트 시트 생성 및 표준 컬럼 헤더 입력
  • □Schedule Trigger: 매주 월요일 오전 8시 (Cron: 0 8 * * 1)

컬럼 구조 통일 — Code 노드

// 각 시트마다 컬럼명이 다를 때 표준화
const item = $input.first().json;
const source = $input.first().json._source ?? '시트1';

return [{ json: {
  날짜:   item.날짜 ?? item.date ?? item.Date ?? '',
  항목:   item.항목 ?? item.item ?? item.category ?? '',
  금액:   Number(item.금액 ?? item.amount ?? item.Amount ?? 0),
  담당자: item.담당자 ?? item.assignee ?? item.owner ?? '',
  출처:   source,
} }];

병합 후 정렬 — Code 노드

const items = $input.all().map(i => i.json);

// 날짜 기준 내림차순 정렬
const sorted = items.sort((a, b) =>
  new Date(b.날짜) - new Date(a.날짜)
);

return sorted.map(j => ({ json: j }));
💡 TIP시트가 많을수록 병렬로 읽어오는 것이 빠릅니다. n8n에서 여러 Sheets Read 노드를 Merge 노드의 각 입력 핀에 연결하면 동시에 읽어올 수 있어요.
⚡

워크플로우 JSON

아래 JSON을 복사해 n8n에 바로 임포트하세요

📥 n8n 임포트 방법
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
{
  "recipeId": "recipe032",
  "title": "영업 파이프라인 주간 현황 리포트",
  "chapter": 3,
  "category": "영업 & 리드 관리 자동화",
  "difficulty": "⭐⭐",
  "estimatedTime": "30분",
  "description": "매주 월요일 오전 9시 HubSpot에서 단계별 딜 현황을 가져와 Slack 팀 채널에 주간 파이프라인 요약 리포트를 자동 발송합니다.",
  "apps": [
    "HubSpot",
    "Slack"
  ],
  "nodes": [
    {
      "id": "trigger_schedule",
      "type": "trigger",
      "name": "Schedule Trigger - 매주 월요일 오전 9시",
      "service": "scheduleTrigger",
      "config": {
        "rule": "0 9 * * 1"
      }
    },
    {
      "id": "hubspot_pipeline",
      "type": "action",
      "name": "HubSpot - 파이프라인 딜 현황 조회",
      "service": "hubspot",
      "config": {
        "operation": "getDeals",
        "filters": [
          {
            "propertyName": "closedate",
            "operator": "THIS_MONTH"
          }
        ],
        "properties": [
          "dealname",
          "dealstage",
          "amount",
          "hubspot_owner_id"
        ]
      }
    },
    {
      "id": "function_aggregate",
      "type": "function",
      "name": "Function - 단계별 집계",
      "code": "const deals = $input.all();\nconst stages = {\n  appointmentscheduled: { label: '탐색 중', count: 0, total: 0 },\n  qualifiedtobuy: { label: '제안 중', count: 0, total: 0 },\n  presentationscheduled: { label: '협상 중', count: 0, total: 0 },\n  closedwon: { label: '계약 완료', count: 0, total: 0 },\n  closedlost: { label: '실패', count: 0, total: 0 }\n};\ndeals.forEach(d => {\n  const s = d.json.dealstage;\n  if (stages[s]) {\n    stages[s].count++;\n    stages[s].total += Number(d.json.amount || 0);\n  }\n});\nreturn [{ json: stages }];"
    },
    {
      "id": "slack_report",
      "type": "action",
      "name": "Slack - 파이프라인 리포트 발송",
      "service": "slack",
      "config": {
        "channel": "={{ $env.SLACK_SALES_CHANNEL }}",
        "message": "📊 이번 주 영업 파이프라인 현황\n탐색 중: {{ $json[\"appointmentscheduled\"][\"count\"] }}건 / 총 ₩{{ $json[\"appointmentscheduled\"][\"total\"].toLocaleString() }}\n제안 중: {{ $json[\"qualifiedtobuy\"][\"count\"] }}건 / 총 ₩{{ $json[\"qualifiedtobuy\"][\"total\"].toLocaleString() }}\n협상 중: {{ $json[\"presentationscheduled\"][\"count\"] }}건 / 총 ₩{{ $json[\"presentationscheduled\"][\"total\"].toLocaleString() }}\n이번 달 계약 완료: {{ $json[\"closedwon\"][\"count\"] }}건 / 총 ₩{{ $json[\"closedwon\"][\"total\"].toLocaleString() }}"
      }
    }
  ],
  "connections": [
    {
      "from": "trigger_schedule",
      "to": "hubspot_pipeline"
    },
    {
      "from": "hubspot_pipeline",
      "to": "function_aggregate"
    },
    {
      "from": "function_aggregate",
      "to": "slack_report"
    }
  ],
  "envVars": [
    {
      "key": "SLACK_SALES_CHANNEL",
      "description": "영업팀 Slack 채널 ID"
    }
  ],
  "qrCodeUrl": "https://www.koreaaitimes.com/books/n8n-vol2/recipe032"
}
← 이전 레시피☰ 목차다음 레시피 →