본문 바로가기

카테고리 없음

[n8n 인프런 챌린지] 2주차: 하루 두 번, 슬랙으로 받는 날씨 + 미세먼지 알리미 만들기 ☀️

시작하게 된 이유

지난주에 이어 인프런 n8n 챌린지 2주차~~~
이번 챕터의 미션은 "OpenWeatherMap API로 날씨 알리미 만들기"입니다!
지난주가 데이터를 '읽어오는' RSS였다면, 이번은 데이터를 '가공해서 다듬는' 작업을 많이 했던 것 같아요!

이번에도 심화 미션까지 같이 풀어봤습니다.

  • 거주지(수원) + 자주 가는 도시(서울)를 동시에 조회하기
  • OpenWeatherMap 외에 다른 공개 API(에어코리아 미세먼지) 추가하기
  • 조건 분기를 넣어 폭염 · 한파 · 강풍 · 미세먼지 시 자동 경고 알림
  • Discord 대신 Slack 웹훅으로 채널 변경
  • 하루 1회가 아닌 아침 5시 + 저녁 22시 (1일 2회) 로 스케줄 변경

특히 출근 전과 다음 날 준비 시간이라는 두 시점을 다르게 다루고 싶어서, 같은 워크플로우인데도 시간대에 따라 "오늘의 날씨""내일의 날씨" 가 자동으로 바뀌도록 만들었어요. 옷장 앞에서 한참 고민하던 시간이 꽤 줄어들었습니다 ㅎㅎㅎ

오늘도 그 과정을 해당 공유해보겠습니다!


워크플로우 한눈에 보기

전체 흐름은 이렇습니다.

 

 

지난주 RSS 워크플로우보다 노드가 좀 더 많아졌어요. 핵심은 세 가지 API를 병렬로 호출하고, 도시 기준으로 다시 묶어서, 하나의 메시지로 조립하는 것입니다.


핵심 노드 살펴보기

 

1. Schedule Trigger — 하루 두 번 (아침 5시 / 저녁 22시)

Cron 표현식 0 5,22 * * *로 매일 두 번 실행되게 설정했어요. 아침엔 출근 준비용, 저녁엔 다음 날 준비용이에요. 시간대에 따라 메시지 내용이 자동으로 바뀌게 되어 있는데, 이 부분은 뒤에서 다시 다룰게요.

 

2. 측정 도시 — 도시 목록을 코드로 관리

Code 노드에 도시 목록을 배열로 정의했어요.

return [
  { json: { cityKey: 'Suwon-si', cityLabel: '수원', airStation: '광교동' } },
  { json: { cityKey: 'Seoul',    cityLabel: '서울', airStation: '송파구' } }
];
  • cityKey: OpenWeatherMap이 인식하는 영문 이름
  • cityLabel: 알림에 표시할 한글 이름
  • airStation: 에어코리아 측정소 이름 (미세먼지용)

이렇게 배열로 두면 도시를 추가하거나 빼고 싶을 때 이 노드 한 군데만 고치면 돼요.

처음엔 도시별로 노드를 따로 만들었었는데, 두 도시만 돼도 노드가 우후죽순으로 늘어나서 다시 갈아엎었습니다....

 

3. 세 갈래 API 병렬 호출

도시 목록이 다음 세 노드로 동시에 흘러갑니다.

  • 오늘 날씨 (OpenWeatherMap): 현재 기온, 체감, 날씨 상태
  • 5일 날씨 (OpenWeatherMap forecast): 3시간 단위 예보
  • 미세먼지 (에어코리아 공공 API): PM10 · PM2.5 등급

지난주에 배운 병렬 처리 패턴을 그대로 활용한 부분이에요. 세 API가 서로 의존하지 않으니 순차 호출할 이유가 없거든요.

 

4. 비랑눈 데이터 / 미세먼지 가공 — 원시 데이터 다듬기

API 응답을 그대로 쓰면 메시지 조립 단계가 너무 무거워져요. 그래서 중간에 Code 노드를 둬서 필요한 정보만 추려서 다음 단계로 넘깁니다.

비랑눈 데이터 노드에서 한 일:

  • 12시간 이내 비/눈 예보 필터링
  • 아침(6~12시) / 점심(12~18시) / 저녁(18~24시) 시간대별 최저·최고 기온 계산
  • 현재 시각이 22시 이후면 자동으로 "내일" 데이터로 전환 ← 이게 시간대 분기의 핵심이에요

미세먼지 가공 노드에서 한 일:

  • PM10/PM2.5 수치를 1~4 등급 → "좋음/보통/나쁨/매우 나쁨" 텍스트로 변환
  • 등급 3 이상이면 airQualityAlert: true 플래그 추가 (나중에 자동 경고에서 사용)

 

5. Merge & 데이터 통합 — 세 갈래를 도시 기준으로 다시 묶기

