콘텐츠로 이동
📣 인포그랩에서 OpenAI 기술 기반으로 자체 개발한 자동화 번역 프로그램을 통해 n8n 공식 문서의 한글판을 국내 최초로 제공합니다.

데이터 병합 및 분할#

이 장에서는 데이터 병합 및 분할 방법과 이러한 작업을 수행하는 것이 유용한 경우에 대해 배우게 됩니다.

데이터 병합#

경우에 따라 서로 다른 소스의 데이터를 병합(결합)하고 처리해야 할 필요가 있습니다.

데이터 병합은 다음을 포함할 수 있습니다:

  • 여러 소스에서 하나의 데이터 세트 생성하기.
  • 여러 시스템 간의 데이터 동기화. 여기에는 중복 데이터 제거 또는 한 시스템에서 변경될 때 다른 시스템의 데이터 업데이트가 포함될 수 있습니다.

단방향 동기화 vs. 양방향 동기화

단방향 동기화에서는 데이터가 한 방향으로 동기화됩니다. 한 시스템이 단일 진실 소스로 작용합니다. 주요 시스템에서 정보가 변경되면 해당 정보는 자동으로 보조 시스템에도 반영되지만, 보조 시스템에서 정보가 변경되면 그 변경 사항은 주요 시스템에 반영되지 않습니다.

양방향 동기화에서는 데이터가 양쪽(두 시스템 간)으로 동기화됩니다. 두 시스템 중 하나에서 정보가 변경되면 자동으로 다른 시스템에서도 변경됩니다.

이 블로그 튜토리얼은 두 CRM 간에 데이터를 단방향 및 양방향으로 동기화하는 방법을 설명합니다.

n8n에서는 Merge node를 사용하여 두 다른 노드에서 데이터를 병합할 수 있으며, 여러 병합 옵션을 제공합니다:

Combine > Merge by Fields는 일치할 입력 필드를 입력해야 합니다. 이러한 필드는 데이터 소스 간에 동일한 값을 포함해야 n8n이 데이터를 적절히 일치시킬 수 있습니다. Merge node에서는 이러한 필드를 Input 1 FieldInput 2 Field라고 합니다.

Merge node의 Property Input 필드
Merge node의 Property Input 필드

점 표기법에서의 속성 입력

Merge node의 매개변수 Input 1 FieldInput 2 Field에서 중첩 값을 참조하려면 속성 키를 점 표기법 형식으로 입력해야 합니다(텍스트 형식으로, 표현식이 아님).

Note

Merge node는 Join이라는 별칭 아래에서도 찾을 수 있습니다. SQL 조인에 익숙하다면 이것이 더 직관적일 수 있습니다.

병합 연습#

Customer Datastore 노드와 Code 노드에서 데이터를 병합하는 워크플로우를 구축하세요.

  1. Customer Datastore node에서 Input 1을 가져오고 Code node에서 Input 2를 가져오는 Merge node를 추가하세요.
  2. Customer Datastore node에서 Get All People 작업을 실행하세요.
  3. Code node에서 세 개의 속성(name, language, country)을 가진 두 개의 객체 배열을 생성하세요. 여기서 country 속성은 두 개의 하위 속성 codename을 가집니다.
    • 이러한 속성의 값을 Customer Database에서 선택한 두 캐릭터의 정보로 채우세요.
    • 예를 들어, Jay Gatsby의 언어는 영어이고 국가 이름은 미국입니다.
  4. Merge node에서 다양한 병합 옵션을 시도해 보세요.
해결책 보여줘

이 연습의 워크플로우는 다음과 같습니다:

데이터 병합을 위한 워크플로우 연습
데이터 병합을 위한 워크플로우 연습

이름을 입력 필드로 사용하고 Keep Matches 옵션을 사용하여 데이터를 병합하면 결과는 다음과 같아야 합니다(이 예제는 Jay Gatsby만 포함되어 있으며, 선택한 캐릭터에 따라 다를 수 있습니다):

병합 노드의 일치 유지 옵션 출력
병합 노드의 일치 유지 옵션 출력

