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

학습 진도 자동 추적 → 리마인더 발송

  • ▸온라인 학습 플랫폼의 수강 진도를 주기적으로 수집
  • ▸목표 진도 대비 현황을 자동 분석
  • ▸학습 지연 수강생에게 맞춤 리마인더 자동 발송

✅사전 준비

  • □학습 플랫폼 API 또는 수강 데이터 Google Sheets 연동
  • □코스별 목표 완료일 및 주차별 목표 진도율 설정
  • □Gmail 또는 Slack 알림 설정
  • □개인화 메시지 템플릿 2~3가지 준비

진도율 계산 및 지연 분류

// Code 노드
const learners = $input.all();
const today = new Date();

return learners.map(l => {
  const startDate = new Date(l.json.start_date);
  const endDate = new Date(l.json.end_date);
  const totalDays = (endDate - startDate) / 86400000;
  const elapsedDays = (today - startDate) / 86400000;

  const expectedProgress = Math.min((elapsedDays / totalDays) * 100, 100);
  const actualProgress = l.json.completion_rate;
  const gap = expectedProgress - actualProgress;

  let status = 'on_track';
  if (gap >= 20) status = 'critical';
  else if (gap >= 10) status = 'behind';

  return { json: { ...l.json, expectedProgress, gap, status } };
});

리마인더 메시지 개인화

// Switch 노드로 status별 분기

// critical (20% 이상 지연)
제목: {{ $json.name }}님, 지금 바로 학습을 시작하세요!
내용: 현재 진도율이 목표보다 {{ $json.gap.toFixed(0) }}% 낮습니다.
이번 주 목표: {{ $json.this_week_lessons }} 강 완료

// behind (10~20% 지연)
제목: {{ $json.name }}님, 조금만 더 힘내세요!
내용: 현재 {{ $json.actualProgress.toFixed(0) }}% 완료! 주 3강만 들으면 목표 달성!!
💡 TIPCron을 매주 월요일 오전 9시(`0 9 * * 1`)로 설정하면 한 주를 시작하는 시점에 리마인더를 보낼 수 있어 학습 동기 부여 효과가 가장 높습니다.
⚡

워크플로우 JSON

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

