본문으로 건너뛰기
취준생을 위한 n8n 실전 워크플로우 레시피 · 2/44시리즈 보기 →

매일 아침 7시 날씨를 디스코드로 받는 n8n 날씨 알림 — 시트 대신 외부 API를 읽는 첫 워크플로우

· 약 10분
Datapopcorn CEO / AI automation educator
이 글과 연결된 글 보기
7편 · 19개 연결
100%
매일 아침 7시 날씨를 디스코드로 받는 n8n 날씨 알림 — 시트 대신 외부 API를 읽는 첫 워크플로우n8n Data Table 처음 써보기 — 트렌드 3개를 합쳐 매일 아침 분석 주제 뽑는 워크플로우n8n으로 정적 웹서버 운영하기 — 수료증 발급부터 진위 확인까지, 멱등 처리로 안전하게벡터DB 없이 실시간으로 사이트를 읽는 챗봇 — 경복대학교 안내 챗봇 해부n8n으로 반복업무 자동화 포트폴리오 만들기실패해도 안 죽는 슬랙 알림 — n8n의 재시도(retryOnFail)와 에러 분기(continueErrorOutput)서브워크플로우를 Tool로 감싸 AI Agent에게 서버 점검시키기 — 그리고 시스템 프롬프트만으로는 부족한 이유

드래그로 이동 · 휠/두 손가락으로 확대 · 방향키로 글 선택 · 0으로 맞춤. 실선: 본문 링크, 점선: 시리즈·주제의 대표 연결.

표시된 글 7편 목록
전체 글 연결 탐색

OpenWeatherMap 무료 API 키 하나와 n8n 노드 5개면, 매일 아침 7시에 서울의 현재 날씨와 앞으로 15시간 예보 표가 디스코드 채널에 도착하는 알림을 만들 수 있습니다. 재고 알림 편에서 구글시트를 읽던 자리에 외부 API가 들어오는 것뿐인데, 이 교체 한 번으로 "API 키를 어디에 두는가"와 "Unix 시각을 한국 시간으로 어떻게 바꾸는가"라는, 모든 API 워크플로우에 따라오는 두 가지를 손에 익히게 됩니다.

이 워크플로우 하나로 보여줄 수 있는 것​

재고 알림 편은 "내 시트를 읽어서 조건에 맞으면 알려줘"였습니다. 이 편은 데이터가 내 손에 없습니다. 남의 서버가 가진 데이터를 API로 받아와 내 채널에 맞게 다듬어 보내는 흐름이고, 포트폴리오에 "외부 API 연동 경험"이라고 쓸 수 있는 가장 작은 단위입니다. 안에 들어간 역량은 세 가지입니다.

  • 외부 API 호출과 키 관리 — API 키를 노드 안에 적지 않고 n8n credential에 넣어, export하거나 공유해도 키가 따라 나가지 않게 만드는 습관
  • 타임스탬프와 시간대 변환 — API가 주는 Unix 초 단위 시각을 Asia/Seoul 기준으로 읽을 수 있게 바꾸는 표현식
  • 두 응답 합치기 — 현재 날씨와 예보라는 서로 다른 응답을 Merge 노드로 아이템 하나에 모아 메시지 한 통을 만드는 구조

환율, 공공데이터, 서비스 상태 페이지처럼 "정해진 시각에 외부 API를 읽어 알려줘" 유형이라면 이 세 가지에서 URL과 필드 이름만 바뀝니다.

배경 — 출근 전 날씨 앱을 여는 대신​

날씨는 매일 확인하지만 매일 잊는 정보입니다. 출근 준비 중에 앱을 열어 우산을 챙길지 정하고, 해가 몇 시에 지는지는 또 따로 찾아봅니다. 이 워크플로우는 그 확인을 "아침 7시에 팀 디스코드 채널에 올라와 있는 메시지 한 통"으로 바꾼 것입니다. 원본 캔버스의 스티키 노트에도 목적이 한 줄로 적혀 있습니다. "openweathermap.org API를 통해 얻어온 날씨 정보를 디스코드에 매일 아침 7시에 발송."

재고 알림 편에서 "Google Sheets 노드 자리에 HTTP Request 노드가 들어간다"고 예고했는데, 실제 원본에는 그 자리에 n8n의 전용 OpenWeatherMap 노드가 들어 있습니다. 이 노드는 겉모습만 다를 뿐 속은 HTTP Request입니다. 내부적으로 /data/2.5/weather와 /data/2.5/forecast를 호출하고, credential의 키를 appid 쿼리 파라미터로 붙여 줍니다. 전용 노드가 있으면 그걸 쓰고 없을 때 HTTP Request를 직접 쓰는데, 원본 캔버스에는 직접 부른 테스트 흔적도 남아 있어 두 방식을 나란히 볼 수 있습니다.