세 API의 결과를 Merge로 합치면, 같은 도시의 데이터인데도 세 개의 아이템으로 따로 들어와요. 그래서 Merge 뒤에 데이터 통합 Code 노드를 둬서, cityKey(예: "Seoul")를 기준으로 같은 도시 데이터를 하나의 객체로 모아줍니다.

// 핵심 아이디어
allItems.forEach(item => {
  const cityKey = item.json.name || item.json.cityKey;
  if (!cityGroups[cityKey]) cityGroups[cityKey] = {};
  Object.assign(cityGroups[cityKey], item.json);  // 도시별로 누적 병합
});

이렇게 해두면 다음 노드에서는 "수원 객체 하나, 서울 객체 하나"로 깔끔하게 다룰 수 있어요.

 

6. 메세지 조립 — 자동 경고 시스템

가장 공들인 노드예요. 단순히 기온만 알려주는 게 아니라, 조건에 따라 자동으로 경고를 붙여주게 만들었습니다.

// 경고 조건 일부
if (feels >= 33) alerts.push('🔥 폭염 주의, 야외활동 자제');
if (feels <= -10) alerts.push('🥶 한파, 두꺼운 외투 + 목도리');
if (diff >= 10) alerts.push(`🌡️ 일교차 ${diff}°, 겉옷 챙기기`);
if (windSpeed >= 10) alerts.push(`💨 강풍 주의`);
if (d.airQualityAlert) alerts.push(`😷 미세먼지 ${d.pm10GradeText}`);

심화 미션엔 "IF 노드로 분기"라는 표현이 있었는데, 저는 경고 조건이 여러 개라 IF 노드를 매번 끼우면 워크플로우가 복잡해질 것 같아서 Code 노드 안에서 조건문으로 처리했어요. 결과적으로 같은 효과를 내면서 워크플로우는 깔끔하게 유지됐습니다.

여기에 더해 시간/계절 분기도 들어가요:

  • 아침이면 "지금 ○°/체감 ○°", 저녁이면 그 줄을 빼고 내일 아침 기온 기준으로 옷차림 추천
  • 봄 🌸 · 여름 ☀️ · 가을 🍂 · 겨울 ❄️ 헤더 이모지 자동 전환

 

7. HTTP Request — Slack 웹훅으로 전송

이번엔 Slack 노드 대신 HTTP Request 노드로 웹훅 URL에 POST를 직접 쏘는 방식으로 했어요.
Slack 전용 노드를 쓰면 매번 OAuth 인증을 거쳐야 해서, 단순 알림용으로는 웹훅이 가볍다고 하더라구요!

{ "text": "{{ JSON.stringify($json.message) }}" }

JSON 문자열 이스케이프를 직접 해줘야 한다는 게 약간의 함정인데, JSON.stringify로 감싸주면 깔끔하게 처리됩니다.

 

실제 받은 알림 화면

이렇게 받아져요! 꽤 깔끔하죠?????



만들면서 느낀 점

  1. 데이터 가공 노드는 일찍 둘수록 좋아요. API 원시 응답을 그대로 끝까지 들고 가니까, 메시지 조립 단계의 코드가 누더기가 되더라고요. 중간에 가공 노드를 끼워서 "이 단계 이후엔 이런 모양"을 약속해두니까 뒷단이 훨씬 단순해졌어요.
  2. 분기 처리를 꼭 IF 노드로 할 필요는 없어요. 조건이 한두 개면 IF가 직관적이지만, 5~6개씩 되면 Code 노드 안에서 조건문으로 처리하는 게 워크플로우 가독성에 더 좋았던 것 같습니다!
  3. 한 워크플로우가 시간에 따라 다른 일을 하게 만드는 건 생각보다 유용했어요. 워크플로우를 두 개로 분리하지 않고, "지금 몇 시인지"로 메시지 내용을 바꾸는 식으로 처리하니까 유지보수가 훨씬 편했습니다.
  4. 여러 API를 합칠 땐 '식별자(key)'를 일찍 정의하세요. 이번 워크플로우에서 cityKey가 그 역할을 했어요. 세 갈래 API 응답을 다시 도시 기준으로 묶을 때, 처음부터 일관된 키를 들고 다닌 덕분에 매칭이 단순해졌습니다.

마치며

이번 미션은 1주차때보다 한 단계 더 깊이 들어간 느낌이 들었습니다!
저번보다 가공하는데 시간을 더 많이 썼던 것 같아요 ㅎㅎㅎ

자동화를 하고나서 매일 아침 5시나 전날 저녁에 슬랙으로 깔끔하게 정리된 날씨를 보고 우산 챙길지, 패딩 입을지, 마스크 쓸지 미리 준비할 수 있어서 좋더라구요!ㅎㅎ

처음엔 막막했는데 책 따라 하면서 한 단계씩 쌓아가니까 생각보다 할 만했어요! n8n 책 보면서 실습하기 정말 좋은 것 같아요!
이번 글도 읽어주셔서 감사합니다 :)