노드 빌딩 스타일 선택하기
n8n v2.42요약
n8n에는 선언적(declarative) 스타일과 프로그래매틱(programmatic) 스타일, 두 가지 노드 빌딩 스타일이 있습니다. 노드에 어떤 스타일이 필요한지 확신이 없다면 선언적 스타일로 시작하세요. 이 섹션의 상세 내용은 n8n 공식 문서를 참조하세요.
n8n에는 선언적(declarative) 스타일과 프로그래매틱(programmatic) 스타일, 두 가지 노드 빌딩 스타일이 있습니다. 노드는 선언적 스타일로 빌드하세요. 새 노드의 기본 스타일입니다.
선언적 스타일은 다음과 같습니다.
- JSON 기반 문법을 사용하므로 작성하기 더 간단하고 버그가 발생할 위험이 적습니다.
- 미래 호환성이 더 좋습니다.
- REST API와의 통합을 지원합니다.
execute()메서드가 필요 없으므로 작성하고 유지 관리할 코드가 줄어듭니다.
노드에 어떤 스타일이 필요한지 확신이 없다면 선언적 스타일로 시작하세요. n8n-node 도구가 선언적 노드의 뼈대를 만들어 주며, 선언적 스타일 노드 빌드하기에서 전체 예시를 단계별로 확인할 수 있습니다.
이 섹션의 상세 내용은 n8n 공식 문서를 참조하세요.
프로그래매틱 스타일이 필요한 경우#
프로그래매틱 스타일은 더 장황하며, 노드의 동작을 직접 유지 관리해야 하는 코드에 담습니다. 예외적인 경우로 취급하세요. 노드가 다음 중 하나에 해당하면 프로그래매틱 스타일을 사용합니다.
- 트리거 노드.
- REST 기반이 아닌 노드. 여기에는 GraphQL API를 호출해야 하는 노드와 외부 의존성을 사용하는 노드가 포함됩니다.
- 라우팅이 처리하는 범위를 넘어 데이터를 변환해야 하는 노드. 선언적 스타일은
routing.request.preSend로 요청을,routing.output.postReceive로 API 응답을 변경할 수 있습니다. 노드가 단일 API 호출과 무관하게 수신 항목을 처리해야 하면 프로그래매틱 스타일을 사용합니다. this.isNodeFeatureEnabled()를 사용해 코드에서 동작을 분기하는 기능 기반 버전 관리가 필요한 노드. 선언적 노드도 가벼운 버전 관리는 사용할 수 있으며,displayOptions의@feature로 기능 플래그를 읽을 수 있습니다. 버전 관리 유형에 대한 자세한 내용은 노드 버전 관리를 참고하세요.
노드가 이 목록에 해당하지 않으면 선언적 스타일로 빌드하세요.
트리거 노드는 프로그래매틱 스타일을 사용해야 합니다
선언적 스타일은 트리거 노드를 지원하지 않습니다. 같은 서비스의 액션 노드가 선언적 스타일이더라도 모든 트리거 노드는 프로그래매틱 스타일로 빌드하세요.
하나의 노드 패키지에서 두 스타일을 함께 사용할 수 있습니다. 예를 들어 검증을 위해 제출하는 패키지에 같은 서비스의 선언적 스타일 액션 노드와 프로그래매틱 스타일 트리거 노드를 함께 담을 수 있습니다.
데이터 처리 방식의 차이#
선언적 스타일과 프로그래매틱 스타일의 주요 차이점은 수신 데이터를 처리하고 API 요청을 구성하는 방식입니다. 프로그래매틱 스타일에는 수신 데이터와 매개변수를 읽은 후 요청을 구성하는 execute() 메서드가 필요합니다. 선언적 스타일은 operations 객체 안의 routing 키를 사용해 이를 처리합니다. 노드 매개변수와 execute() 메서드에 대한 자세한 내용은 노드 기본 파일을 참고하세요.
문법 차이#
선언적 스타일과 프로그래매틱 스타일의 차이를 이해하려면 아래 두 코드 스니펫을 비교해 보세요. 이 예시는 SendGrid 통합을 단순화한 버전인 "FriendGrid"를 만듭니다. 다음 코드 스니펫은 완전한 코드가 아니며, 노드 빌딩 스타일의 차이를 강조하기 위한 것입니다.
FriendGrid는 REST API를 호출하고 입력을 변환하지 않으므로 선언적 스타일이 적합합니다. 선언적 스타일은 다음과 같습니다.
import { INodeType, INodeTypeDescription } from 'n8n-workflow';
// Create the FriendGrid class
export class FriendGrid implements INodeType {
description: INodeTypeDescription = {
displayName: 'FriendGrid',
name: 'friendGrid',
. . .
// Set up the basic request configuration
requestDefaults: {
baseURL: 'https://api.sendgrid.com/v3/marketing'
},
properties: [
{
displayName: 'Resource',
. . .
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'contact',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a contact',
// Add the routing object
routing: {
request: {
method: 'POST',
url: '=/contacts',
send: {
type: 'body',
properties: {
email: '={{$parameter["email"]}}'
}
}
},
// Handle the response to contact creation
output: {
postReceive: [
{
type: 'set',
properties: {
value: '={{ { "success": $response } }}'
}
}
]
}
}
},
],
default: 'create',
description: 'The operation to perform.',
},
{
displayName: 'Email',
. . .
},
{
displayName: 'Additional Fields',
// Sets up optional fields
},
],
}
// No execute method needed
}
같은 노드를 프로그래매틱 스타일로 작성하면 매개변수를 읽고 요청을 직접 구성하는 execute() 메서드가 필요합니다.
import {
IExecuteFunctions,
INodeExecutionData,
INodeType,
INodeTypeDescription,
IRequestOptions,
} from 'n8n-workflow';
// Create the FriendGrid class
export class FriendGrid implements INodeType {
description: INodeTypeDescription = {
displayName: 'FriendGrid',
name: 'friendGrid',
. . .
properties: [
{
displayName: 'Resource',
. . .
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'contact',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a contact',
},
],
default: 'create',
description: 'The operation to perform.',
},
{
displayName: 'Email',
name: 'email',
. . .
},
{
displayName: 'Additional Fields',
// Sets up optional fields
},
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
let responseData;
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;
//Get credentials the user provided for this node
const credentials = await this.getCredentials('friendGridApi') as IDataObject;
if (resource === 'contact') {
if (operation === 'create') {
// Get email input
const email = this.getNodeParameter('email', 0) as string;
// Get additional fields input
const additionalFields = this.getNodeParameter('additionalFields', 0) as IDataObject;
const data: IDataObject = {
email,
};
Object.assign(data, additionalFields);
// Make HTTP request as defined in https://sendgrid.com/docs/api-reference/
const options: IRequestOptions = {
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${credentials.apiKey}`,
},
method: 'PUT',
body: {
contacts: [
data,
],
},
url: `https://api.sendgrid.com/v3/marketing/contacts`,
json: true,
};
responseData = await this.helpers.httpRequest(options);
}
}
// Map data to n8n data
return [this.helpers.returnJsonArray(responseData)];
}
}