선언형 스타일 node 빌드
이 튜토리얼은 선언형 스타일 node를 빌드하는 과정을 안내합니다. 개발 머신에 다음이 설치되어 있어야 합니다: 다음에 대한 기본 이해가 필요합니다: 이 섹션에서 n8n의 node 스타터 리포지터리를 클론하고 NASA API를 통합하는 node를 빌드합니다.
이 튜토리얼은 선언형 스타일 node를 빌드하는 과정을 안내합니다. 시작하기 전에 이 node 스타일이 필요한지 확인하세요. 자세한 내용은 node 빌드 접근 방식 선택을 참고하세요.
사전 요구사항#
개발 머신에 다음이 설치되어 있어야 합니다:
- git
- Node.js 및 npm. 최소 버전은 Node 18.17.0입니다. Linux, Mac, WSL에서 nvm(Node Version Manager)을 사용하여 두 가지를 설치하는 방법은 여기에서 확인할 수 있습니다. Windows 사용자는 Microsoft의 Windows에 NodeJS 설치 가이드를 참고하세요.
다음에 대한 기본 이해가 필요합니다:
- JavaScript/TypeScript
- REST API
- git
node 빌드#
이 섹션에서 n8n의 node 스타터 리포지터리를 클론하고 NASA API를 통합하는 node를 빌드합니다. NASA의 두 서비스를 사용하는 node를 만들 것입니다: APOD(오늘의 천문학 사진)와 화성 탐사선 사진. 코드 예시를 간결하게 유지하기 위해 화성 탐사선 사진 엔드포인트의 모든 옵션을 구현하지 않습니다.
n8n에는 내장 NASA node가 있습니다. 기존 node와의 충돌을 피하기 위해 다른 이름을 사용합니다.
1단계: 프로젝트 설정#
n8n은 node 개발을 위한 스타터 리포지터리를 제공합니다. 스타터를 사용하면 모든 필요한 의존성을 갖출 수 있습니다. 린터도 제공합니다.
리포지터리를 클론하고 디렉터리로 이동합니다:
- 템플릿 리포지터리에서 새 리포지터리를 생성합니다.
- 새 리포지터리를 클론합니다:
shell git clone https://github.com/<your-organization>/<your-repo-name>.git n8n-nodes-nasa-pics cd n8n-nodes-nasa-pics
스타터에는 예시 node와 자격 증명이 포함되어 있습니다. 다음 디렉터리와 파일을 삭제합니다:
nodes/Examplenodes/GithubIssuescredentials/GithubIssuesApi.credentials.tscredentials/GithubIssuesOAuth2Api.credentials.ts
이제 다음 디렉터리와 파일을 생성합니다:
nodes/NasaPics
nodes/NasaPics/NasaPics.node.json
nodes/NasaPics/NasaPics.node.ts
credentials/NasaPicsApi.credentials.ts
이것이 모든 node에 필요한 핵심 파일입니다. 필수 파일 및 권장 구성에 대한 자세한 내용은 node 파일 구조를 참고하세요.
이제 프로젝트 의존성을 설치합니다:
npm i
2단계: 아이콘 추가#
여기에서 NASA SVG 로고를 nodes/NasaPics/에 nasapics.svg로 저장합니다.
n8n은 노드 아이콘으로 SVG 사용을 권장하지만, PNG도 사용할 수 있습니다. PNG를 사용하는 경우 아이콘 해상도는 60x60px여야 합니다. 노드 아이콘은 정사각형 또는 정사각형에 가까운 비율이어야 합니다.
노드에 Font Awesome 아이콘을 사용하려면 이미지를 다운로드하여 임베드하세요.
3단계: node 생성#
모든 node는 기본 파일이 있어야 합니다. 기본 파일 파라미터에 대한 자세한 내용은 node 기본 파일을 참고하세요.
이 예시에서 파일은 NasaPics.node.ts입니다. 이 튜토리얼을 간결하게 유지하기 위해 모든 node 기능을 이 하나의 파일에 넣습니다. 더 복잡한 node를 빌드할 때는 기능을 모듈로 분리하는 것을 고려해야 합니다. 자세한 내용은 node 파일 구조를 참고하세요.
3.1단계: 임포트#
임포트 문을 추가하는 것부터 시작합니다:
import { NodeConnectionTypes } from 'n8n-workflow';
import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
3.2단계: 메인 클래스 생성#
node는 INodeType을 구현하는 인터페이스를 내보내야 합니다. 이 인터페이스에는 description 인터페이스가 포함되어야 하며, 이 인터페이스에는 properties 배열이 포함됩니다.
클래스 이름과 파일 이름이 일치하는지 확인하세요. 예를 들어, NasaPics 클래스의 경우 파일명은 NasaPics.node.ts여야 합니다.
export class NasaPics implements INodeType {
description: INodeTypeDescription = {
// 기본 node 세부 정보가 여기에 옵니다
properties: [
// 리소스와 작업이 여기에 옵니다
]
};
}
3.3단계: node 세부 정보 추가#
모든 node에는 표시 이름, 아이콘, node를 사용한 요청을 위한 기본 정보와 같은 기본 파라미터가 필요합니다. description에 다음을 추가합니다:
displayName: 'NASA Pics',
name: 'nasaPics',
icon: 'file:nasapics.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Get data from NASAs API',
defaults: {
name: 'NASA Pics',
},
usableAsTool: true,
inputs: [ NodeConnectionTypes.Main ],
outputs: [ NodeConnectionTypes.Main ],
credentials: [
{
name: 'NasaPicsApi',
required: true,
},
],
requestDefaults: {
baseURL: 'https://api.nasa.gov',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
n8n은 에디터 UI에서 node를 렌더링하기 위해 description에 설정된 일부 속성을 사용합니다. 이 속성들은 displayName, icon, description, subtitle입니다.
3.4단계: 리소스 추가#
리소스 오브젝트는 node가 사용하는 API 리소스를 정의합니다. 이 튜토리얼에서 NASA의 두 API 엔드포인트인 planetary/apod와 mars-photos에 접근하는 node를 만들고 있습니다. 즉, NasaPics.node.ts에 두 가지 리소스 옵션을 정의해야 합니다. 리소스 오브젝트로 properties 배열을 업데이트합니다:
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Astronomy Picture of the Day',
value: 'astronomyPictureOfTheDay',
},
{
name: 'Mars Rover Photos',
value: 'marsRoverPhotos',
},
],
default: 'astronomyPictureOfTheDay',
},
// 작업이 여기에 옵니다
]
type은 n8n이 리소스에 대해 표시할 UI 요소를 제어하고, n8n에게 사용자로부터 기대하는 데이터 유형을 알려줍니다. options는 n8n이 사용자가 하나의 옵션을 선택할 수 있는 드롭다운을 추가하게 합니다. 자세한 내용은 node UI 요소를 참고하세요.
3.5단계: 작업 추가#
작업 오브젝트는 리소스에서 사용 가능한 작업을 정의합니다.
선언형 스타일 node에서 작업 오브젝트는 (options 배열 내에) routing을 포함합니다. 이것은 API 호출의 세부 정보를 설정합니다.
properties 배열에 resource 오브젝트 뒤에 다음을 추가합니다:
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: [
'astronomyPictureOfTheDay',
],
},
},
options: [
{
name: 'Get',
value: 'get',
action: 'Get the APOD',
description: 'Get the Astronomy Picture of the day',
routing: {
request: {
method: 'GET',
url: '/planetary/apod',
},
},
},
],
default: 'get',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: [
'marsRoverPhotos',
],
},
},
options: [
{
name: 'Get',
value: 'get',
action: 'Get Mars Rover photos',
description: 'Get photos from the Mars Rover',
routing: {
request: {
method: 'GET',
},
},
},
],
default: 'get',
},
{
displayName: 'Rover name',
description: 'Choose which Mars Rover to get a photo from',
required: true,
name: 'roverName',
type: 'options',
options: [
{name: 'Curiosity', value: 'curiosity'},
{name: 'Opportunity', value: 'opportunity'},
{name: 'Perseverance', value: 'perseverance'},
{name: 'Spirit', value: 'spirit'},
],
routing: {
request: {
url: '=/mars-photos/api/v1/rovers/{{$value}}/photos',
},
},
default: 'curiosity',
displayOptions: {
show: {
resource: [
'marsRoverPhotos',
],
},
},
},
{
displayName: 'Date',
description: 'Earth date',
required: true,
name: 'marsRoverDate',
type: 'dateTime',
default:'',
displayOptions: {
show: {
resource: [
'marsRoverPhotos',
],
},
},
routing: {
request: {
// URL을 이미 설정했습니다. qs는 쿼리 문자열로 필드 값을 추가합니다
qs: {
earth_date: '={{ new Date($value).toISOString().substr(0,10) }}',
},
},
},
},
// 선택/추가 필드가 여기에 옵니다
이 코드는 두 가지 작업을 생성합니다: 오늘의 APOD 이미지를 가져오는 작업과 화성 탐사선 사진에 대한 GET 요청을 전송하는 작업. roverName이라는 오브젝트는 사용자가 어떤 탐사선의 사진을 원하는지 선택하도록 요청합니다. 화성 탐사선 작업의 routing 오브젝트는 API 호출을 위한 URL을 생성하기 위해 이를 참조합니다.
3.6단계: 선택적 필드#
이 예시에서 사용하는 NASA API를 포함한 대부분의 API에는 쿼리를 세분화하는 데 사용할 수 있는 선택적 필드가 있습니다.
사용자가 압도당하지 않도록 n8n은 UI의 추가 필드 아래에 이를 표시합니다.
이 튜토리얼에서는 사용자가 APOD 엔드포인트와 함께 사용할 날짜를 선택할 수 있도록 하나의 추가 필드를 추가합니다. properties 배열에 다음을 추가합니다:
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
default: {},
placeholder: 'Add Field',
displayOptions: {
show: {
resource: [
'astronomyPictureOfTheDay',
],
operation: [
'get',
],
},
},
options: [
{
displayName: 'Date',
name: 'apodDate',
type: 'dateTime',
default: '',
routing: {
request: {
// URL을 이미 설정했습니다. qs는 쿼리 문자열로 필드 값을 추가합니다
qs: {
date: '={{ new Date($value).toISOString().substr(0,10) }}',
},
},
},
},
],
}
4단계: 인증 및 자격 증명 테스트 설정#
NASA API는 사용자가 API 키로 인증하도록 요구합니다. API 키가 작동하는지 확인하는 요청을 보낼 수도 있습니다.
nasaPicsApi.credentials.ts에 다음을 추가합니다:
import {
IAuthenticateGeneric,
ICredentialTestRequest,
ICredentialType,
INodeProperties,
} from 'n8n-workflow';
export class NasaPicsApi implements ICredentialType {
name = 'NasaPicsApi';
displayName = 'NASA Pics API';
// 이 튜토리얼 링크를 예시로 사용합니다
// 자신의 node를 빌드할 때는 자신의 문서 링크로 교체하세요
documentationUrl = 'https://docs.n8n.io/integrations/creating-nodes/build/declarative-style-node/';
properties: INodeProperties[] = [
{
displayName: 'API Key',
name: 'apiKey',
type: 'string',
default: '',
},
];
authenticate: IAuthenticateGeneric = {
type: 'generic',
properties: {
qs: {
'api_key': '={{$credentials.apiKey}}'
}
},
};
test: ICredentialTestRequest = {
request: {
baseURL: 'https://api.nasa.gov',
url: '/apod',
},
};
}
자격 증명 파일 및 옵션에 대한 자세한 내용은 자격 증명 파일을 참고하세요.
5단계: node 메타데이터 추가#
node에 대한 메타데이터는 node 루트의 JSON 파일에 있습니다. n8n은 이를 코덱스 파일이라고 합니다. 이 예시에서 파일은 NasaPics.node.json입니다.
JSON 파일에 다음 코드를 추가합니다:
{
"node": "n8n-nodes-base.NasaPics",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": [
"Miscellaneous"
],
"resources": {
"credentialDocumentation": [
{
"url": ""
}
],
"primaryDocumentation": [
{
"url": ""
}
]
}
}
이 파라미터에 대한 자세한 내용은 node 코덱스 파일을 참고하세요.
6단계: npm 패키지 세부 정보 업데이트#
npm 패키지 세부 정보는 프로젝트 루트의 package.json에 있습니다. 자격 증명 및 기본 node 파일에 대한 링크와 함께 n8n 오브젝트를 포함하는 것이 필수적입니다. 다음 정보를 포함하도록 이 파일을 업데이트합니다:
{
// 모든 node 이름은 "n8n-nodes-"로 시작해야 합니다
"name": "n8n-nodes-nasapics",
"version": "0.1.0",
"description": "n8n node to call NASA's APOD and Mars Rover Photo services.",
"keywords": [
// 이 키워드는 커뮤니티 node에 필수입니다
"n8n-community-node-package"
],
"license": "MIT",
"homepage": "https://n8n.io",
"author": {
"name": "Test",
"email": "test@example.com"
},
"repository": {
"type": "git",
// git 리모트를 자신의 리포지터리로 변경하세요
// 여기에 새 URL을 추가하세요
"url": "git+<your-repo-url>"
},
"main": "index.js",
"scripts": {
// 변경하지 마세요
},
"files": [
"dist"
],
// 자격 증명과 node 연결
"n8n": {
"n8nNodesApiVersion": 1,
"credentials": [
"dist/credentials/NasaPicsApi.credentials.js"
],
"nodes": [
"dist/nodes/NasaPics/NasaPics.node.js"
]
},
"devDependencies": {
// 변경하지 마세요
},
"peerDependencies": {
// 변경하지 마세요
}
}
이름 및 리포지터리 URL과 같은 자신의 정보를 포함하도록 package.json을 업데이트해야 합니다. npm package.json 파일에 대한 자세한 내용은 npm의 package.json 문서를 참고하세요.
node 테스트#
로컬 n8n 인스턴스에서 실행하여 노드를 만들면서 테스트할 수 있습니다.
- npm으로 n8n을 설치합니다:
npm install n8n -g
- 노드를 테스트할 준비가 되면 로컬에 배포합니다:
# 노드 디렉토리 내에서
npm run build
npm link
- 로컬 n8n 인스턴스에 노드를 설치합니다:
# n8n 설치 디렉토리 내 nodes 폴더에서
# node-package-name은 package.json의 이름입니다
npm link <node-package-name>
n8n 설치 디렉토리 내 nodes 폴더에서 npm link <node-name>을 실행하세요. 위치는 다음과 같습니다:
* `~/.n8n/custom/`
* `~/.n8n/<your-custom-name>`: n8n 설치 시 `N8N_CUSTOM_EXTENSIONS`로 다른 이름을 설정한 경우.
- n8n을 시작합니다:
n8n start
- 브라우저에서 n8n을 엽니다. 노드 패널에서 검색하면 노드가 표시됩니다.
패키지 이름이 아닌 노드 이름으로 검색하세요. 예를 들어 npm 패키지 이름이 n8n-nodes-weather-nodes이고 패키지에 rain, sun, snow라는 노드가 있다면 weather-nodes가 아닌 rain으로 검색해야 합니다.
문제 해결#
~/.n8n 로컬 설치에 custom 디렉토리가 없으면 수동으로 custom 디렉토리를 생성하고 npm init을 실행해야 합니다:
# ~/.n8n 디렉토리에서 실행
mkdir custom
cd custom
npm init
다음 단계#
- node 배포.
- 선언형 node 예시 확인: n8n의 Brevo node. 메인 node는 선언형이지만 트리거 node는 프로그래매틱 스타일입니다.
- node 버전 관리에 대해 알아보세요.