📥 n8n 임포트 방법
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
{
  "recipeId": "recipe090",
  "title": "네이버 검색광고 일간 성과 리포트",
  "chapter": 8,
  "category": "국내 서비스 특화 레시피",
  "difficulty": "⭐⭐",
  "estimatedTime": "40분",
  "usedApps": [
    "네이버 검색광고 API",
    "Google Sheets",
    "Slack"
  ],
  "description": "매일 오전 7시 네이버 검색광고 API로 전일 키워드별 노출수·클릭수·비용·전환수를 자동 수집해 Google Sheets에 누적 기록하고, 주요 지표 요약을 Slack으로 발송합니다.",
  "apiGuide": {
    "platform": "네이버 검색광고",
    "issueUrl": "searchad.naver.com",
    "steps": [
      "네이버 검색광고 → 도구 → API 관리",
      "이용 신청 (심사 필요, 1~2 영업일)",
      "API 키 / 시크릿 발급",
      "HMAC-SHA256 서명 인증 방식 사용 (Function 노드에서 처리)"
    ]
  },
  "nodes": [
    {
      "id": "node1",
      "type": "n8n-nodes-base.scheduleTrigger",
      "name": "매일 오전 7시 실행",
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 7 * * *"
            }
          ]
        }
      }
    },
    {
      "id": "node2",
      "type": "n8n-nodes-base.code",
      "name": "HMAC-SHA256 서명 생성",
      "parameters": {
        "jsCode": "const crypto = require('crypto');\nconst timestamp = Date.now().toString();\nconst method = 'GET';\nconst path = '/stats';\nconst message = timestamp + '.' + method + '.' + path;\nconst signature = crypto.createHmac('sha256', $env.NAVER_AD_SECRET_KEY).update(message).digest('base64');\nreturn [{ json: { timestamp, signature } }];"
      }
    },
    {
      "id": "node3",
      "type": "n8n-nodes-base.httpRequest",
      "name": "네이버 검색광고 성과 조회",
      "parameters": {
        "method": "GET",
        "url": "https://api.naver.com/stats",
        "headers": {
          "X-Timestamp": "={{$json['timestamp']}}",
          "X-API-KEY": "={{$env.NAVER_AD_API_KEY}}",
          "X-Customer": "={{$env.NAVER_AD_CUSTOMER_ID}}",
          "X-Signature": "={{$json['signature']}}"
        },
        "queryParameters": {
          "dateFrom": "={{$now.minus({days: 1}).format('YYYYMMDD')}}",
          "dateTo": "={{$now.minus({days: 1}).format('YYYYMMDD')}}",
          "timeUnit": "DAY",
          "fields": "clkCnt,impCnt,salesAmt,ctr"
        }
      }
    },
    {
      "id": "node4",
      "type": "n8n-nodes-base.googleSheets",
      "name": "성과 시트 누적 기록",
      "parameters": {
        "operation": "appendOrUpdate",
        "spreadsheetId": "={{$env.AD_REPORT_SHEET_ID}}",
        "sheetName": "네이버광고성과",
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "날짜": "={{$now.minus({days: 1}).format('YYYY-MM-DD')}}",
            "노출수": "={{$json['data'][0]['impCnt']}}",
            "클릭수": "={{$json['data'][0]['clkCnt']}}",
            "CTR": "={{($json['data'][0]['ctr'] * 100).toFixed(2)}}%",
            "광고비": "={{$json['data'][0]['salesAmt']}}"
          }
        }
      }
    },
    {
      "id": "node5",
      "type": "n8n-nodes-base.slack",
      "name": "일간 성과 요약 발송",
      "parameters": {
        "channel": "={{$env.MARKETING_SLACK_CHANNEL}}",
        "text": "📊 어제 네이버 광고 성과 ({{$now.minus({days: 1}).format('MM/DD')}})\n\n총 노출: {{$node['네이버 검색광고 성과 조회'].json['data'][0]['impCnt'].toLocaleString()}}회\n총 클릭: {{$node['네이버 검색광고 성과 조회'].json['data'][0]['clkCnt'].toLocaleString()}}회\nCTR: {{($node['네이버 검색광고 성과 조회'].json['data'][0]['ctr'] * 100).toFixed(2)}}%\n총 비용: ₩{{$node['네이버 검색광고 성과 조회'].json['data'][0]['salesAmt'].toLocaleString()}}"
      }
    }
  ],
  "envVariables": {
    "NAVER_AD_API_KEY": "네이버 검색광고 API 키",
    "NAVER_AD_SECRET_KEY": "네이버 검색광고 API 시크릿 키",
    "NAVER_AD_CUSTOMER_ID": "네이버 광고 고객 ID",
    "AD_REPORT_SHEET_ID": "Google Sheets 광고 성과 시트 ID",
    "MARKETING_SLACK_CHANNEL": "마케팅팀 Slack 채널 ID"
  },
  "tips": [
    "네이버 검색광고 API는 HMAC-SHA256 서명 인증이 필요합니다. Code 노드의 서명 생성 코드가 QR코드 템플릿에 포함되어 있어요.",
    "레시피 013(구글 광고 성과 리포트)과 함께 운영하면 구글·네이버 광고 성과를 하나의 시트에서 통합 비교할 수 있어요.",
    "CPA(전환당 비용)를 계산하려면 Code 노드에서 '광고비 / 전환수' 수식을 추가하세요."
  ],
  "qrUrl": "www.koreaaitimes.com/books/n8n-vol2/recipe090"
}
← 이전 레시피☰ 목차다음 레시피 →