67세 교수가 하루 종일 버그를 쫓은 날 — n8n 팟캐스트 자동화 디버깅기
🎙️ 오늘은 코드를 한 줄도 짜지 않았다, 그런데 가장 긴 하루였다
오늘은 정확히 새 기능을 하나도 추가하지 않았다. 그런데 아침부터 밤까지, 거의 하루 종일 화면 앞에 앉아 있었다. 35년 강단에 서 있다가 은퇴하고 n8n으로 자동화를 만지기 시작한 지도 꽤 됐는데, 오늘 같은 날은 흔치 않았다. 한 가지 버그를 잡으면 똑같은 모양의 버그가 다른 데서 또 튀어나왔다. 마치 두더지 잡기 게임 같았다.
기록으로 남겨두지 않으면 분명 비슷한 날을 또 맞이할 것 같아서, 오늘 무슨 일이 있었는지 정리해본다.
📌 시작은 단순한 의심에서
damesek.com 팟캐스트 자동화 워크플로우를 들여다보다가 이상한 점을 발견했다. podcast_history라는 구글 시트에 글이 2,048개나 쌓여 있었던 것이다. 분명 매번 새 글 하나씩만 등록되어야 하는데.
원인을 추적해보니, “전체 이력을 읽어오는 노드”의 출력 — 그러니까 시트 전체 내용 — 이 분기 판단 노드(If)에 통째로 들어가고 있었다. If 노드는 들어온 항목 하나하나를 평가하는데, 입력 자체가 이미 “역사 전체”였으니 항목 하나하나가 늘 자기 자신과 비교되어 거의 다 “신규”로 잘못 판정되고, 그게 매번 다시 통째로 쌓이는 구조였다. 실행할 때마다 거의 2배씩 불어나는 셈이었다.
이걸 고치고 나니 ElevenLabs 기반 워크플로우는 멀쩡해졌다. “역시 원인을 잡았구나” 하고 안심했다.
📌 안심한 지 30분도 안 돼서, 같은 버그가 또
문제는 거기서 끝나지 않았다. damesek 팟캐스트에는 ElevenLabs 외에 Gemini TTS를 쓰는 백업 워크플로우도 있는데, 거기서도 똑같은 구조의 버그가 그대로 들어 있었다. 같은 패턴을 두 번 베껴서 만들었으니, 버그도 그대로 두 번 베껴진 것이다.
이쯔음 깨달은 게 있다. 자동화는 한 번 잘 만들어두면 끝이 아니라, “같은 실수를 복제하지 않았는지” 늘 점검해야 하는 일이라는 것. 워크플로우를 복사-붙여넣기로 늘려가는 재미에 취해 있었는데, 그 편리함이 곧 위험이기도 했다.
📌 6시간을 기다릴 이유가 없다는 걸 깨달은 순간
버그를 다 잡고 나서 생긴 또 다른 궁금증. “새 글을 올렸는데, 팟캐스트는 왜 바로 안 만들어지지?”
답은 단순했다. 팟캐스트 워크플로우의 RSS 감지 주기가 6시간으로 설정되어 있었던 것이다. 글을 올려도 최대 6시간을 기다려야 팟캐스트 변환이 시작되는 구조였다.
그래서 오늘 새로 배운 게 하나 생겼다 — Webhook. 블로그에 글을 올리는 워크플로우(A)가 끝나는 순간, 팟캐스트를 만드는 워크플로우(B)를 직접 깨워주는 방식이다. 우체국에 편지를 맡기고 6시간 뒤에 배달부가 우편함을 확인하러 오길 기다리는 게 아니라, 편지를 쓴 즉시 초인종을 눌러 직접 건네주는 셈이다.
말로는 간단한데, 실제로 연결하려니 또 다른 산이 기다리고 있었다.
📌 “노드 이름을 직접 부르면 안 된다”는 교훈
Webhook을 연결하고 나니 새로운 에러가 떴다.
Error: Node 'RSS Feed Trigger' hasn't been executed
알고 보니 워크플로우 안의 여러 코드 노드들이 $('RSS Feed Trigger')라는 식으로 트리거 노드의 이름을 직접 호명하고 있었다. 그런데 이번엔 Webhook으로 시작했으니, 그 실행 안에는 “RSS Feed Trigger”라는 노드 자체가 아예 존재하지 않는다. 존재하지 않는 사람 이름을 부르며 “거기 응답해주세요”라고 한 셈이니, 당연히 대답이 없을 수밖에.
이 문제를 고치는 방법은 의외로 단순했다. 노드 이름을 직접 부르지 말고, “바로 앞에서 넘겨준 데이터”($input.first().json)를 그냥 받아 쓰면 된다. 누가 보냈는지 따지지 않고, 지금 내 손에 들어온 것만 보고 일하는 방식이다.
워크플로우 전체를 하나씩 열어보며 이런 식으로 트리거 이름을 직접 부르는 곳이 몇 군데나 더 있는지 점검했다. 다행히 대부분의 노드는 이미 안전하게 짜여 있었고, 딱 두 곳만 고치면 됐다. 그중 한 곳은 오히려 이미 try-catch로 여러 후보 노드를 돌려가며 안전하게 찾아내는 코드가 짜여 있어서, “누가 이렇게 꼼꼼하게 짜놨지” 하고 스스로 감탄하기도 했다(아마 예전의 내가 짠 것일 텐데도 기억이 안 났다).
📌 그렇게, 저녁 7시 14분에
오후 7시 14분, 마침내 실행 기록에 초록색 “Succeeded”가 처음부터 끝까지 한 줄로 떴다. Webhook이 울리고, 대본이 만들어지고, 음성이 합성되고, feed.xml이 갱신되고, Google에 갱신 알림(WebSub)까지 나가는 전체 흐름이 단 한 번의 끊김 없이 돌았다.
55.858초. 별것 아닌 숫자처럼 보이지만, 오늘 하루의 결과물이 그 숫자 안에 다 들어 있다.
🔑 오늘 배운 것 세 가지
- 자동화는 “한 번 만들면 끝”이 아니다. 비슷한 워크플로우를 복제할 때, 버그도 함께 복제된다는 걸 잊지 말아야 한다.
- 기다리지 말고 직접 알리는 구조가 낫다. 폴링(주기적으로 확인하기)보다 Webhook(즉시 알리기)이 훨씬 자연스럽고 빠르다.
- 이름을 직접 부르는 코드는 위험할 수 있다. 누가 보냈는지 따지기보다, 지금 들어온 데이터를 그대로 받아 쓰는 게 더 튼튼한 구조다.
35년 강의실에서는 학생들에게 “왜?”를 끊임없이 물으라고 가르쳤는데, 오늘은 내가 컴퓨터 앞에서 하루 종일 “왜 안 되지?”를 되물은 날이었다. 신기하게도, 그 질문을 끝까지 따라간 끝에는 늘 답이 있었다. 67세에 다시 배우는 게 이런 맛이구나 싶다.
🔗 관련 링크
- 블로그 홈: damesek.com
- 팟캐스트 RSS: feed.xml