발행일: 2026-10-06(화) 11:44
← 목차로 돌아가기|하루 30분 n8n 시리즈 ② 실무 자동화 레시피 100
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 클릭
{
  "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"
}
← 이전 레시피☰ 목차다음 레시피 →