RECIPE 020
고객 리뷰 자동 수집 → 긍정/부정 분류
- ▸데이터 수집 워크플로우의 병목 지점을 파악할 수 있다
- ▸SplitInBatches + Wait 노드로 API Rate Limit에 안전하게 대응할 수 있다
- ▸에러 발생 시 자동 재시도(Retry) 패턴을 구현할 수 있다
✅사전 준비
- □최적화 대상 워크플로우 1개 선정
- □해당 워크플로우의 Executions 탭에서 각 노드 실행 시간 확인
- □사용 중인 API의 Rate Limit 문서 확인 (분당/시간당 호출 한도)
SplitInBatches + Wait 조합 — Rate Limit 대응
SplitInBatches 설정:
Batch Size: 10 (API 한도에 맞게 조정)
Wait 노드 설정 (SplitInBatches 뒤에 연결):
Wait Amount: 1
Wait Unit: seconds
→ 10개 처리 후 1초 대기 반복자동 재시도 패턴 — Error Trigger 활용
1. Error Trigger 노드 추가 (별도 워크플로우)
2. 실패한 워크플로우 ID와 실행 ID를 수신
3. Wait 노드: 5분 대기
4. Execute Workflow 노드로 원본 워크플로우 재실행
※ 무한 루프 방지:
Sheets에 재시도 횟수 기록 → 3회 초과 시 Slack 알림 후 중단실행 시간 측정 — Code 노드
// 워크플로우 시작 시 저장
const startTime = Date.now();
return [{ json: { startTime } }];
// 워크플로우 종료 시 계산
const elapsed = Date.now() - $('시작노드').first().json.startTime;
return [{ json: { elapsedMs: elapsed, elapsedSec: (elapsed / 1000).toFixed(1) } }];💡 TIPn8n Executions 탭에서 각 노드의 실행 시간을 확인할 수 있어요. 가장 느린 노드부터 최적화하는 게 효율적입니다. 대부분의 병목은 외부 API 호출이나 대량 Sheets 쓰기에서 발생합니다.
⚠️ 주의n8n 클라우드 무료 플랜은 실행 시간이 5분으로 제한됩니다. 대량 데이터 처리 워크플로우는 Self-hosted 환경이나 유료 플랜을 권장합니다.
⚡
워크플로우 JSON
아래 JSON을 복사해 n8n에 바로 임포트하세요
📥 n8n 임포트 방법
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
{
"name": "recipe020_review_sentiment_classification",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 9 * * *"
}
]
}
},
"id": "schedule-020-01",
"name": "매일 오전 9시",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
200,
400
]
},
{
"parameters": {
"method": "GET",
"url": "={{ $env.REVIEW_API_URL }}",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"options": {}
},
"id": "http-020-02",
"name": "리뷰 데이터 수집",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
420,
400
]
},
{
"parameters": {
"model": "gpt-4o-mini",
"messages": {
"values": [
{
"role": "system",
"content": "다음 리뷰가 긍정적인지 부정적인지 판단해서 '긍정' 또는 '부정' 중 하나만 답하세요."
},
{
"role": "user",
"content": "={{ $json.review_text }}"
}
]
},
"options": {}
},
"id": "openai-020-03",
"name": "AI 감성 분류",
"type": "@n8n/n8n-nodes-langchain.openAi",
"typeVersion": 1.7,
"position": [
640,
400
]
},
{
"parameters": {
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.message.content }}",
"rightValue": "부정",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
}
},
"id": "if-020-04",
"name": "부정 리뷰 여부 확인",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
860,
400
]
},
{
"parameters": {
"resource": "message",
"operation": "post",
"channel": "#cs-alerts",
"text": "=⚠️ 부정 리뷰 감지!\n리뷰 내용: {{ $('리뷰 데이터 수집').item.json.review_text }}\n작성자: {{ $('리뷰 데이터 수집').item.json.author }}\n별점: {{ $('리뷰 데이터 수집').item.json.rating }}점"
},
"id": "slack-020-05",
"name": "CS팀 즉시 알림",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.2,
"position": [
1080,
300
]
},
{
"parameters": {
"operation": "append",
"documentId": {
"value": "={{ $env.REVIEW_SHEET_ID }}"
},
"sheetName": {
"value": "reviews"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"reviewText": "={{ $('리뷰 데이터 수집').item.json.review_text }}",
"author": "={{ $('리뷰 데이터 수집').item.json.author }}",
"rating": "={{ $('리뷰 데이터 수집').item.json.rating }}",
"sentiment": "={{ $('AI 감성 분류').item.json.message.content }}",
"collectedAt": "={{ $now.format('YYYY-MM-DD HH:mm') }}"
}
}
},
"id": "sheets-020-06",
"name": "전체 리뷰 시트 기록",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.4,
"position": [
1080,
500
]
}
],
"connections": {
"매일 오전 9시": {
"main": [
[
{
"node": "리뷰 데이터 수집",
"type": "main",
"index": 0
}
]
]
},
"리뷰 데이터 수집": {
"main": [
[
{
"node": "AI 감성 분류",
"type": "main",
"index": 0
}
]
]
},
"AI 감성 분류": {
"main": [
[
{
"node": "부정 리뷰 여부 확인",
"type": "main",
"index": 0
}
]
]
},
"부정 리뷰 여부 확인": {
"main": [
[
{
"node": "CS팀 즉시 알림",
"type": "main",
"index": 0
}
],
[
{
"node": "전체 리뷰 시트 기록",
"type": "main",
"index": 0
}
]
]
},
"CS팀 즉시 알림": {
"main": [
[
{
"node": "전체 리뷰 시트 기록",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"timezone": "Asia/Seoul"
},
"meta": {
"chapter": 2,
"recipe": "020",
"title": "고객 리뷰 자동 수집 → 긍정/부정 분류",
"difficulty": "⭐⭐⭐",
"estimatedTime": "50분",
"apps": [
"HTTP Request",
"OpenAI",
"Google Sheets",
"Slack"
]
}
}