잘못된 편집으로 작동하던 n8n 워크플로우를 잃어버리다 — 이제 배포마다 Git 버전 관리
요약
본 글은 n8n 워크플로우를 프로덕션 환경에서 운영할 때 발생하는 버전 관리의 어려움을 다루고 있습니다. 작성자는 n8n에 Git 기능이 없다는 문제점을 인식하고, 모든 워크플로우를 매일 밤 자동으로 백업하는 '메타 워크플로우'를 직접 구축했습니다. 이 익스포터는 휘발성 필드를 제거하고 변경 사항이 있을 때만 Git 커밋을 수행하여 안정적인 버전 관리를 가능하게 합니다.
핵심 포인트
- n8n은 기본적으로 Git 기능을 제공하지 않아 외부 구현이 필요함.
- 메타 워크플로우를 통해 모든 워크플로우를 주기적으로 백업하는 시스템 구축.
- 휘발성 필드(timestamp 등) 제거는 의미 있는 Git 히스토리를 만드는 핵심 단계임.
- 변경 사항이 있을 때만 커밋하여 레포지토리의 노이즈를 최소화함.
잘못된 편집으로 작동하던 n8n 워크플로우를 잃어버리다 — 이제 모든 배포에 Git 버전 관리 적용하기
이 글은 프로덕션 환경에서 n8n을 이용해 LLM(대규모 언어 모델) 워크플로우를 실행하는 과정에 대한 '공개적 구축 기록' 시리즈의 일부입니다. 이번 주제는 아무도 자랑하지 않는 인프라, 즉 버전 관리에 관한 것입니다. n8n에는 Git 기능이 없습니다. 그래서 제가 직접 추가했습니다. 매일 밤마다 모든 워크플로우를 스냅샷 찍어 Git 저장소에 백업하는 익스포터(exporter)를 만든 것입니다. 덕분에 잘못된 편집을 하더라도 40분 동안 추측 게임을 할 필요 없이 git checkout만 하면 됩니다.
금요일 밤의 나에게 비용이 된 수정 작업
몇 달 전, 저는 고객의 받은 편지함 분류 워크플로우에 "작은" 개선 작업을 했습니다. 분류 프롬프트(classify prompt)를 더 "명확하게" 다시 작성한 것입니다. 하지만 명확하다는 것은 결국 길다는 의미였고, 추가된 지침들은 모델이 망설이도록 만들었습니다. 그 결과 모든 이메일이 "불확실함(uncertain)"으로 반환되었고, 라우터(router)는 모든 것을 검토 대기열(review queue)에 쌓아버렸습니다. 결국 고객은 분류되지 않은 200개의 이메일을 보고 깜짝 놀랐습니다.
그 워크플로우는 목요일까지 완벽했습니다. 금요일 아침이 되자 저는 목요일의 프롬프트가 정확히 무엇이었는지 말할 수 없었습니다. n8n은 워크플로우별 버전 기록을 보관하고 있지만, 새벽 1시에 "버전 47"과 "버전 46"을 스크롤하며 머릿속으로 프롬프트를 비교(diff)하는 것은 복구 전략이 아닙니다. 그것은 기도에 가깝습니다. 제가 무엇을 변경했는지 재구성하는 데 40분이 걸렸고, 이는 제가 2주 전에 이전 프롬프트를 슬랙 메시지로 저 자신에게 붙여넣어 두었기 때문에 가능했던 순전히 운이었습니다.
그것이 워크플로우가 오직 n8n 안에만 존재했던 마지막 순간이었습니다.
익스포터: 노드 5개, 크론(cron) 1개로 모든 워크플로우를 Git에 저장
저는 그 주말 동안 메타 워크플로우(meta-workflow)를 만들었습니다. 이 워크플로우의 유일한 임무는 다른 모든 워크플로우들을 백업하는 것입니다. 이것은 매일 밤 11시에 실행되며, 정확히 다음 작업을 수행합니다:
- 크론 트리거(Cron trigger) — 매일 23:00. 지루하게 의도적으로 설정함.
- 모든 워크플로우 가져오기(Get all workflows) — API 키를 사용하여 나 자신의 n8n 인스턴스 API(
GET /api/v1/workflows)에 접근하는 HTTP 노드입니다. 이 익스포터는 자신도 백업합니다. 스스로 제외하는 백업 스크립트를 충분히 많이 봤기 때문입니다. - 노이즈 제거(Strip the noise) — 저장하기 전에 각 워크플로우 JSON에서 휘발성 필드(
updatedAt,createdAt,versionId, 그리고 실행별webhookId의 변화분)를 제거하는 Code 노드입니다. 이 단계가 없으면, 매일 밤 내보내기(nightly export)마다 단순히 타임스탬프인 "변경 사항"이 표시되어 git 히스토리가 읽을 수 없게 됩니다. 이것은 모두가 건너뛰고 나중에 왜 자신의 레포지토리(repo)에 400개의 의미 없는 커밋이 있는지 궁금해하는 단계입니다. - 파일 쓰기(Write files) — 각 워크플로우는 레포지토리에
workflows/<slug>.json으로 저장되며, 여기에 워크플로우 이름, 노드 개수, 활성 상태, 마지막 편집자가 포함된manifest.json이 추가됩니다. 워크플로우 하나당 파일 하나이므로 diff(차이점)를 읽기 쉽습니다. - 변경 시에만 커밋(Commit only on change) — shell/Execute 노드가 먼저
git diff --quiet을 실행합니다. 아무것도 변경되지 않았다면 커밋하지 않습니다. 무언가 변경되었다면,nightly: inbox-triage, prompt changed in classify node와 같은 메시지로 커밋하고 푸시(push)합니다. 실제 변경 사항이 있을 때만 Telegram 알림을 받으며, 휴대폰으로 "2 files changed, 14 insertions"를 볼 수 있도록--stat요약 정보가 제공됩니다.
전체 레포지토리는 비공개입니다. 워크플로우 JSON에는 프롬프트 IP와 클라이언트별 로직이 포함되어 있습니다. 하지만 이것은 실제 git 시스템입니다: 브랜치(branches), "안정적으로 알려진" 상태를 위한 태그(tags), 그리고 배포 이력으로 사용되는 git log --oneline을 갖추고 있습니다.
복원(Restore)이 중요한 부분입니다 (그리고 제가 테스트하는 부분입니다).
복원하지 않는 백업은 장식품에 불과합니다. 제 것은 의도적으로 매월 복원됩니다. 테스트 절차는 다음과 같습니다: 워크플로우를 하나 선택하고, 지난주 버전으로 체크아웃(check out)한 다음, staging n8n 인스턴스로 가져와서(import), 테스트 받은 편지함에 대해 실행해보고, 지난주처럼 작동하는지 확인합니다. 이 절차를 통해 올해 두 가지 실제 문제가 발견되었습니다:
- Webhook URL 손실 문제. 워크플로우 JSON을 가져올 때 n8n은 웹훅 경로를 재생성합니다. 그래서 제 익스포터는 이제 프로덕션 웹훅 URL을 매니페스트에 기록하고, 복원 절차에는 수동 재등록 단계가 포함됩니다. 이 방법은 문서가 아니라 실전 경험(drill)을 통해 알게 되었습니다.
- 하위 워크플로우 참조 오류. ID를 사용하여 다른 워크플로우를 호출하는 가져온 워크플로우는 인스턴스가 새로 생성되면 ID가 다르기 때문에 잘못된 것을 가리키게 됩니다. 그래서 제 규칙은 다음과 같습니다: 하위 워크플로우는 하드코딩된 ID로 참조하지 않고, 항상
Execute Workflow노드의 조회 기능을 통해_name_으로 참조합니다. 익스포터는 매번 실행 시 이를 검증하며, 원시적인(raw) 하위 워크플로우 ID를 포함하는 워크플로우는 야간 점검에서 실패하고 저에게 알림을 보냅니다.
솔직히 말하자면: 이 과정은 한 달에 20분 정도 걸립니다. 지난 금요일 밤 사건은 40분과 고객의 신뢰가 걸렸습니다. 수학적으로 큰 차이가 납니다.
저장소를 깨끗하게 유지하는 세 가지 규칙
규칙 1: 저장소(repo)는 편집자가 아니라 심판이다. 저는 여전히 n8n UI에서 워크플로우를 편집합니다. Git은 개발 워크플로우가 아니라 스냅샷 계층일 뿐입니다. 아무도 JSON 파일을 수동으로 편집하지 않으며, 익스포터가 덮어씁니다. 이는 두 개의 진실의 출처(two sources of truth)라는 고전적인 함정을 피하게 해줍니다. 저장소의 파일과 실제 작동하는 워크플로우가 다르면, 실제 작동하는 워크플로우가 승리하며 다음 야간 실행에서 커밋을 통해 이를 조정합니다. 저장소는 배포된 것만을 기록할 뿐입니다.
규칙 2: 자격 증명(credentials)은 절대 저장소에 들어가지 않는다. n8n API 익스포트는 기본적으로 자격 증명을 포함하지 않으며, 저는 의도적으로 그렇게 유지합니다. 매니페스트는 각 워크플로우가 어떤 자격 증명을 사용하는지(이름으로) 기록하지만, 비밀값 자체는 절대 기록하지 않습니다. 새 인스턴스를 복원한다는 것은 수동으로 자격 증명을 다시 입력해야 한다는 의미입니다. 귀찮은가요? 약간 그렇습니다. 하지만 대안보다 훨씬 안전합니다.
규칙 3: n8n 업그레이드는 전용 커밋을 받는다. n8n이 새 버전을 출시할 때, 워크플로우 JSON 스키마(schema)가 때때로 변경되며, 다음 야간 내보내기(nightly export)에서는 모든 파일에 차이점(diff)이 나타난다. 나는 이를 schema-bump: n8n 1.x → 1.y로 커밋하여 노이즈에도 이름과 날짜를 부여한다. 6개월 후, 같은 밤에 왜 30개의 파일이 변경되었는지 궁금해할 때, 과거의 자신에게 감사하게 될 것이다.
내가 여전히 주시하는 실패 모드
익스포터가 해결할 수 없는 한 가지: 두 명의 사람이 동일한 워크플로우를 편집하는 경우. 워크플로우 JSON에서의 Git 병합 충돌(Git merge conflicts)은 정말 끔찍하다 — '충돌'이 두 사람이 같은 노드를 이동시킨 것에 불과한, 수천 줄짜리 JSON 블롭이다. 현재 나의 해결책은 기술적인 것이 아니라 구조적인 것이다: 내가 유일한 편집자다. 매니페스트는 워크플로우당 단일 소유자를 기록하며, 클라이언트 인계에는 하나의 규칙이 포함된다 — 무엇을 변경할지 말해주면, 내가 변경하고, git이 이를 기록한다. 이는 내 규모에서는 작동한다. 5명의 팀은 견딜 수 없을 것이며, 솔직히 말하자면: 두 번째 자동화 엔지니어를 고용하는 날, 이것은 실제 문제가 되고, 해결책은 더 나은 병합(merge)이 아니라 워크플로우별 잠금(per-workflow locking)일 가능성이 높다.
n8n 빌더를 위한 시사점
프로덕션에서 3개 이상의 워크플로우를 실행한다면, 필요하기 전에 익스포터(exporter)를 구축하라 — 즉, 이번 주말에 구축하라는 의미이다. 장치는 작다: 하나의 API 호출(API call), 노이즈 제거 함수(noise-stripping function), git diff --quiet, 그리고 cron이다. 규율은 더 작다: 절대로 노이즈를 커밋하지 말고, 비밀을 저장하지 말고, 스케줄에 따라 복원하라. n8n은 버전 관리(version control)를 제공하지 않는다. 그러나 API를 제공하며, API와 git의 결합은 추가 단계를 가진 버전 관리이며 — 이 추가 단계는 모든 것이 망가지는 밤에만 눈에 띄게 된다.
저는 AI Automation Lab을 구축하고 있습니다. 여기에는 프로덕션 레디한 n8n 워크플로우 템플릿과 문의 페이지를 통해 고정 가격으로 맞춤 제작 서비스(79달러부터)가 제공됩니다. 이 시리즈의 핵심 파이프라인은 AI Inbox Triage & Reply Drafter(29달러)로 판매되며, 무료인 AI Hook Generator는 제가 어떻게 구축하는지 위험 부담 없이 확인할 수 있는 방법입니다. 저의 오픈소스 패턴은 github.com/zhp910318/n8n-ai-automation-lab에서 확인하실 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기