설치나 기본 노드 설명은 n8n으로 반복업무 자동화 포트폴리오 만들기에 있으니, 이 글에서는 워크플로우 자체만 다룹니다.

선행조건 — OpenWeatherMap 무료 API 키

OpenWeatherMap 가격 페이지 기준(2026년 8월)으로 무료 플랜은 분당 60회, 월 1,000,000회까지 호출할 수 있고, 이 워크플로우가 쓰는 Current Weather API와 3시간 간격 5일 예보(3-hour Forecast 5 days)가 둘 다 포함됩니다. 회원가입 후 API keys 메뉴에서 키를 발급받으면 됩니다. One Call 계열 API는 무료 플랜 목록에 없고 별도의 호출당 과금 구독인데, 이 글의 본 흐름에는 필요 없습니다.

구조 — Trigger / Task / Target​

데이터팝콘은 워크플로우를 언제 시작하는가(Trigger), 무엇을 하는가(Task), 어디로 보내는가(Target) 세 칸으로 나눠 봅니다. 이 워크플로우는 트리거 하나에서 두 갈래가 나뉩니다.

  • Trigger — 매일 아침 7시 스케줄
  • Task — 현재 날씨와 5일 예보를 각각 받기 → 한국 시간으로 변환 → 메시지 문자열 조립 (선택: Merge로 두 응답을 아이템 하나로 합치기)
  • Target — 디스코드 웹훅 채널 두 통, 또는 Merge를 거친 슬랙 한 통

디스코드 갈래가 원본의 본 흐름이고, Merge → Slack 갈래는 두 응답을 하나로 합치는 패턴을 보여주는 확장이라 마지막에 같이 다룹니다.

만들기​

0. API 키는 credential에 넣기​

n8n의 Credentials 메뉴에서 OpenWeatherMap API를 추가하고 발급받은 키를 Access Token 칸에 붙여 넣습니다. 이후 OpenWeatherMap 노드는 이 credential을 고르기만 하면 되고, 키는 워크플로우 JSON 어디에도 남지 않습니다.

이걸 첫 단계로 둔 이유는 원본 캔버스에 반대 예시가 남아 있기 때문입니다. Set 노드에 app_id 필드로 키를 넣고 HTTP Request URL에 appid={{ $json.app_id }}로 이어 붙인 테스트 흐름인데, 이렇게 만들면 export한 JSON 파일에 키가 그대로 박힙니다. 공개할 워크플로우라면 이 차이가 곧 평가 포인트입니다.

1. Schedule Trigger — 매일 아침 7시​

Schedule Trigger 노드에서 Trigger Interval을 Days, Trigger at Hour를 7로 둡니다. 스케줄은 워크플로우 Settings의 Timezone을 따르므로 Asia/Seoul로 되어 있는지 확인해 두세요. 실습 중에는 Execute workflow 버튼으로 바로 돌려보고, 마지막에 Active를 켜면 그때부터 매일 7시에 돕니다.

2. OpenWeatherMap 노드 두 개 — 현재 날씨와 5일 예보​

트리거 뒤에 OpenWeatherMap 노드를 두 개 나란히 붙입니다. 둘 다 Location Selection은 City Name, City는 seoul, Language는 kr이고, 하나는 Operation을 Current Weather로, 다른 하나는 5 Day Forecast로 둡니다. Format은 기본값 Metric이라 기온이 섭씨로 오고, Language가 kr이라 날씨 설명이 한국어로 옵니다.

실행하고 출력 패널에서 응답 모양을 확인해 두세요. 다음 노드의 표현식이 이 필드 이름을 씁니다.

  • 현재 날씨: main.temp(기온), main.feels_like(체감), weather[0].description(날씨 설명), sys.sunrise·sys.sunset(일출·일몰), dt(관측 시각)
  • 5일 예보: list 배열에 3시간 간격 항목이 들어 있고, 항목마다 dt, main.temp, weather[0].description이 있습니다

시각 필드는 전부 Unix 초 단위 숫자라 그대로 보내면 아무도 못 읽습니다. 다음 단계의 표현식이 이걸 한국 시간으로 바꿉니다.

3. Discord — 웹훅으로 현재 날씨 보내기​

