[문과생도 n8n] 기사수집해서 chatGPT이용하여 내용을 요약 후 메일링 (최종)

소개

(지난 번 글을 작성한 이후 진행된 내용을 더하여 글을 작성함)

하루 동안 발생한 중요한 기사와 그 내용을 요약

요약한 기사를 대시보드 형태로 웹형식으로 html파일을 만들고

지메일에 발송함.

진행 방법

1. 사용한 툴 소개

  • n8n: 워크프로우 자동화 플랫폼

  • ChatGPT: n8n에서 ChatGPT node를 사용하여 뉴스기사 요약 진행

  • Lovable: 대시보드 웹시각화 디자인

  • tavily: 뉴스기사 수집 api

 

2. 워크플로우

(1) 워크플로우1

프로세스의 흐름을 보여주는 다이어그램
  • 스케쥴링: 매일 밤 12시 업데이트

  • 뉴스기사 수집

  • 수집된 html구조 변경

    return $json["results"].map(item => {
      return {
        json: {
          title: item.title,
          original_text: item.content,       // 이름 변경
          url: item.url,
          published_date: item.published_date,
          score: item.score ?? null          // 필요 시 score 유지
        }
      };
    });
  • 원하는 컬럼만 남기기

  • 뉴스기사 요약, 주제와 세부주제 선정, 키워드 선정

  • 구글시트에 넣을 형식으로 데이터 정리(제목에서 출처분리, 수집일 컬럼 만들기)

    const items = $input.all();
    const now = new Date().toISOString().split("T")[0];  // "2025-06-04" 형식
    
    for (let i = 0; i < items.length; i++) {
      const item = items[i];
      const raw = item.json?.message?.content || "";
      let parsed = {};
    
      try {
        parsed = JSON.parse(raw);
      } catch (e) {
        item.json = { error: "JSON parse failed", raw_content: raw };
        continue;
      }
    
      const fullTitle = parsed.title || "";
      const splitTitle = fullTitle.split(" - ");
      const cleanTitle = splitTitle[0]?.trim() || "";
      const source = splitTitle[1]?.trim() || "";
    
      const idNumber = String(i + 1).padStart(3, "0"); // 001, 002, ...
      const id = `news-${idNumber}`;
    
      item.json = {
        id: id,
        title: cleanTitle,
        source: source,
        original_text: parsed.original_text || "",
        url: parsed.url || "",
        published_date: parsed.published_date || "",
        collected_date: now,  // ✅ 오늘 날짜를 수집일로 저장
        theme: parsed.theme || "",
        sub_theme: parsed.sub_theme || "",
        summary: parsed.summary || "",
        keywords: parsed.keywords || ""
      };
    }
    
    return items;
  • 구글시트에 저장

그것에 한자가있는 테이블

(2) 워크플로우2

