RECIPE 074
GitHub 이슈 → 작업 일정 자동 생성
- ▸GitHub 신규 이슈 생성 시 Google Calendar에 작업 일정 자동 등록
- ▸이슈 라벨에 따라 우선순위 및 예상 소요시간 자동 설정
- ▸마감 기한 초과 이슈 자동 감지 및 담당자 알림
✅사전 준비
- □GitHub 리포지토리 웹훅 등록 (Issues 이벤트)
- □Google Calendar API OAuth2 설정
- □이슈 라벨과 예상 소요시간 매핑 테이블 준비
- □Slack 알림 채널 설정
라벨별 소요시간 매핑 (Code 노드)
const labels = $json.issue.labels.map(l => l.name);
const durationMap = {
'bug': 2, // 2시간
'feature': 8, // 8시간
'hotfix': 1, // 1시간
'documentation': 3,
'enhancement': 4
};
const priorityMap = {
'critical': 1,
'high': 2,
'medium': 3,
'low': 4
};
const duration = labels.reduce((max, l) => Math.max(max, durationMap[l] || 2), 2);
const priority = labels.reduce((min, l) => Math.min(min, priorityMap[l] || 3), 3);
return [{ json: { ...$json, estimatedHours: duration, priority } }];Google Calendar 이벤트 생성
Node: Google Calendar (Create Event)
Calendar ID: YOUR_CALENDAR_ID
제목: [#{{ $json.issue.number }}] {{ $json.issue.title }}
시작: {{ $now.plus({hours: 1}).toISO() }}
종료: {{ $now.plus({hours: 1 + $json.estimatedHours}).toISO() }}
설명: {{ $json.issue.html_url }}
색상: {{ $json.priority === 1 ? '빨강' : $json.priority === 2 ? '노랑' : '파랑' }}💡 TIPGoogle Calendar 색상 ID는 숫자로 지정합니다: 11(빨강), 5(노랑), 9(파랑), 2(초록). Google Calendar API 문서에서 전체 색상 목록을 확인하세요.
⚡
워크플로우 JSON
아래 JSON을 복사해 n8n에 바로 임포트하세요
📥 n8n 임포트 방법
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
{
"recipeId": "recipe074",
"title": "팟캐스트 에피소드 → 다채널 자동 공유",
"chapter": 7,
"category": "콘텐츠 & 미디어 자동화",
"difficulty": "⭐⭐",
"estimatedTime": "30분",
"usedApps": [
"RSS Feed",
"Twitter",
"Facebook",
"Slack"
],
"description": "팟캐스트 RSS 피드에 새 에피소드가 등록되면 에피소드 제목·요약·링크를 자동 추출해 Twitter, Facebook 페이지, 팀 Slack에 동시 발행합니다. 채널별로 최적화된 메시지 형식으로 자동 변환해 발송합니다.",
"nodes": [
{
"id": "node1",
"type": "n8n-nodes-base.rssFeedReadTrigger",
"name": "팟캐스트 새 에피소드 감지",
"parameters": {
"url": "={{$env.PODCAST_RSS_URL}}",
"pollTimes": {
"item": [
{
"mode": "everyHour"
}
]
}
}
},
{
"id": "node2",
"type": "n8n-nodes-base.twitter",
"name": "Twitter 발행",
"parameters": {
"operation": "create",
"text": "🎙 새 에피소드 공개!\n\n{{$json['title']}}\n\n{{$json['contentSnippet'].slice(0, 80)}}...\n\n▶️ 듣기: {{$json['link']}}\n\n#팟캐스트 #podcast"
}
},
{
"id": "node3",
"type": "n8n-nodes-base.facebookGraphApi",
"name": "Facebook 페이지 발행",
"parameters": {
"node": "={{$env.FACEBOOK_PAGE_ID}}",
"edge": "feed",
"method": "POST",
"body": {
"message": "🎙 새 에피소드가 공개되었습니다!\n\n{{$json['title']}}\n\n{{$json['contentSnippet']}}\n\n지금 바로 들어보세요 👇",
"link": "={{$json['link']}}"
}
}
},
{
"id": "node4",
"type": "n8n-nodes-base.slack",
"name": "팀 Slack 공유",
"parameters": {
"channel": "={{$env.CONTENT_SLACK_CHANNEL}}",
"text": "🎙 새 팟캐스트 에피소드 발행!\n\n*{{$json['title']}}*\n{{$json['contentSnippet'].slice(0, 150)}}...\n\n▶️ {{$json['link']}}"
}
}
],
"envVariables": {
"PODCAST_RSS_URL": "팟캐스트 RSS 피드 URL",
"FACEBOOK_PAGE_ID": "Facebook 페이지 ID",
"CONTENT_SLACK_CHANNEL": "콘텐츠 팀 Slack 채널 ID"
},
"tips": [
"Twitter는 280자 제한이 있으므로 contentSnippet을 적절히 자르는 slice() 처리를 꼭 적용하세요.",
"인스타그램은 API 정책상 텍스트만으로 포스팅이 불가하므로 에피소드 커버 이미지 URL이 RSS에 포함된 경우 이미지와 함께 발행할 수 있어요.",
"레시피 012(블로그 → SNS 자동 공유)와 구조가 동일해요. 두 레시피를 함께 참고하면 다채널 배포 패턴을 빠르게 이해할 수 있어요."
],
"qrUrl": "www.koreaaitimes.com/books/n8n-vol2/recipe074"
}