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

경쟁사 가격 모니터링 → 변동 알림

  • ▸여러 RSS 피드를 병렬로 수집해 Merge 노드로 합칠 수 있다
  • ▸수집된 기사를 OpenAI로 요약해 뉴스레터 형식으로 가공할 수 있다
  • ▸Gmail로 HTML 뉴스레터를 구독자 목록에 일괄 발송할 수 있다

✅사전 준비

  • □수집할 RSS 피드 URL 3~5개 준비
  • □OpenAI API 키 및 자격증명 연결 완료
  • □Gmail 자격증명 연결 완료
  • □Google Sheets에 구독자 이메일 목록 시트 생성
  • □Schedule Trigger: 매주 금요일 오후 5시 (Cron: 0 17 * * 5)

Merge 노드 설정값

Mode: Append
→ 여러 RSS Feed Read 노드의 출력을 하나로 합침

연결 방법:
  RSS Feed 1 → Merge
  RSS Feed 2 → Merge
  RSS Feed 3 → Merge (노드를 추가할수록 입력 핀이 늘어남)

기사 요약 — OpenAI 노드 프롬프트

Model: gpt-4o-mini  (비용 절감)

Prompt:
다음 뉴스 기사 제목을 보고 1~2줄로 핵심만 한국어로 요약해줘.
독자가 클릭 여부를 판단할 수 있게 간결하게 작성해.

제목: {{ $json.title }}
내용 (있을 경우): {{ $json.contentSnippet?.slice(0, 500) }}

뉴스레터 HTML 조립 — Code 노드

const articles = $input.all();

const body = articles.map(a => `
  <div style="margin-bottom:20px;padding-bottom:20px;border-bottom:1px solid #eee">
    <a href="${a.json.link}" style="font-size:16px;font-weight:bold;color:#1a73e8">${a.json.title}</a>
    <p style="color:#555;margin:6px 0">${a.json.summary ?? ""}</p>
    <small style="color:#999">${a.json.pubDate ?? ""}</small>
  </div>
`).join("");

return [{
  json: {
    html: `
      <div style="max-width:600px;margin:0 auto;font-family:sans-serif">
        <h2 style="color:#1a73e8">📰 주간 AI 뉴스레터</h2>
        <p style="color:#666">${new Date().toLocaleDateString("ko-KR")} 발행</p>
        ${body}
        <p style="color:#999;font-size:12px">n8n 자동화로 발행됩니다.</p>
      </div>
    `,
  }
}];
💡 TIP구독자 수가 많다면 Gmail 일일 발송 한도(무료 500건)에 주의하세요. 대량 발송이 필요하면 SendGrid 또는 Mailgun 노드로 교체하는 게 좋습니다.
⚡

워크플로우 JSON

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

📥 n8n 임포트 방법
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
{
  "name": "recipe019_competitor_price_monitoring",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9,18 * * *"
            }
          ]
        }
      },
      "id": "schedule-019-01",
      "name": "하루 2회 (오전 9시, 오후 6시)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.1,
      "position": [
        200,
        400
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $env.COMPETITOR_PRODUCT_URL }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "id": "http-019-02",
      "name": "경쟁사 상품 페이지 가져오기",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        420,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const html = $json.data || '';\nconst priceMatch = html.match(/[\\d,]+원/) || html.match(/\\\\$[\\d,\\\\.]+/);\nconst currentPrice = priceMatch ? parseInt(priceMatch[0].replace(/[^0-9]/g, '')) : 0;\nreturn [{ json: { currentPrice, checkedAt: $now.format('YYYY-MM-DD HH:mm') } }];"
      },
      "id": "code-019-03",
      "name": "가격 데이터 추출",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        640,
        400
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "documentId": {
          "value": "={{ $env.PRICE_MONITOR_SHEET_ID }}"
        },
        "sheetName": {
          "value": "prices"
        },
        "options": {}
      },
      "id": "sheets-019-04",
      "name": "이전 가격 조회",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        860,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const currentPrice = $('가격 데이터 추출').item.json.currentPrice;\nconst prevData = $input.all();\nconst prevPrice = prevData.length > 0 ? parseInt(prevData[prevData.length - 1].json.price || 0) : 0;\nconst changed = prevPrice > 0 && currentPrice !== prevPrice;\nreturn [{ json: { currentPrice, prevPrice, changed, diff: currentPrice - prevPrice } }];"
      },
      "id": "code-019-05",
      "name": "가격 변동 감지",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1080,
        400
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "leftValue": "={{ $json.changed }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ]
        }
      },
      "id": "if-019-06",
      "name": "가격 변동 여부 확인",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1300,
        400
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "post",
        "channel": "#marketing-pricing",
        "text": "=💰 가격 변동 감지!\n이전 가격: ₩{{ $json.prevPrice.toLocaleString() }}\n현재 가격: ₩{{ $json.currentPrice.toLocaleString() }} ({{ $json.diff > 0 ? '↑' : '↓' }} ₩{{ Math.abs($json.diff).toLocaleString() }})"
      },
      "id": "slack-019-07",
      "name": "Slack 가격 변동 알림",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        1520,
        300
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "value": "={{ $env.PRICE_MONITOR_SHEET_ID }}"
        },
        "sheetName": {
          "value": "prices"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "price": "={{ $('가격 변동 감지').item.json.currentPrice }}",
            "checkedAt": "={{ $now.format('YYYY-MM-DD HH:mm') }}"
          }
        }
      },
      "id": "sheets-019-08",
      "name": "가격 이력 기록",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        1520,
        500
      ]
    }
  ],
  "connections": {
    "하루 2회 (오전 9시, 오후 6시)": {
      "main": [
        [
          {
            "node": "경쟁사 상품 페이지 가져오기",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "경쟁사 상품 페이지 가져오기": {
      "main": [
        [
          {
            "node": "가격 데이터 추출",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "가격 데이터 추출": {
      "main": [
        [
          {
            "node": "이전 가격 조회",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "이전 가격 조회": {
      "main": [
        [
          {
            "node": "가격 변동 감지",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "가격 변동 감지": {
      "main": [
        [
          {
            "node": "가격 변동 여부 확인",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "가격 변동 여부 확인": {
      "main": [
        [
          {
            "node": "Slack 가격 변동 알림",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "가격 이력 기록",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "timezone": "Asia/Seoul"
  },
  "meta": {
    "chapter": 2,
    "recipe": "019",
    "title": "경쟁사 가격 모니터링 → 변동 알림",
    "difficulty": "⭐⭐⭐",
    "estimatedTime": "45분",
    "apps": [
      "HTTP Request",
      "Google Sheets",
      "Slack"
    ]
  }
}
← 이전 레시피☰ 목차다음 레시피 →