가져오기 동작 방식
n8n v2.42요약
n8n 패키지는 미리보기(Preview) 상태입니다. 이 페이지에서는 가져오기를 호출한 뒤 n8n이 n8n 패키지로 수행하는 작업을 설명합니다. 이 섹션의 상세 내용은 n8n 공식 문서를 참조하세요. 가져오기는 두 단계로 진행됩니다.
미리보기 상태
n8n 패키지는 미리보기(Preview) 상태입니다. 가져오기 동작은 이후 릴리즈에서 변경될 수 있습니다.
이 페이지에서는 가져오기를 호출한 뒤 n8n이 n8n 패키지로 수행하는 작업을 설명합니다. 가져오기를 진행할 수 있는지 판단하는 방법과 각 엔티티 유형을 확인하는 방법을 다룹니다.
이 섹션의 상세 내용은 n8n 공식 문서를 참조하세요.
모두 검사한 뒤에 쓰기#
가져오기는 두 단계로 진행됩니다. 먼저 n8n이 계획을 세웁니다. 패키지를 읽고, 모든 엔티티에 대해 수행할 작업을 파악하며, 가져오기를 진행할 수 없는 이유를 모두 수집합니다. 그다음 수집한 이유와 라이선스, 권한, 할당량 요구 사항을 함께 확인합니다. 진행을 막는 항목이 하나도 없을 때만 쓰기를 시작합니다.
모든 문제를 한 번에 확인할 수 있습니다. 거부된 가져오기는 첫 번째 문제에서 멈추지 않고 모든 이유를 issues 배열에 담아 함께 반환합니다. 따라서 새 오류가 나올 때마다 가져오기를 다시 실행하지 않고, 한 번에 파이프라인을 고칠 수 있습니다.
거부된 가져오기는 아무것도 쓰지 않습니다. 가져오기가 차단되면 워크플로, 폴더, 자격 증명, 데이터 테이블, 변수, 태그가 생성되거나 변경되지 않습니다.
롤백은 없습니다. n8n은 가져오기 전체를 데이터베이스 트랜잭션으로 감싸지 않으므로, 거부된 가져오기는 아무것도 쓰지 않는다는 보장은 n8n이 예측할 수 있는 문제에만 해당하며 발생 가능한 모든 실패에 적용되지는 않습니다. 가져오기를 쓰는 도중 데이터베이스 연결 끊김 같은 예기치 않은 문제가 발생하면, 이미 쓴 내용은 인스턴스에 그대로 남고 이후에 정리되지 않습니다. 먼저 검사하기 때문에 이런 일이 드물 뿐, 불가능한 것은 아닙니다.
가져오기는 워크플로, 폴더, 프로젝트, 데이터 테이블, 태그를 삭제하지 않습니다. --data-table-schema-conflict-policy=overwrite를 사용하면 데이터 테이블에서 칼럼을 제거할 수 있습니다. 데이터 테이블을 참조하세요.
쓰기 순서#
프로젝트 안에서 n8n은 정해진 순서로 씁니다.
tags → folders → credentials → data tables → workflows → variables → publish
태그를 워크플로에 붙이는 일이 워크플로를 쓰는 과정의 일부이므로 태그를 먼저 씁니다. 변수를 덮어쓰는 것이 기존 데이터를 바꾸는 유일한 단계이고 그 이전 단계에서는 변수를 읽지 않으므로 변수는 마지막에 씁니다. $vars는 가져오기 시점이 아니라 런타임에 이름으로 확인됩니다.
게시는 패키지의 모든 프로젝트를 쓴 뒤 마지막에 수행하는 별도 단계입니다. 워크플로가 호출하는 대상이 모두 존재해야 그 워크플로를 게시할 수 있기 때문입니다.
워크플로 콘텐츠는 매니페스트에 나열된 순서대로 씁니다. 서브 워크플로 그래프에 따라 리프(leaf)부터 순서가 정해지는 것은 게시 단계입니다. 아직 게시되지 않은 서브 워크플로를 가진 워크플로를 게시하면 실패하기 때문입니다. 의존성 순환에 속한 워크플로는 가장 마지막에 게시됩니다.
프로젝트 패키지의 경우 n8n은 모든 프로젝트의 계획을 세우고, 패키지 전체를 검사하고, 프로젝트 셸을 생성한 다음, 각 프로젝트의 콘텐츠를 차례로 쓰고, 마지막으로 전체를 한 번에 게시합니다.
참조 다시 쓰기#
가져온 워크플로의 참조는 소스가 아닌 대상 인스턴스의 엔티티를 가리켜야 합니다. n8n은 진행하면서 소스 ID에서 대상 ID로의 맵을 만들고, 이 맵을 통해 다음 네 가지를 다시 씁니다.
- 노드의 자격 증명 ID.
- Execute Workflow, Call n8n Workflow Tool, Workflow Retriever 노드의 서브 워크플로 ID. 단, 노드가 표현식이 아니라 목록에서 워크플로를 선택하는 경우에만 해당합니다.
- 워크플로 설정의 오류 워크플로.
- 워크플로 설정의 호출자 허용 목록(allowlist). 요소별로 처리하며, 매핑할 수 없는 ID는 그대로 둡니다.
다시 쓰지 않는 항목이 두 가지 있습니다. 표현식으로 설정한 참조는 n8n이 평가 결과를 알 수 없으므로 그대로 둡니다. 또 서브 워크플로 노드에 표시되는 캐시된 표시 이름은 갱신되지 않으므로, 대상이 바뀐 서브 워크플로는 노드를 다시 열기 전까지 편집기에 이전 이름이 표시될 수 있습니다.
자격 증명#
패키지에는 자격 증명 데이터가 포함되지 않으므로 모든 자격 증명 참조를 대상 인스턴스에서 확인해야 합니다. n8n은 각 참조를 다음 순서로 확인합니다.
- 해당 자격 증명에 대해 명시적인 바인딩을 지정한 경우 그 바인딩.
- 그렇지 않으면
--credential-matching-mode규칙. - 그렇지 않으면
--credential-missing-mode가 빈 플레이스홀더를 생성할지, 가져오기를 거부할지 결정합니다.
어떤 경로를 거치든 n8n은 유형을 검사합니다. 자격 증명의 유형이 잘못되면 가져오기가 거부되며, 노드에 필요한 유형과 자격 증명의 실제 유형을 모두 알려 줍니다. 이는 명시적 바인딩에도 적용됩니다.
후보가 되는 자격 증명#
n8n은 사용자가 읽을 수 있고 대상 프로젝트가 사용할 수 있는 자격 증명과 글로벌 자격 증명만 후보로 고려합니다. 사용자가 읽을 수 없는 자격 증명은 id-only를 포함한 어떤 모드에서도 후보가 되지 않습니다. ID가 일치하는 자격 증명이 매칭되지 않을 때는 대체로 이것이 원인입니다.
일치 항목을 고르는 방법#
id-only는 ID를 찾거나 찾지 못하거나 둘 중 하나입니다. name-and-type과 type-only는 후보가 여러 개 나올 수 있으므로 n8n은 엄격한 단계 순서로 고릅니다.
- 대상 프로젝트가 소유한 자격 증명.
- 대상 프로젝트에 공유된 자격 증명.
- 글로벌 자격 증명.
이 단계는 점수 체계가 아니라 엄격한 순서입니다. 대상 프로젝트가 소유한 자격 증명이 하나라도 있으면 n8n은 공유 자격 증명이나 글로벌 자격 증명을 아예 살펴보지 않습니다. 선택된 단계 안에서는 가장 최근에 업데이트된 자격 증명이 선택되며, 두 자격 증명이 같은 시각에 업데이트되었다면 ID가 가장 낮은 것이 선택됩니다.
공유 자격 증명도 대상에 포함됩니다. 이를 제외하면 일반적인 승격(promotion) 사례가 깨지며, 어느 쪽이든 가져오는 사용자에게는 자격 증명에 대한 읽기 권한이 필요합니다.
플레이스홀더 자격 증명#
기본값인 --credential-missing-mode=create-stub에서는 n8n이 확인할 수 없는 참조가 대상 프로젝트의 빈 자격 증명이 되며, 이름은 패키지에 있는 자격 증명의 이름을 따릅니다. 워크플로는 가져와지고, n8n은 해당 자격 증명을 credentials.stubbed에 보고하며 새 바인딩을 반환하므로 다음에 재사용할 수 있습니다.
플레이스홀더 자격 증명을 사용하는 워크플로는 게시 정책과 관계없이 게시되지 않습니다. 자격 증명을 채운 뒤에 워크플로를 게시하세요.
일부 자격 증명 문제는 create-stub에서도 가져오기를 거부합니다. 플레이스홀더로는 해결되지 않기 때문입니다. 인스턴스에 설치되지 않은 자격 증명 유형, 잘못된 유형의 자격 증명을 가리키는 바인딩, 패키지에 선언되지 않은 자격 증명에 대한 바인딩이 여기에 해당합니다.
변수#
런타임에 $vars.<name>이 이름으로 확인되므로 변수는 ID가 아니라 항상 이름으로 매칭됩니다. n8n은 실행 중인 워크플로와 똑같이 대상 프로젝트를 먼저 살펴본 다음 글로벌 범위를 살펴봅니다. 이식 가능한 ID가 없으므로 패키지의 요구 사항에는 이름만 기록됩니다.
내보내기에서 같은 이름이 프로젝트와 글로벌에 모두 있으면 프로젝트의 값이 우선합니다. 하나의 이름이 같은 패키지 안에서 서로 다른 두 변수로 확인되는 경우 내보내기가 거부됩니다.
가져오기에서 확인되지 않는 변수는 --variable-missing-mode가, 확인되는 변수는 --variable-conflict-policy가 처리합니다. 변경할 내용이 없으면, 즉 패키지에 해당 변수의 값이 없거나 값이 이미 일치하면 두 정책 모두 확인된 변수를 건드리지 않습니다.
변수를 쓰려면 변수를 지원하는 라이선스가 필요합니다. 변수를 생성하려면 생성(create) 스코프와 인스턴스의 변수 한도 내 여유도 필요합니다. 변수를 덮어쓰려면 업데이트(update) 스코프가 필요하지만, 해당 변수는 이미 한도에 포함되어 있으므로 여유 공간은 소모하지 않습니다. 한도는 글로벌 변수와 프로젝트 범위 변수를 합쳐 인스턴스의 모든 변수를 셉니다. 새 변수 때문에 한도를 초과하는 가져오기는 n8n이 아무것도 쓰기 전에 거부합니다.
변수를 생성하지도 덮어쓰지도 않는 가져오기에는 이 요구 사항이 필요하지 않습니다. 기본값인 --variable-conflict-policy=keep-existing에서는 모든 변수 이름이 확인되는 가져오기가 모두 여기에 해당합니다.
--variable-conflict-policy=overwrite에서는 여러 프로젝트가 모두 같은 변수로 확인되는데 그 프로젝트들이 서로 다른 값을 가지고 있는 패키지가 거부됩니다. 하나의 변수는 두 개의 값을 가질 수 없으므로, n8n은 마지막에 쓴 값이 조용히 적용되도록 두지 않습니다.
데이터 테이블#
스키마만 전달됩니다. 행은 어느 방향으로도 이동하지 않으므로, 가져오기로 생성된 테이블은 비어 있는 상태로 시작합니다.
테이블은 이름이 아니라 대상 프로젝트 내의 ID로 매칭됩니다. 생성된 테이블은 소스 ID를 유지합니다.
--data-table-schema-conflict-policy는 매칭된 테이블의 스키마가 패키지와 다를 때의 동작을 결정합니다.
| 정책 | 동작 |
|---|---|
keep-existing (기본값) |
대상 테이블을 변경하지 않습니다. 패키지에 있는 데이터 테이블 칼럼이 대상에 없거나 유형이 다르면 가져오기를 거부합니다. 대상에만 있는 추가 칼럼은 허용됩니다 |
fail |
keep-existing과 같지만, 대상에 추가 칼럼이 있어도 가져오기를 거부합니다 |
overwrite |
대상 테이블을 패키지와 같도록 변경합니다. 칼럼을 추가, 이름 변경, 제거(파괴적), 유형 변경(파괴적), 순서 변경하고 테이블 이름도 변경합니다 |
overwrite-non-destructive |
overwrite와 같은 변경을 수행하지만, 파괴적인 변경이 있으면 가져오기를 중단하고 해당 변경을 보고합니다. 아무것도 쓰지 않습니다 |
keep-existing과 fail 모두 대상 테이블에 칼럼을 추가하거나 이름을 변경하지 않습니다. 소스에서 이름이 바뀐 칼럼을 포함해 칼럼이 없으면 가져오기가 거부됩니다. 이름 변경을 적용하려면 overwrite 또는 overwrite-non-destructive를 사용하세요. 칼럼 순서와 테이블 이름은 비교하지 않으며, 칼럼 이름은 대소문자를 구분해 비교합니다.
파괴적인 변경은 칼럼을 제거하거나 칼럼의 유형을 바꾸는 것입니다. 해당 칼럼의 값은 제거됩니다. 다른 칼럼의 데이터는 보존됩니다. 칼럼 이름 변경은 파괴적이지 않으며 값을 유지합니다. 두 overwrite 정책 모두에서 변경 사항은 해당 테이블을 사용하는 모든 워크플로에 적용됩니다.
n8n 2.44.0 이전에 내보낸 패키지에는 칼럼 ID가 없습니다. 이런 패키지에서는 두 overwrite 정책 모두 이름이 바뀐 칼럼을 제거 후 다시 추가한 것으로 처리하며, 이는 파괴적인 변경이므로 그렇게 표시됩니다.
테이블 ID가 다른 프로젝트를 포함해 인스턴스의 어디에든 이미 있거나, 대상 프로젝트에서 이름이 이미 사용 중이면 테이블 생성도 실패합니다. overwrite 정책에서 테이블 이름을 변경할 때 새 이름이 대상 프로젝트에서 이미 사용 중이면 마찬가지로 실패합니다.
태그#
n8n에서 태그는 글로벌이며 이름은 인스턴스 전체에서 고유합니다. n8n은 태그를 이름이 아니라 소스 ID로 매칭합니다. 이름 변경과 삭제 후 재생성은 안정적인 ID를 추적해야만 구분할 수 있기 때문입니다. 생성된 태그는 소스 ID를 이어받습니다.
충돌에는 두 가지 종류가 있습니다.
- 이름 변경 드리프트(Rename drift): ID가 대상의 태그와 일치하지만 이름이 다릅니다. 한쪽 인스턴스에서 누군가 이름을 바꾼 경우입니다.
- 이름 충돌(Name collision): ID는 대상에 없지만 다른 태그가 이미 그 이름을 사용합니다. 태그가 각각 독립적으로 생성되어 ID가 서로 무관한, 오래 운영된 인스턴스에서 흔한 경우입니다.
--tag-conflict-policy=rename은 두 경우를 모두 처리합니다. 드리프트된 태그는 패키지의 이름으로 변경하고, 이름 충돌은 기존 태그를 패키지의 ID로 옮겨 이름과 이미 해당 태그가 붙은 모든 항목을 유지하는 방식으로 해결합니다. 이 정책으로도 거부하는 유일한 경우는, 드리프트된 태그의 새 이름을 제3의 태그가 이미 사용 중인 경우입니다.
n8n이 워크플로를 업데이트할 때 패키지의 태그 목록은 대상 워크플로의 태그를 정확히 그 목록으로 대체하며, 빈 목록도 마찬가지입니다. 태그 목록이 아예 없는 워크플로는 대상의 태그를 그대로 둡니다. 제외된 태그는 쓰기 전에 걸러지므로, 패키지의 태그가 모두 제외된 태그 지정 워크플로를 업데이트하면 해당 워크플로의 태그가 지워집니다. 대상의 태그를 건드리지 않으려면 --include-tags=false로 내보내세요.
가져오기는 태그를 삭제하지 않습니다. 대상 인스턴스에서 태그가 꺼져 있으면 모든 태그 처리를 조용히 건너뛰며 가져오기를 실패시키지 않습니다.
폴더와 프로젝트#
--folder-conflict-policy=merge는 ID로 매칭된 폴더를 재사용하고 패키지의 콘텐츠를 그 폴더에 병합합니다. 기존 폴더는 자체 이름을 유지하므로 병합해도 이름이 바뀌지 않습니다. 단, 병합된 폴더의 경우 응답에는 대상에서의 폴더 이름이 아니라 패키지의 폴더 이름이 보고된다는 점에 유의하세요.
두 가지 폴더 충돌은 정책과 관계없이 가져오기를 거부합니다. 둘 다 폴더에 병합하는 것이 아니라 폴더를 옮기는 것이 되기 때문입니다. 다른 프로젝트에 존재하는 폴더 ID, 그리고 가져오기가 배치하려는 위치와 다른 상위 폴더 아래에 있는 기존 폴더가 여기에 해당합니다.
프로젝트 패키지의 경우 n8n은 먼저 프로젝트 셸을 생성한 다음 프로젝트마다 한 번씩 동일한 절차를 실행합니다. 패키지 프로젝트의 ID가 대상의 개인 프로젝트와 일치하면 가져오기는 403으로 거부됩니다. 어떤 충돌 정책으로도 병합할 수 없는 경우이기 때문입니다.
노드 유형#
n8n은 매니페스트의 requirements.nodeTypes 목록을 신뢰하지 않고, 워크플로 자체에서 패키지에 필요한 노드 유형을 파악합니다. 매니페스트는 가져오기를 빠르게 할 수는 있어도 결과를 틀리게 만들 수는 없습니다.
기본값인 --missing-node-type-mode=fail에서는 인스턴스에 없는 노드 유형이나 노드 버전을 사용하는 패키지가 아무것도 쓰기 전에 가져오기를 거부하며, 누락된 모든 유형과 이를 사용하는 워크플로를 나열합니다. import-anyway에서는 해당 워크플로가 가져와지지만 게시되지 않습니다.
게시 결과#
응답의 모든 워크플로에는 publishing.state가 포함됩니다.
| 상태 | 의미 |
|---|---|
published |
워크플로가 라이브 상태입니다 |
unpublished |
정책에서 의도한 대로 워크플로가 라이브 상태가 아닙니다 |
unchanged |
게시를 시도하지 않았거나 건너뛰었습니다. 기존 라이브 버전은 계속 실행됩니다 |
blocked |
n8n이 게시를 거부했습니다. blockedReason에 이유가 표시됩니다 |
failed |
게시를 시도했으나 실패했습니다. error에 이유가 표시됩니다 |
blockedReason은 stub-credential 또는 missing-node-type 중 하나입니다. 두 가지 모두로 차단된 워크플로는 missing-node-type을 보고합니다. 이는 워크플로를 물리적으로 실행할 수 없다는 뜻이기 때문입니다.
blocked는 라이브 상태인 것이 없다는 뜻입니다. 워크플로에 이미 게시된 버전이 있는데 새 버전을 게시할 수 없으면, blocked가 아니라 skippedPublishReason이 포함된 unchanged를 받으며 이전 버전이 계속 트래픽을 처리합니다. 따라서 "게시되지 않음"은 워크플로가 아니라 방금 가져온 버전을 가리킵니다.
게시 실패가 가져오기를 실패시키지는 않습니다. 워크플로는 가져와지며, 응답에서 라이브 상태가 아님을 알려 줍니다.
웹훅 경로 충돌#
두 워크플로는 같은 HTTP 메서드로 같은 웹훅 경로를 등록할 수 없습니다. 패키지가 같은 경로를 사용하려는 두 워크플로를 게시하려는 경우, 첫 번째 워크플로는 게시되고 두 번째 워크플로는 There is a conflict with one of the webhooks. 메시지와 함께 failed를 보고합니다. 가져오기 자체는 성공합니다. 인스턴스에 게시된 워크플로가 이미 그 경로를 사용 중일 때도 마찬가지입니다.
n8n은 문자 그대로 읽을 수 있는 경로만 비교합니다. 노드가 활성화되어 있어야 하고, 경로는 표현식이 아닌 일반 값이어야 하며 경로 파라미터가 없어야 합니다. 표현식으로 만든 경로, 파라미터가 있는 경로, n8n이 워크플로마다 접두사를 붙이는 웹훅은 이런 식으로 충돌할 수 없습니다. 같은 경로라도 HTTP 메서드가 다르면 문제가 없습니다.
가져오기가 거부되는 이유#
가져오기가 차단될 수 있는 이유는 12가지입니다. 각 이유는 type과 함께 issues 배열에 나타나며, 일부는 이를 더 세분화하는 kind를 포함합니다.
| 유형 | 종류 | 의미 |
|---|---|---|
workflow-conflict |
워크플로가 대상에 존재하며 --workflow-conflict-policy가 fail입니다 |
|
workflow-id-conflict |
--workflow-id-policy=source에서 해당 워크플로 ID가 다른 프로젝트와 보관된(archived) 워크플로를 포함해 인스턴스의 어딘가에서 이미 사용 중입니다 |
|
workflow-folder-conflict |
기존 워크플로가 가져오기가 배치하려는 폴더와 다른 폴더에 있습니다. --workflow-conflict-policy=skip에서도 가져오기가 거부됩니다 |
|
project-conflict |
fail-policy |
프로젝트가 존재하며 --project-conflict-policy가 fail입니다 |
folder-conflict |
parent-mismatch, id-in-other-project, fail-policy |
앞의 두 가지는 정책과 관계없이 거부합니다 |
credential-unresolved |
not_found, unknown_type, source_not_found, type_mismatch |
not_found만 플레이스홀더 자격 증명으로 해결할 수 있습니다 |
data-table-unresolved |
missing, id-conflict, name-conflict, schema-incompatible, module-disabled, permission-denied |
overwrite-non-destructive에서 schema-incompatible은 변경으로 인해 칼럼이 제거되거나 유형이 바뀐다는 뜻이며, 해당 칼럼을 나열합니다 |
tag-unresolved |
rename-drift, name-collision, invalid-name, invalid-id, permission-denied |
|
variable-unresolved |
참조된 변수가 확인되지 않으며 --variable-missing-mode가 must-preexist입니다 |
|
variable-conflict |
확인된 변수의 값이 다르며 --variable-conflict-policy가 fail입니다 |
|
variable-limit-exceeded |
새 변수가 인스턴스의 변수 한도를 초과합니다 | |
missing-node-type |
--missing-node-type-mode=fail에서 워크플로가 인스턴스에 없는 노드 유형이나 버전을 사용합니다 |
HTTP 상태는 문제의 종류에 따라 달라집니다. 워크플로, 프로젝트, 폴더, 변수 충돌, 데이터 테이블 ID 또는 이름 충돌, 태그 이름 변경 드리프트나 이름 충돌처럼 충돌 성격의 이슈가 하나라도 있으면 응답은 409입니다. 그 외에는 모두 422입니다. 충돌이 하나라도 섞여 있으면 전체 응답이 409로 반환됩니다.
일부 실패는 n8n이 계획을 세우기 전에 중단시키므로 나머지와 함께 묶이지 않고 단독으로 보고됩니다. 누락된 라이선스 기능, 누락된 API 키 스코프, 잘못된 형식의 패키지가 여기에 해당합니다.
태그를 생성하거나 데이터 테이블을 생성 또는 변경할 권한이 없는 경우는 403이 아닙니다. 필요한 스코프를 알려 주는 permission-denied 차단 이슈로 반환됩니다.
다음에 읽을 내용#
- 이 페이지에서 언급한 옵션은 패키지 가져오기를 참조하세요.
- 가져오기가 검사하는 라이선스 기능, 스코프, 할당량은 제한 및 권한을 참조하세요.
- n8n이 읽는 파일의 구성은 패키지 형식을 참조하세요.