노드의 구성을 확인하려면 아래의 JSON 워크플로우 코드를 복사하여 편집기 UI에 붙여넣으세요:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
{
"meta": {
	"templateCredsSetupCompleted": true,
	"instanceId": "cb484ba7b742928a2048bf8829668bed5b5ad9787579adea888f05980292a4a7"
},
"nodes": [
	{
	"parameters": {
		"mode": "combine",
		"mergeByFields": {
		"values": [
			{
			"field1": "name",
			"field2": "name"
			}
		]
		},
		"options": {}
	},
	"id": "578365f3-26dd-4fa6-9858-f0a5fdfc413b",
	"name": "Merge",
	"type": "n8n-nodes-base.merge",
	"typeVersion": 2.1,
	"position": [
		720,
		580
	]
	},
	{
	"parameters": {},
	"id": "71aa5aad-afdf-4f8a-bca0-34450eee8acc",
	"name": "When clicking \"Test workflow\"",
	"type": "n8n-nodes-base.manualTrigger",
	"typeVersion": 1,
	"position": [
		260,
		560
	]
	},
	{
	"parameters": {
		"operation": "getAllPeople"
	},
	"id": "497174fe-3cab-4160-8103-78b44efd038d",
	"name": "Customer Datastore (n8n training)",
	"type": "n8n-nodes-base.n8nTrainingCustomerDatastore",
	"typeVersion": 1,
	"position": [
		500,
		460
	]
	},
	{
	"parameters": {
		"jsCode": "return [\n  {\n    'name': 'Jay Gatsby',\n    'language': 'English',\n    'country': {\n      'code': 'US',\n      'name': 'United States'\n    }\n    \n  }\n  \n];"
	},
	"id": "387e8a1e-e796-4f05-8e75-7ce25c786c5f",
	"name": "Code",
	"type": "n8n-nodes-base.code",
	"typeVersion": 2,
	"position": [
		500,
		720
	]
	}
],
"connections": {
	"When clicking \"Test workflow\"": {
	"main": [
		[
		{
			"node": "Customer Datastore (n8n training)",
			"type": "main",
			"index": 0
		},
		{
			"node": "Code",
			"type": "main",
			"index": 0
		}
		]
	]
	},
	"Customer Datastore (n8n training)": {
	"main": [
		[
		{
			"node": "Merge",
			"type": "main",
			"index": 0
		}
		]
	]
	},
	"Code": {
	"main": [
		[
		{
			"node": "Merge",
			"type": "main",
			"index": 1
		}
		]
	]
	}
},
"pinData": {}
}

루핑#

경우에 따라 배열의 각 요소 또는 각 데이터 항목에 동일한 작업을 수행해야 할 수 있습니다(예: 주소록의 모든 연락처에 메시지를 전송). 기술적으로는 데이터를 반복(iterate)해야 합니다.

n8n은 일반적으로 이러한 반복 처리를 자동으로 처리하므로, 노드는 각 항목에 대해 한 번 실행되므로 워크플로우에 루프를 구축할 필요가 없습니다.

그러나 워크플로우에 루프를 구축해야 하는 노드와 작업의 예외가 있습니다.

n8n 워크플로우에서 루프를 생성하려면, 한 노드의 출력을 이전 노드의 입력에 연결하고, 루프를 멈출 시점을 확인하기 위해 If 노드를 추가해야 합니다.

배치 단위로 데이터 분할#

대량의 데이터가 들어오는 경우, Code 노드를 여러 번 실행하거나 API 속도 제한을 피해야 하는 경우, 데이터를 배치(그룹)로 나누어 처리하는 것이 가장 좋습니다.

이러한 프로세스에는 Loop Over Items node를 사용하세요. 이 노드는 입력 데이터를 지정된 배치 크기로 나누고 각 반복에서 미리 정의된 양의 데이터를 반환합니다.

Loop Over Items 노드 실행

Loop Over Items 노드는 모든 들어오는 항목이 배치로 나누어지고 워크플로우의 다음 노드로 전달된 후에 실행을 중지하므로 루프를 멈추기 위해 If 노드를 추가할 필요가 없습니다.

루프/배치 연습#

