RECIPE 057
경쟁사 가격 모니터링 → 자동 리포트
- ▸경쟁사 제품 페이지에서 가격 정보 주기적 수집
- ▸가격 변동 감지 시 즉시 알림 발송
- ▸주간 가격 비교 리포트를 Google Sheets에 자동 저장
✅사전 준비
- □모니터링할 경쟁사 URL 목록 준비 (최대 10개 권장)
- □Google Sheets 가격 이력 저장용 시트 생성
- □Slack 또는 이메일 알림 설정
- □HTML 파싱용 CSS 셀렉터 사전 확인
모니터링 URL 목록 (Sheets에서 읽기)
Node: Google Sheets
Operation: Read Rows
Spreadsheet: 경쟁사 모니터링
Sheet: URL목록
컬럼 구성: | 회사명 | URL | CSS셀렉터 | 이전가격 |가격 파싱 (HTML Extract)
Node: HTTP Request → HTML Extract
HTML Extract 설정:
Extraction Values:
- Key: price
CSS Selector: {{ $json.css_selector }}
Return Value: Text
// 가격 정제 (Code 노드)
const raw = $input.first().json.price;
const price = parseFloat(raw.replace(/[^0-9.]/g, ''));
return [{ json: { price, raw, url: $input.first().json.url } }];가격 변동 감지 로직
// Code 노드
const currentPrice = $json.price;
const previousPrice = $json.previous_price;
const changeRate = ((currentPrice - previousPrice) / previousPrice * 100).toFixed(2);
return [{
json: {
...$json,
changeRate: parseFloat(changeRate),
isChanged: Math.abs(changeRate) > 1, // 1% 이상 변동
direction: currentPrice > previousPrice ? '인상' : '인하'
}
}];💡 TIP일부 쇼핑몰은 봇 차단을 적용합니다. User-Agent 헤더를 실제 브라우저 값으로 설정하거나, 요청 간격을 3~5초로 늘려 차단을 방지하세요.
⚡
워크플로우 JSON
아래 JSON을 복사해 n8n에 바로 임포트하세요
📥 n8n 임포트 방법
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
{
"recipeId": "recipe057",
"title": "인사평가 리마인더 & 설문 자동 발송",
"chapter": 5,
"category": "HR & 조직 운영 자동화",
"difficulty": "⭐⭐",
"estimatedTime": "30분",
"usedApps": [
"Google Sheets",
"Gmail",
"Slack"
],
"description": "인사평가 시작 7일 전·3일 전·당일에 대상자와 평가자에게 순차적으로 안내 이메일과 설문 링크를 발송하고, 마감 하루 전 미제출자에게만 리마인더를 자동 발송합니다.",
"nodes": [
{
"id": "trigger_daily",
"type": "trigger",
"service": "Schedule",
"name": "매일 오전 9시 실행",
"config": {
"interval": "daily",
"time": "09:00"
}
},
{
"id": "get_eval_schedule",
"type": "action",
"service": "Google Sheets",
"name": "평가 일정 조회",
"config": {
"operation": "readRows",
"spreadsheetId": "{{$env.EVAL_SHEET_ID}}",
"sheetName": "평가일정",
"columns": [
"평가명",
"시작일",
"마감일",
"대상자이메일",
"평가자이메일",
"설문URL",
"상태"
]
}
},
{
"id": "check_schedule",
"type": "action",
"service": "Function",
"name": "발송 대상 계산",
"config": {
"code": "const today = $now.format('YYYY-MM-DD');\nconst results = [];\n\n$items().forEach(item => {\n const e = item.json;\n const startDate = new Date(e['시작일']);\n const dueDate = new Date(e['마감일']);\n const todayDate = new Date(today);\n const daysToStart = Math.ceil((startDate - todayDate) / (1000 * 60 * 60 * 24));\n const daysToDue = Math.ceil((dueDate - todayDate) / (1000 * 60 * 60 * 24));\n\n if ([7, 3, 0].includes(daysToStart)) {\n results.push({ ...e, triggerType: 'notice', daysToStart });\n }\n if (daysToDue === 1 && e['상태'] !== '제출완료') {\n results.push({ ...e, triggerType: 'reminder' });\n }\n});\n\nreturn results.map(r => ({ json: r }));"
}
},
{
"id": "check_trigger_type",
"type": "condition",
"service": "IF",
"name": "안내 vs 리마인더 분기",
"config": {
"condition": "{{$json['triggerType'] === 'notice'}}"
}
},
{
"id": "send_notice_email",
"type": "action",
"service": "Gmail",
"name": "평가 안내 이메일 발송",
"config": {
"operation": "sendEmail",
"to": "{{$json['대상자이메일']}}",
"cc": "{{$json['평가자이메일']}}",
"subject": "[인사평가 안내] {{$json['평가명']}} — {{$json['daysToStart'] === 0 ? '오늘 시작!' : $json['daysToStart'] + '일 후 시작'}}",
"body": "안녕하세요!\n\n{{$json['평가명']}} 인사평가 안내드립니다.\n\n📅 평가 기간: {{$json['시작일']}} ~ {{$json['마감일']}}\n\n{{$json['daysToStart'] === 0 ? '오늘부터 평가가 시작됩니다!' : $json['daysToStart'] + '일 후 평가가 시작됩니다.'}}\n\n📝 평가 설문 바로가기:\n{{$json['설문URL']}}\n\n마감일 내에 제출해 주시기 바랍니다.\n{{$env.COMPANY_NAME}} HR팀 드림"
}
},
{
"id": "send_reminder_email",
"type": "action",
"service": "Gmail",
"name": "마감 D-1 리마인더 발송",
"config": {
"operation": "sendEmail",
"to": "{{$json['대상자이메일']}}",
"subject": "⚠️ [인사평가 마감 D-1] {{$json['평가명']}} 내일까지 제출해 주세요!",
"body": "안녕하세요!\n\n{{$json['평가명']}} 인사평가 마감이 내일({{$json['마감일']}})입니다.\n\n아직 제출하지 않으셨다면 오늘 중으로 완료해 주세요!\n\n📝 평가 설문 바로가기:\n{{$json['설문URL']}}\n\n{{$env.COMPANY_NAME}} HR팀 드림"
}
},
{
"id": "notify_hr_slack",
"type": "action",
"service": "Slack",
"name": "HR팀 발송 완료 알림",
"config": {
"operation": "sendMessage",
"channel": "{{$env.HR_SLACK_CHANNEL}}",
"message": "📧 인사평가 이메일 발송 완료\n\n평가명: {{$json['평가명']}}\n유형: {{$json['triggerType'] === 'notice' ? '안내 (' + $json['daysToStart'] + '일 전)' : '마감 D-1 리마인더'}}\n발송 시각: {{$now.format('YYYY-MM-DD HH:mm')}}"
}
}
],
"edges": [
{
"from": "trigger_daily",
"to": "get_eval_schedule"
},
{
"from": "get_eval_schedule",
"to": "check_schedule"
},
{
"from": "check_schedule",
"to": "check_trigger_type"
},
{
"from": "check_trigger_type",
"to": "send_notice_email",
"branch": "true"
},
{
"from": "check_trigger_type",
"to": "send_reminder_email",
"branch": "false"
},
{
"from": "send_notice_email",
"to": "notify_hr_slack"
},
{
"from": "send_reminder_email",
"to": "notify_hr_slack"
}
],
"tips": [
"미제출자 리마인더는 설문 응답 시트와 대상자 명단을 대조해 응답하지 않은 사람에게만 발송되도록 설정하면 정확도가 높아져요.",
"평가자와 피평가자에게 각각 다른 설문 URL을 발송하려면 Google Sheets에 '대상자설문URL'과 '평가자설문URL' 열을 분리해 관리하세요.",
"상반기·하반기 평가를 동시에 관리하려면 평가 일정 시트에 여러 행을 추가하면 돼요. 워크플로우 수정 없이 자동 처리됩니다."
],
"qrUrl": "www.koreaaitimes.com/books/n8n-vol2/recipe057"
}