디스코드 채널 설정의 연동(Integrations) 메뉴에서 웹훅을 만들고 URL을 복사한 뒤 n8n에 Discord Webhook credential로 저장합니다. Discord 노드에서 Connection Type을 Webhook으로 두고 그 credential을 고르면 됩니다. 웹훅 URL도 키와 마찬가지로 노드 안에 직접 적지 않습니다.

Message의 Content에는 원본 표현식을 그대로 넣습니다.

⏰ {{ $json.dt.toDateTime('s').setZone('Asia/Seoul').format('LLL dd yyyy, HH:mm:dd') }} 기준

현재 서울은 "{{ $json.weather[0].description }}" 입니다.
현재 기온은 {{ $json.main.temp }}'C (체감 온도 {{ $json.main.feels_like }}'C)

🌅일출시각 : {{ $json.sys.sunrise.toDateTime('s').setZone('Asia/Seoul').format('HH:mm:dd') }}
🌇일몰시각 : {{ $json.sys.sunset.toDateTime('s').setZone('Asia/Seoul').format('HH:mm:dd') }}

핵심은 toDateTime('s').setZone('Asia/Seoul').format(...) 세 단계입니다. toDateTime('s')가 초 단위 Unix 숫자를 날짜 객체로 만들고, setZone('Asia/Seoul')이 시간대를 한국으로 옮기고, format()이 읽을 수 있는 문자열로 바꿉니다. API에서 받은 시각을 다룰 때는 이 세 단계를 한 묶음으로 기억해 두세요.

다만 복사해 쓸 때 두 군데는 고치는 게 좋습니다. 원본의 HH:mm:dd에서 dd는 초가 아니라 "일(day)"이라, 일출 시각이 06:12:17처럼 나오면 끝의 17은 17일이라는 뜻입니다. HH:mm으로 바꾸면 되고, 기온 뒤의 'C도 °C로 바꾸는 편이 읽기 좋습니다.

4. Discord — 예보 표 보내기​

5일 예보 노드 뒤에는 Discord 노드를 하나 더 붙이고 Content에 표를 조립합니다. 디스코드는 마크다운 표를 그려주지 않아서 원본은 코드 블록 안에 파이프로 구분한 텍스트 표를 넣었습니다. list[2]부터 list[4]까지 같은 형식으로 세 줄이 더 있습니다.

```
| 날짜 및 시간 | 날씨 상태 | 기온 ('C) |
| {{ $json.list[0].dt.toDateTime('s').setZone('Asia/Seoul').format('yyyy-MM-dd T') }} | {{ $json.list[0].weather[0].description }} | {{ $json.list[0].main.temp }} |
| {{ $json.list[1].dt.toDateTime('s').setZone('Asia/Seoul').format('yyyy-MM-dd T') }} | {{ $json.list[1].weather[0].description }} | {{ $json.list[1].main.temp }} |
```

list[0]부터 list[4]까지 다섯 줄이므로 3시간 간격 기준 앞으로 약 15시간치가 표에 들어갑니다. format('yyyy-MM-dd T')의 T는 시각을 09:00 같은 24시간 표기로 찍는 토큰입니다. 두 Discord 노드를 실행해 채널에 메시지가 두 통 도착하면 본 흐름은 완성입니다.

5. (선택) Merge → Slack — 두 응답을 한 통으로​

디스코드 갈래는 현재 날씨와 예보가 두 통으로 나뉘어 옵니다. 원본 캔버스에는 이걸 한 통으로 합친 슬랙 갈래가 같이 있습니다. 현재 날씨 노드와 예보 노드의 출력을 Merge 노드의 입력 1, 2에 각각 연결하고 Mode를 Combine, Combine By를 Position으로 두면 두 노드의 첫 아이템이 하나로 합쳐집니다. 결과 아이템에 main.temp와 list가 같이 들어 있으니, 뒤의 Slack 노드(Message Type: Blocks, 채널 선택) 하나에서 위의 두 표현식을 한 메시지에 쓸 수 있습니다.

재고 편의 Code 노드가 여러 행을 문자열 하나로 합쳤다면, 여기서는 Merge 노드가 서로 다른 출처의 아이템을 필드 단위로 합칩니다.

원본 캔버스에 남아 있는 흔적 — 키를 어디에 두느냐의 차이​

이 워크플로우는 교육용이라 운영 데이터는 없습니다. 대신 캔버스에 본 흐름과 연결되지 않은 노드가 여럿 떠 있고 스티키 노트가 용도를 적어 두고 있어서 그걸 옮깁니다.

