바쁜 출근길, 미세먼지 수치를 확인하려다 지각할 뻔한 적 없으신가요? 오늘은 n8n 날씨 자동화 설정을 통해 매일 아침 공공데이터 API 정보를 이메일로 받는 법을 알아보겠습니다. NAS 환경이나 로컬 PC 어디서든 간단하게 구축할 수 있습니다.
1. n8n 워크플로우 전체 구조
워크플로우는 크게 트리거 – 데이터 수집 – 병합 – 가공 – 전송의 5단계로 구성됩니다.

- Schedule Trigger: 평일 오전 7시 자동 실행
- HTTP Request: 기상청 및 에어코리아 API 데이터 호출
- Merge & Code: 서로 다른 API 데이터를 하나로 합치고 가독성 좋게 가공
- Gmail: 최종 리포트를 이메일로 발송
2. 공공데이터포털 API 신청 및 준비물
본격적인 설정에 앞서 아래 3가지가 준비되어야 합니다.
| 준비물 | 상세 내용 |
| n8n 설치 | Docker, NAS, 또는 n8n Desktop 버전 |
| API 키 발급 | 공공데이터포털 회원가입 후 ‘한국환경공단에어코리아대기오염정보’, ‘기상청_단기예보 조회서비스’ 신청 |
| 이메일 계정 | Gmail SMTP 사용을 위한 앱 비밀번호 발급 |
3. 단계별 설정 가이드
Step 1: 실행 스케줄 설정 (Schedule Trigger)
매일 아침 정보를 받아야 하므로 Schedule 노드를 사용합니다.

Step 2: 공공데이터 호출 (HTTP Request)
두 개의 HTTP Request 노드를 생성하여 각각 미세먼지와 기상 정보를 가져옵니다.
- 기상청 API: 기온, 습도, 강수확률 데이터를
GET방식으로 요청합니다. - 에어코리아 API: 현재 위치의 실시간 미세먼지 등급 정보를 가져옵니다.
Step 3: 데이터 가공 및 병합 (Merge & Code)
- Merge 노드: 두 API에서 온 결과값을 하나로 묶어줍니다. (Mode: Combine)

- 데이터 가공(Code) 노드: 수많은 데이터 중 우리에게 필요한 정보(예: ‘나쁨’, ’25도’)만 추출하여 이메일에 들어갈 문구로 정리합니다.

// 1. 모든 입력 데이터 수집
const allItems = $input.all();
let airData = {};
let weatherItems = [];
// 2. 데이터 분류
for (const item of allItems) {
const json = item.json;
const body = json.response?.body?.items;
if (!body) continue;
// 날씨 데이터 추출 (items.item 구조)
if (body.item && Array.isArray(body.item) && body.item[0]?.category) {
weatherItems = body.item;
}
// 대기질 데이터 추출 (배열 또는 items.item 구조)
const airBase = Array.isArray(body) ? body : (body.item || []);
if (airBase[0]?.pm10Value) {
airData = airBase[0];
}
}
// 3. 시간 설정 (KST 기준)
const now = new Date();
const kstNow = new Date(now.getTime() + (9 * 60 * 60 * 1000));
const today = kstNow.toISOString().split('T')[0].replace(/-/g, ''); // 20260203
const currentHour = kstNow.getUTCHours().toString().padStart(2, '0') + "00"; // 현재 시각 (예: 1800)
// 4. 날씨 변수 추출 (현재 시간 데이터 찾기)
let temp = 'N/A', humidity = 'N/A', rainfall = '0', rainProb = '0', sky = '1', pty = '0';
// 현재 시간과 일치하는 데이터들만 먼저 필터링
const currentForecast = weatherItems.filter(i => i.fcstDate === today && i.fcstTime === currentHour);
// 만약 현재 시간 데이터가 없으면 오늘 전체 데이터 사용
const targetData = currentForecast.length > 0 ? currentForecast : weatherItems.filter(i => i.fcstDate === today);
targetData.forEach(i => {
// 각 카테고리별로 값이 비어있을 때만 채워넣음 (현재 시간 우선)
if (i.category === 'TMP') temp = i.fcstValue;
if (i.category === 'REH') humidity = i.fcstValue;
if (i.category === 'PCP') rainfall = i.fcstValue;
if (i.category === 'POP') rainProb = i.fcstValue;
if (i.category === 'SKY') sky = i.fcstValue;
if (i.category === 'PTY') pty = i.fcstValue;
});
// 5. 텍스트 변환
const skyMap = { '1': '☀️ 맑음', '3': '⛅ 구름많음', '4': '☁️ 흐림' };
const ptyMap = { '0': '', '1': '🌧️ 비', '2': '🌨️ 비/눈', '3': '❄️ 눈', '4': '🌦️ 소나기' };
const getGrade = (g) => ({'1':'😊 좋음','2':'🙂 보통','3':'😷 나쁨','4':'😨 매우나쁨'}[g] || '정보없음');
const conditionText = pty !== '0' ? ptyMap[pty] : skyMap[sky];
// 6. 조언 생성
let advice = "✨ 오늘 하루도 화이팅하세요!";
if (['3', '4'].includes(airData.pm10Grade)) advice = "😷 미세먼지가 나빠요. 마스크를 꼭 쓰세요!";
if (pty !== '0' || parseInt(rainProb) >= 60) advice = "☔ 비 소식이 있어요. 우산을 챙기세요!";
// 7. HTML 템플릿용 최종 반환 (무조건 1개 아이템)
return [{
json: {
currentDate: kstNow.toLocaleDateString('ko-KR', { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' }),
timestamp: kstNow.toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit', hour12: false }),
advice: advice,
airQuality: {
pm10: airData.pm10Value || 'N/A',
pm10Grade: getGrade(airData.pm10Grade),
pm25: airData.pm25Value || 'N/A',
pm25Grade: getGrade(airData.pm25Grade),
station: airData.stationName || '수지'
},
weather: {
temp: temp,
condition: conditionText,
humidity: humidity,
rainProbability: rainProb,
rainfall: (rainfall === '강수없음' || rainfall === '0') ? '0' : rainfall,
sky: skyMap[sky] || '맑음'
}
}
}];
Step 4: 이메일 발송 (Gmail)
최종적으로 가공된 텍스트를 Gmail 노드를 통해 전송합니다. HTML 형식을 지원하므로 표나 이모지를 섞어 예쁘게 꾸밀 수 있습니다.
4. 메일로 온 결과물
이제 매일 아침 메일로 자동으로 맞춤형 날씨 리포트를 받을 수 있습니다