Medium과 dev.to에서 RSS 피드를 읽는 워크플로우를 구축하세요. 이 워크플로우는 세 개의 노드로 구성되어야 합니다:

  1. Medium(https://medium.com/feed/n8n-io) 및 dev.to(https://dev.to/feed/n8n)의 RSS 피드 URL을 반환하는 Code 노드.
  2. Code 노드RSS Read 노드의 입력을 받아 항목을 반복하는 Batch Size: 1Loop Over Items node.
  3. Medium RSS 피드의 URL을 가져오는 RSS Read 노드, 표현식으로 전달됨: {{ $json.url }}.
    • RSS Read 노드는 수신하는 첫 번째 항목만 처리하는 예외 노드이므로 여러 항목을 반복하기 위해 Loop Over Items node가 필요합니다.
해결 방법 보여주기
  1. Code Node를 추가하세요. 코드를 여러 가지 방법으로 포맷할 수 있습니다. 한 가지 방법은:
    • ModeRun Once for All Items로 설정합니다.
    • LanguageJavaScript로 설정합니다.
    • 아래 코드를 복사하여 JavaScript 코드 편집기에 붙여넣습니다:
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      let urls = [
      	{
      		json: {
      		url: 'https://medium.com/feed/n8n-io'
      		}
      	},
      	{
      	json: {
      		url: 'https://dev.to/feed/n8n'
      		} 
      	}
      ]
      return urls;
      
  2. Code 노드에 연결된 Loop Over Items 노드를 추가합니다.
    • Batch Size1로 설정합니다.
  3. Loop Over Items 노드는 "Replace Me"라는 자동으로 추가된 노드를 포함합니다. 해당 노드를 RSS Read 노드로 교체합니다.
    • URL을 Code Node의 URL로 설정합니다: {{ $json.url }}.

이 연습을 위한 워크플로우는 다음과 같습니다:

두 블로그에서 RSS 피드를 가져오는 워크플로우
두 블로그에서 RSS 피드를 가져오는 워크플로우

노드의 구성을 확인하기 위해 아래의 JSON 워크플로우 코드를 복사하여 편집기 UI에 붙여넣을 수 있습니다:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
{
"meta": {
	"templateCredsSetupCompleted": true,
	"instanceId": "cb484ba7b742928a2048bf8829668bed5b5ad9787579adea888f05980292a4a7"
},
"nodes": [
	{
	"parameters": {},
	"id": "ed8dc090-ae8c-4db6-a93b-0fa873015c25",
	"name": "When clicking \"Test workflow\"",
	"type": "n8n-nodes-base.manualTrigger",
	"typeVersion": 1,
	"position": [
		460,
		460
	]
	},
	{
	"parameters": {
		"jsCode": "let urls = [\n  {\n    json: {\n      url: 'https://medium.com/feed/n8n-io'\n    }\n  },\n  {\n   json: {\n     url: 'https://dev.to/feed/n8n'\n   } \n  }\n]\n\nreturn urls;"
	},
	"id": "1df2a9bf-f970-4e04-b906-92dbbc9e8d3a",
	"name": "Code",
	"type": "n8n-nodes-base.code",
	"typeVersion": 2,
	"position": [
		680,
		460
	]
	},
	{
	"parameters": {
		"options": {}
	},
	"id": "3cce249a-0eab-42e2-90e3-dbdf3684e012",
	"name": "Loop Over Items",
	"type": "n8n-nodes-base.splitInBatches",
	"typeVersion": 3,
	"position": [
		900,
		460
	]
	},
	{
	"parameters": {
		"url": "={{ $json.url }}",
		"options": {}
	},
	"id": "50e1c1dc-9a5d-42d3-b7c0-accc31636aa6",
	"name": "RSS Read",
	"type": "n8n-nodes-base.rssFeedRead",
	"typeVersion": 1,
	"position": [
		1120,
		460
	]
	}
],
"connections": {
	"When clicking \"Test workflow\"": {
	"main": [
		[
		{
			"node": "Code",
			"type": "main",
			"index": 0
		}
		]
	]
	},
	"Code": {
	"main": [
		[
		{
			"node": "Loop Over Items",
			"type": "main",
			"index": 0
		}
		]
	]
	},
	"Loop Over Items": {
	"main": [
		null,
		[
		{
			"node": "RSS Read",
			"type": "main",
			"index": 0
		}
		]
	]
	},
	"RSS Read": {
	"main": [
		[
		{
			"node": "Loop Over Items",
			"type": "main",
			"index": 0
		}
		]
	]
	}
},
"pinData": {}
}
인포레터에서 최신 DevOps 트렌드를 격주로 만나보세요!