첫째는 "API 테스트 — 본인의 API_KEY를 입력 후 실행"이라는 스티키 아래의 Set → HTTP Request 두 노드입니다. HTTP Request가 One Call 3.0 API의 timemachine 엔드포인트를 위도·경도와 appid={{ $json.app_id }}로 호출합니다. 전용 노드 없이 API를 부를 때의 뼈대인데, 키가 Set 노드에 있다는 점과 One Call 계열은 무료 플랜 밖이라는 점을 짚어 둘 만합니다. 지금 만든다면 HTTP Request 노드의 Authentication을 Generic Credential Type → Query Auth로 두고 appid를 credential에 저장하면 URL에 키를 이어 붙일 필요가 없습니다.

둘째는 "모바일, 크롬 푸시 알림 — 앱 설치 후 연동"이라는 스티키 아래의 Pushbullet·Pushover 노드입니다. 메시지 표현식이 디스코드 노드와 완전히 같아서, Target만 바꾸면 되는 구조라는 것을 캔버스가 보여줍니다.

셋째는 작은 흔적 두 개입니다. 현재 날씨를 보내는 Discord 노드 이름이 "날씨 예보 발송", 예보 표를 보내는 노드가 "현재 날씨 발송"으로 서로 바뀌어 있습니다. 실행에는 영향이 없지만 노드 이름은 하는 일 그대로 붙이는 게 좋습니다. 그리고 슬랙 갈래에서는 HH:mm:dd가 HH:mm:ss로, 'C가 °C로 고쳐져 있어, 디스코드 버전을 먼저 만들고 슬랙 버전에서 다듬은 순서가 남아 있습니다.

한계​

  • 예보 범위가 짧습니다 — list[0]~list[4]는 앞으로 15시간이라 "내일 날씨"는 없습니다. 같은 폴더의 다른 버전에서는 list[7](약 21시간 뒤)을 "tomorrow"로 뽑아 둔 흔적이 있으니, 원하는 시점의 인덱스를 골라 쓰면 됩니다.
  • 도시가 고정입니다 — seoul이 노드에 박혀 있습니다. 여러 도시를 돌리려면 도시 목록 아이템을 만들어 City에 {{ $json.city }}처럼 표현식으로 넣어야 합니다.
  • 실패하면 조용히 멈춥니다 — 키가 만료되거나 응답이 비면 메시지가 안 올 뿐 아무도 모릅니다. Error Trigger 편에서 따로 다룹니다.
  • 메시지 길이 — 디스코드 웹훅 메시지 본문은 2,000자까지입니다. 예보를 늘리거나 여러 도시를 한 통에 넣으면 이 한도에 걸릴 수 있습니다.

포트폴리오·면접 포인트​

포트폴리오에는 캔버스 스크린샷, 디스코드에 도착한 메시지 캡처, 키를 가린 credential 설정 화면 세 장이 좋습니다. 세 번째가 있으면 "키를 어디에 뒀는지"를 말하지 않아도 보여줄 수 있습니다.

응용은 두 방향이 자연스럽습니다. 하나는 재고 편의 Filter를 가져와 비나 눈 예보가 있는 날만 보내는 것입니다. 다른 하나는 같은 무료 플랜에 포함된 Air Pollution API로 미세먼지를 같은 메시지에 붙이는 것인데, OpenWeatherMap 노드에 없는 API라 HTTP Request + Query Auth credential을 직접 써 보는 연습이 됩니다.

면접에서는 "API 키를 왜 credential에 넣었나요?"나 "시각이 왜 9시간 어긋났나요?" 같은 질문이 올 수 있습니다. 앞의 답은 export와 공유 시 키 노출을 막기 위해서, 뒤의 답은 API가 UTC 기준 Unix 초를 주기 때문에 setZone으로 시간대를 옮겨야 한다는 것입니다. 둘 다 외부 시스템의 데이터를 내 환경으로 가져올 때 무엇이 달라지는지 이해했다는 답입니다.

다음 액션​

여기까지 만들면 "정해진 시각에 외부 API를 읽어 채널로 보낸다"는 틀이 손에 익습니다. 다음 편은 API 대신 RSS를 읽습니다. 뉴스 RSS 피드 5개를 모아 매일 메일 한 통으로 보내는 워크플로우인데, 소스가 여러 개일 때 아이템을 어떻게 모으는지를 다룹니다. 그다음에 이 편의 한계에서 미룬 Error Trigger 편으로 넘어갑니다.