매일 아침 뉴스 5개를 메일 한 통으로 — n8n RSS 이메일 자동화와 여러 아이템 합치는 법
이 글과 연결된 글 보기
드래그로 이동 · 휠/두 손가락으로 확대 · 방향키로 글 선택 · 0으로 맞춤. 실선: 본문 링크, 점선: 시리즈·주제의 대표 연결.표시된 글 7편 목록
관심 키워드로 구글 뉴스를 검색한 RSS 주소 하나만 있으면, n8n 노드 6개로 매일 아침 6시에 상위 기사 5개의 제목과 링크가 담긴 메일 한 통을 받을 수 있습니다. 코드는 한 줄도 없습니다. 대신 "아이템 5개를 어떻게 메일 1통으로 접는가"라는, 자동화를 만들다 보면 반드시 마주치는 문제를 Aggregate 노드로 푸는 법을 익히게 됩니다.
이 워크플로우 하나로 보여줄 수 있는 것
재고 알림 편이 "시트를 읽어 조건에 맞는 행만 알린다"였다면, 이 편은 "외부 피드를 읽어 정해진 개수만 모아 보낸다"입니다. 노드 6개짜리 작은 워크플로우지만, 면접에서 설명할 수 있는 역량은 세 가지가 됩니다.
- 외부 피드 읽기 — 구글시트 같은 내 데이터가 아니라, 남이 제공하는 RSS를 주기적으로 읽어 오는 경험
- 양 제어 — 피드에 수십 개가 들어와도 앞에서 5개만 남기고, 필요한 필드만 추리는 경험
- 여러 아이템을 하나로 — 아이템 5개를 메시지 1개로 접는 Aggregate 노드를 써보고, Code 노드 방식과 차이를 설명할 수 있는 경험
세 번째가 이 글의 중심입니다. n8n은 아이템 하나마다 다음 노드를 한 번씩 실행하기 때문에, 이 단계를 빼면 기사 5개가 메일 5통으로 나갑니다. "N개를 1개로" 접는 방법을 알고 있으면 뉴스 메일뿐 아니라 주간 리포트, 신규 문의 요약, 에러 목록 알림처럼 목록을 한 번에 보내야 하는 자동화 전부에 그대로 쓸 수 있습니다.
배경 — 매일 아침 검색창에 같은 키워드를 치는 일
새 도구를 공부하다 보면 관련 소식을 놓치고 싶지 않아 매일 아침 구글 뉴스에 같은 키워드를 검색하게 됩니다. 결과를 위에서 아래로 훑고, 몇 개 열어보고, 바쁜 날은 건너뜁니다. 이 워크플로우는 그 검색을 대신해 상위 5개를 메일로 넣어두는 것입니다. 원본은 데이터팝콘 n8n 인스턴스에 n8n이라는 검색어로 만들어져 있고, 같은 폴더에 "2장 구글RSS피드_레퍼런스"라는 이름의 이전 버전이 함께 남아 있는 걸 보면 강의 교재용으로 만든 것으로 보입니다.
교재답게 캔버스에는 Trigger, Task, Target이라고 적힌 스티키 노트 세 장이 노드 위에 붙어 있습니다. 데이터팝콘이 워크플로우를 설계할 때 쓰는 3T 프레임이 캔버스에 그대로 올라가 있는 셈이라, 이 글도 그 순서로 따라갑니다. 설치와 credential 연결 같은 기본은 n8n으로 반복업무 자동화 포트폴리오 만들기에 정리돼 있으니 여기서는 워크플로우 자체만 다룹니다. 이 편에 필요한 외부 준비물은 Gmail credential 하나뿐이고, 비용은 들지 않습니다.
구조 — Trigger / Task / Target
- Trigger — 매일 오전 6시 스케줄
- Task — RSS 읽기 → 5개만 남기기 → 제목·링크만 추리기 → 하나로 합치기
- Target — Gmail로 본인 메일함에 전송
원본 스티키 노트의 Task 칸에는 "5개의 뉴스를 가져와서 집계"라고 적혀 있습니다. "집계"라는 한 단어가 Limit부터 Aggregate까지 세 노드를 가리킵니다.
만들기
1. Schedule Trigger — 매일 오전 6시
Schedule Trigger 노드에서 Trigger Interval을 Days, Days Between Triggers를 1, Trigger at Hour를 6으로 둡니다. 시각은 워크플로우 설정의 타임존을 따르므로, 캔버스 우측 상단 메뉴의 Settings에서 Timezone이 Asia/Seoul인지 한 번 확인해두세요. 만드는 동안에는 이 노드를 기다리지 말고 Execute workflow 버튼으로 바로 돌려보면 됩니다.
2. RSS Read — 구글 뉴스 검색 결과를 피드로
RSS Read 노드의 URL에 구글 뉴스 검색 RSS 주소를 넣습니다. 원본에 들어 있는 주소는 이렇습니다.
https://news.google.com/rss/search?q=n8n&hl=ko&gl=KR&ceid=KR%3Ako
q= 뒤가 검색어입니다. 다른 키워드로 바꿀 때는 이 값만 고치면 되고, 한글 키워드는 URL 인코딩된 형태로 들어갑니다(브라우저 주소창에 한글로 검색한 뒤 주소를 복사하면 인코딩된 채로 나옵니다). hl, gl, ceid는 언어와 국가 설정이라 한국어 기사를 받으려면 그대로 두면 됩니다.
실행해보면 기사 하나가 아이템 하나가 되어 나옵니다. 출력 패널에서 title, link, pubDate, isoDate, contentSnippet 같은 필드가 들어오는 걸 확인해두세요. 다음 노드들이 이 이름을 그대로 씁니다.
3. Limit — 앞에서 5개만
Limit 노드에 Max Items를 5로 둡니다. 이 노드는 정렬을 하지 않고 들어온 순서대로 앞의 5개만 남깁니다. 피드 순서와 다르게 최신순을 보장하고 싶으면 Limit 앞에 Sort 노드를 넣고 isoDate 기준 내림차순으로 정렬하면 됩니다. 원본은 피드 순서를 그대로 믿고 Sort 없이 갑니다.
4. Edit Fields — 제목과 링크만 남기기
Edit Fields(Set) 노드에서 title과 link 두 필드만 만듭니다. 값은 각각 {{ $json.title }}, {{ $json.link }}입니다. Include Other Input Fields는 끈 상태라 이 노드를 지나면 아이템마다 필드가 딱 두 개만 남습니다.
이 노드가 Aggregate 앞에 있는 이유는 다음 단계에서 드러납니다. Aggregate는 들어온 아이템의 필드를 전부 하나로 모으기 때문에, 본문·요약·GUID까지 딸려 있는 채로 합치면 합쳐진 덩어리가 불필요하게 커지고 메일 본문을 조립하는 표현식도 그만큼 헷갈립니다. 합치기 전에 먼저 깎아두는 겁니다.
5. Aggregate — 아이템 5개를 1개로
여기가 이 워크플로우의 핵심입니다. Aggregate 노드에서 Aggregate를 All Item Data (Into a Single List)로 둡니다. 옵션은 손대지 않았습니다.
실행하면 입력이 5 items, 출력이 1 item으로 바뀝니다. 그 1개의 아이템 안에 data라는 배열이 생기고, 배열 원소가 방금 전 아이템 5개의 {title, link}입니다. 즉 이 노드를 지나면 다음 Gmail 노드는 한 번만 실행되고, 5개 기사는 $json.data로 한꺼번에 접근하게 됩니다.
재고 알림 편에서는 같은 문제를 Code 노드(Run Once for All Items)로 풀었습니다. 두 방식의 차이를 정리하면 이렇습니다.
- Code 노드 — 아이템을 합치는 일과 메시지 문자열을 만드는 일을 자바스크립트 한 곳에서 처리합니다. "총 N개" 같은 헤더, 조건에 따라 다른 문장, 정렬이나 계산이 필요하면 이쪽이 편합니다.
- Aggregate 노드 — 합치는 일만 합니다. 코드가 없고, 문자열 조립은 다음 노드의 표현식으로 넘어갑니다. 목록을 그대로 나열하면 되는 경우에는 이쪽이 더 단순하고, 캔버스만 봐도 "여기서 하나로 접힌다"가 보입니다.
둘 다 "N개를 1개로"라는 같은 일을 하고, 재고 편의 items.length는 여기서 $json.data.length로 그대로 쓸 수 있습니다. 고르는 기준은 간단합니다. 합치기만 필요하면 Aggregate, 합치면서 논리가 들어가야 하면 Code입니다.
6. Gmail — 메일 본문 조립과 전송
Gmail 노드에서 Resource를 Message, Operation을 Send로 두고 credential을 연결합니다. n8n cloud라면 Sign in with Google 버튼으로 끝나고, 셀프호스팅이면 Google Cloud 콘솔에서 OAuth 클라이언트를 만들어 넣어야 합니다. To에는 본인 메일 주소, Email Type은 Text입니다.
Subject에는 원본이 {{ $today.format("DD") }}의 뉴스를 넣었습니다. 그런데 $today는 Luxon DateTime이고, Luxon에서 DD는 "일(day)"이 아니라 로케일 날짜 프리셋이라 영문 로케일에서는 "Feb 12, 2026" 형태로 나옵니다. 우리말 제목을 원하면 {{ $today.format("M월 d일") }}의 뉴스나 {{ $today.format("yyyy-MM-dd") }}처럼 소문자 토큰으로 바꾸는 편이 낫습니다.
Message에는 아래를 그대로 넣습니다. data 배열을 돌면서 제목 한 줄, 링크 한 줄로 만들고 기사 사이를 빈 줄로 띄우는 표현식입니다.
오늘의 n8n뉴스
{{ $json.data.map(item => `${item.title}\n${item.link}`).join('\n\n') }}
map이 기사 5개를 "제목\n링크" 문자열 5개로 바꾸고, join('\n\n')이 그 사이를 빈 줄로 이어 붙입니다. 재고 편의 Code 노드가 하던 문자열 조립이 표현식 한 줄로 옮겨 온 것입니다. Execute workflow로 돌려 메일이 한 통만 오는지 확인한 뒤 Active 토글을 켜면, 다음 날 아침 6시부터 자동으로 갑니다.
원본 캔버스에 남아 있는 흔적 — 3T 스티키와 이전 버전
이 워크플로우는 운영 데이터를 쌓아 둔 게 아니라 교재용이라, 실행 결과 대신 캔버스에 남은 흔적을 옮깁니다. 스티키 노트는 세 장인데 내용은 짧습니다. Target 칸에 "구글 메일로 전송하기", Task 칸에 "5개의 뉴스를 가져와서 집계", 그리고 Trigger 칸은 제목만 있고 비어 있습니다. 스티키가 설명서가 아니라 설계 프레임 자체로 쓰인 경우라, 따라 만들 때도 노드를 놓기 전에 세 칸을 먼저 채워보는 연습을 해볼 만합니다.
더 흥미로운 건 같은 폴더의 레퍼런스 버전입니다. 두 버전을 나란히 보면 최종본으로 오면서 바뀐 점이 세 가지입니다.
- 필드 이름 불일치가 잡혔습니다. 레퍼런스 버전은 Set 노드에서
link라는 이름으로 필드를 만들어 놓고, 메일 본문 표현식에서는item.url을 참조합니다. 이러면 메일에 링크 자리마다undefined가 찍힙니다. 최종본은 둘 다link로 맞췄습니다. Aggregate로 합친 뒤 표현식에서 필드를 부를 때 가장 자주 나는 실수라, 본인 것도 Set의 필드명과 표현식의 필드명을 한 번 대조해보세요. - 필드가 줄었습니다. 레퍼런스 버전은
isoDate와contentSnippet까지 네 개를 남겼는데, 최종본은title과link둘만 남깁니다. 메일 본문에 쓰지 않는 필드는 합치기 전에 버린다는 4단계의 원칙이 여기서 나왔습니다. - 제목 포맷이 바뀌었습니다. 레퍼런스 버전은
{{ $today.format('yyyy-MM-dd') }}의 뉴스레터였고, 최종본이DD로 바뀌면서 위에서 말한 로케일 프리셋 문제가 생겼습니다. 이 한 곳은 레퍼런스 쪽이 더 낫습니다.
한계
- 링크가 기사 원문 주소가 아닙니다. 구글 뉴스 RSS의
link는 news.google.com을 거쳐 가는 주소이지 기사 자체의 URL이 아닙니다. 원문 주소를 시트나 노션에 남기려면 디코딩 단계가 하나 더 필요한데, 이건 다른 편에서 따로 다룹니다. - 어제 본 기사가 또 옵니다. 피드의 앞 5개를 그대로 보내므로 새 기사가 없는 날은 같은 목록이 다시 옵니다. Limit 앞에 Filter 노드를 두고
isoDate가 최근 24시간 안인 것만 통과시키면 "새 기사가 없으면 메일도 없음"으로 바꿀 수 있습니다. - 텍스트 메일입니다. Email Type이 Text라 제목·링크가 줄글로 나열됩니다. 제목을 링크로 감싼 HTML로 바꾸면 읽기 좋아지지만, 텍스트로 먼저 성공시키고 나서 바꾸는 걸 권합니다.
- 실패하면 아무도 모릅니다. RSS 주소가 바뀌거나 Gmail 토큰이 만료되면 메일이 안 올 뿐 알림이 없습니다. 이 부분은 다음 편의 주제입니다.
포트폴리오·면접 포인트
포트폴리오에는 캔버스 스크린샷 한 장과 도착한 메일 캡처 한 장, 그리고 Aggregate 노드의 입력 5 items · 출력 1 item이 보이는 실행 화면 한 장을 권합니다. 세 번째 캡처가 있으면 "여러 아이템을 하나로 합치는 단계를 이해하고 만들었다"는 게 설명 없이 전달됩니다.
응용은 검색어와 수신자만 바꿔도 됩니다. 지원하려는 회사 이름을 검색어로 넣어 면접 전날 아침 관련 기사를 받아보면 실제로 쓸모가 있고 면접에서 이야깃거리도 됩니다. 한 단계 더 가려면 RSS Read 노드를 여러 개 놓고 Merge로 합친 뒤 Limit을 거는 구조로 키워드 여러 개를 한 통에 담아보세요.
면접에서 나올 법한 질문은 "왜 Code 노드를 안 쓰고 Aggregate를 썼나요?"입니다. 합치기만 필요한 곳에 코드를 쓰면 다음 사람이 읽어야 할 자바스크립트가 하나 늘어난다는 점, 그리고 조건이나 계산이 들어가는 순간에는 반대로 Code로 가겠다는 기준까지 말하면 도구 선택에 근거가 있는 사람으로 보입니다.
다음 액션
재고 알림, 날씨 알림, 그리고 이 뉴스 메일까지 세 편은 모두 "정해진 시각에 어딘가에서 읽어 어딘가로 보낸다"는 같은 뼈대입니다. 셋 다 공통으로 빠져 있는 게 하나 있는데, 실패했을 때 조용히 멈춘다는 점입니다. 다음 편에서는 워크플로우가 에러로 죽었을 때 그 사실을 슬랙으로 받는 Error Trigger를 붙입니다. 그것까지 붙이면 "만들어봤다"가 아니라 "운영까지 생각했다"고 포트폴리오에 쓸 수 있습니다.