스마트 워치의 다른 부분을 보여주는 다이어그램
  • 구글시트에서 데이터 읽기

  • html 구조로 변환

    const today = new Date().toLocaleDateString('ko-KR', {
      year: 'numeric',
      month: 'long',
      day: 'numeric'
    });
    
    function escapeHTML(str) {
      return str?.replace(/[&<>"']/g, (m) => ({
        '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;'
      })[m]) ?? '';
    }
    
    const articles = $input.all().map(item => item.json);
    
    const html = `
    <!DOCTYPE html>
    <html lang="ko">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>오늘의 뉴스 대시보드</title>
      <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body class="bg-gradient-to-br from-slate-50 to-blue-50 min-h-screen">
      <div class="p-6 space-y-6 max-w-7xl mx-auto">
        <div class="text-center space-y-2">
          <h1 class="text-4xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
            오늘의 주요 뉴스
          </h1>
          <p class="text-sm text-gray-600">📅 ${today} 기준</p>
          <p class="text-lg text-muted-foreground">최신 뉴스를 한눈에 확인하세요</p>
        </div>
        <div class="flex justify-center">
          <input 
            id="searchInput"
            placeholder="키워드로 검색..." 
            class="max-w-md w-full shadow-sm border border-blue-200 focus:border-blue-400 transition-colors h-10 rounded-md px-3 py-2 text-base"
          />
        </div>
        <div id="newsContainer" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
          ${
            articles.map(a => `
              <div class="news-card rounded-2xl shadow-md bg-white p-6 space-y-3 hover:shadow-lg transition">
                <h2 class="text-lg font-semibold text-gray-800">
                  <a href="${escapeHTML(a.url)}" target="_blank" class="hover:underline text-blue-600">
                    ${escapeHTML(a.title)}
                  </a>
                </h2>
                <p class="text-sm text-gray-600">출처: ${escapeHTML(a.source)} | 작성일: ${escapeHTML(a.published_date)}</p>
                <p class="text-base">${escapeHTML(a.summary)}</p>
                <div class="text-sm italic text-gray-600">키워드: ${escapeHTML(a.keywords)}</div>
                <div class="text-sm italic text-gray-600">
                  주제: ${escapeHTML(a.theme)}<br>
                  세부주제: ${escapeHTML(a.sub_theme)}
                </div>
              </div>
            `).join('\n')
          }
        </div>
        <div class="text-center pt-8">
          <p class="text-sm text-gray-500">
            더 많은 뉴스는 각 기사의 원문 링크를 확인해주세요.
          </p>
        </div>
      </div>
      <script>
        document.getElementById('searchInput').addEventListener('input', function () {
          const query = this.value.toLowerCase();
          const cards = document.querySelectorAll('.news-card');
          cards.forEach(card => {
            const text = card.innerText.toLowerCase();
            card.style.display = text.includes(query) ? 'block' : 'none';
          });
        });
      </script>
    </body>
    </html>
    `;
    
    return [{ json: { html } }];
  • html 다운로드 파일 생성

    const html = items[0].json.html; // 또는 직접 HTML 문자열
    
    return [
      {
        binary: {
          data: {
            data: Buffer.from(html, 'utf-8').toString('base64'),
            mimeType: 'text/html',
            fileName: 'news_dashboard.html'
          }
        }
      }
    ];
  • Gmail로 보내기

한국 뉴스 웹 사이트의 스크린 샷

결과와 배운점

평소에 내가 생각하는 것들을 간단히 구현해보고 싶은 욕구가 있었으나

개발을 배우는 것에 대한 부담이 커서 시도를 못했는데

개발을 모르는 사람도 완벽하지는 않지만 생각을 초안 정도는 구현해 볼 수 있는 시대가 열린 것 같다.

 

이렇게 하기까지 n8n의 역할도 컸지만 무엇보다 chatGPT의 역할이 컸다.

chatGPT가 내가 전혀 모르는 언어들을 만들어주었기 때문에 해낼 수 있었다.

다만, 자바스크립트 코드를 잘못 작성해줘서 여러차레 물어봐야 했다.

이부분은 클로드가 훨씬 잘 한다고 하기에 다음에 사용해보고 싶다.

또 lovable은 chatGPT보다 훨씬 디자인을 잘해주는 것 같다.

 

처음에 n8n을 익히는데 약간 버거웠지만 익숙해지니 뚝딱 데이터 수집부터 메일링까지 완성하였다.

 

n8n을 활용하기 위해서는 다음과 같은 것들에 익숙해지면 좋을 것 같다.

- n8n에서 제공하는 노드들의 활용법

- LLM이 제공한 자바스크립트를 이해하고 수정할 수 있는 능력

- LLM 프롬프트 활용능력 (SYSTEM PROMPT, USER PROMPT, LANG CHAIN)

 

앞으로도 내가 그동안 해보고 싶었던 것들

그리고 내 생활에서 자동화가 가능한 부분들을 찾아서 자동화를 진행해봐야겠다.

5
2개의 답글

뉴스레터 무료 구독