G: 안녕하세요, 자동화와 워크플로우를 사랑하는 여러분! ✨ n8n은 정말 강력한 도구죠. 수많은 노드들로 복잡한 작업도 뚝딱 자동화할 수 있습니다. 하지만 때로는 기본 노드만으로는 해결하기 어려운 복잡한 로직이나 데이터 변환이 필요할 때가 있습니다. 이럴 때 n8n의 진정한 슈퍼히어로가 등장합니다! 바로 Code Node입니다. 🦸♂️
Code Node는 여러분이 직접 JavaScript 코드를 작성하여 n8n 워크플로우에 원하는 기능을 추가할 수 있게 해주는 마법 같은 공간입니다. 이 글에서는 Code Node를 완벽하게 활용하기 위한 필수 문법과, 코딩 초보자도 쉽게 따라 할 수 있는 디버깅 꿀팁들을 자세히 알려드릴게요. 💡
🚀 Code Node, 왜 중요할까?
n8n은 다양한 앱과 서비스를 연결해주는 수많은 노드를 제공하지만, 모든 시나리오를 커버할 수는 없습니다. 이럴 때 Code Node가 빛을 발합니다.
- ⚡️ 복잡한 데이터 변환: 여러 소스에서 들어온 데이터를 특정 형식으로 가공하거나, 특정 필드만 추출하여 조합해야 할 때 유용합니다.
- 🧩 맞춤형 로직 구현: 특정 조건에 따라 다른 동작을 수행하거나, 외부 API를 호출하여 데이터를 가져오는 등 n8n 기본 노드에 없는 독자적인 기능을 구현할 수 있습니다.
- ⚙️ 효율적인 워크플로우: 여러 노드를 거쳐야 할 작업을 Code Node 하나로 압축하여 워크플로우를 간결하고 효율적으로 만들 수 있습니다.
- 🔗 외부 라이브러리 활용:
axios
로 HTTP 요청을 보내거나,lodash
같은 유틸리티 라이브러리를 활용하여 더욱 강력한 기능을 만들 수 있습니다.
한마디로 Code Node는 n8n 워크플로우의 한계를 넘어서는 “자유로운 확장성”을 제공합니다. 이제 이 강력한 도구를 다루는 방법을 알아볼까요?
📝 Code Node 필수 문법 완전 정복!
Code Node는 기본적으로 JavaScript 환경입니다. 따라서 기본적인 JavaScript 문법에 익숙하다면 빠르게 적응할 수 있습니다.
1. 입력 데이터 접근하기 (items
, $node
, $
) 🧑🤝🧑
Code Node는 이전 노드에서 넘어온 데이터를 처리합니다. 이 데이터는 주로 items
라는 이름의 배열로 제공됩니다.
-
items
: 이전 노드에서 전달받은 모든 데이터 아이템들의 배열입니다. 각 아이템은 보통{ json: { ... } }
형태로 구성되어 있습니다. 여기서json
객체 안에 실제 데이터가 들어있습니다.예시:
items
배열의 첫 번째 아이템에 접근하고 싶을 때// 입력 데이터 예시: // [ // { json: { name: "김철수", age: 30, city: "서울" } }, // { json: { name: "이영희", age: 25, city: "부산" } } // ] const firstItemData = items[0].json; // { name: "김철수", age: 30, city: "서울" } console.log(firstItemData.name); // "김철수"
-
$node
: 현재 Code Node의 이름, 이전 노드의 이름 등 현재 노드 및 워크플로우 관련 정보에 접근할 수 있습니다. 고급 사용 시 유용합니다.예시: 현재 Code Node의 이름을 출력하고 싶을 때
console.log(`현재 노드 이름: ${$node.name}`);
-
$
: n8n의 전역 변수나 Credential(자격 증명)에 접근할 때 사용합니다. API 키 등을 안전하게 불러올 때 활용됩니다.예시:
myApiKey
라는 이름의 Credential을 사용하고 싶을 때// (n8n Credential에 'myApiKey'가 설정되어 있다고 가정) const apiKey = $('myApiKey'); console.log(`API 키: ${apiKey}`);
2. 출력 데이터 구조 이해하기 📤
Code Node는 항상 배열 형태의 객체를 반환해야 합니다. 각 객체는 입력 데이터와 마찬가지로 { json: { ... } }
구조를 가지는 것이 일반적입니다.
예시: 간단한 메시지를 출력하는 Code Node
return [{
json: {
message: "Code Node 실행이 성공적으로 완료되었습니다!",
timestamp: new Date().toISOString()
}
}];
만약 아무런 데이터를 다음 노드로 넘기지 않고 싶다면, 빈 배열 []
을 반환하면 됩니다.
3. 데이터 변환의 마법 (Map, Filter, Reduce) 🪄
입력 데이터를 원하는 형태로 가공하는 것은 Code Node의 핵심 기능입니다. JavaScript 배열 메서드인 map
, filter
, reduce
는 이럴 때 강력한 도구입니다.
-
map()
: 각 아이템을 변환하기 🔄map
은 배열의 각 요소를 순회하며 새로운 형태로 변환하여 새로운 배열을 반환합니다.예시: 각 사용자 데이터에
fullName
필드 추가하기// 입력: [{ json: { firstName: "John", lastName: "Doe" } }, { json: { firstName: "Jane", lastName: "Smith" } }] const transformedItems = items.map(item => ({ json: { ...item.json, // 기존 데이터를 유지하면서 fullName: `${item.json.firstName} ${item.json.lastName}` // 새로운 필드 추가 } })); return transformedItems; // 출력: [{ json: { firstName: "John", lastName: "Doe", fullName: "John Doe" } }, { json: { firstName: "Jane", lastName: "Smith", fullName: "Jane Smith" } }]
-
filter()
: 특정 조건에 맞는 아이템만 걸러내기 🧹filter
는 배열의 각 요소를 순회하며 특정 조건에 맞는 요소들만으로 새로운 배열을 만듭니다.예시: 나이가 30세 이상인 사용자만 필터링하기
// 입력: [{ json: { name: "Alice", age: 25 } }, { json: { name: "Bob", age: 35 } }, { json: { name: "Charlie", age: 40 } }] const filteredItems = items.filter(item => item.json.age >= 30); return filteredItems; // 출력: [{ json: { name: "Bob", age: 35 } }, { json: { name: "Charlie", age: 40 } }]
-
reduce()
: 배열의 모든 아이템을 하나의 결과로 압축하기 🗜️reduce
는 배열의 모든 요소를 순회하여 하나의 값(또는 객체)으로 축소합니다. 총합, 평균 계산, 데이터 그룹화 등에 유용합니다.예시: 모든 사용자의 나이 합계 구하기
// 입력: [{ json: { name: "Alice", age: 25 } }, { json: { name: "Bob", age: 35 } }] const totalAge = items.reduce((sum, item) => sum + item.json.age, 0); return [{ json: { totalAge: totalAge } }]; // 출력: [{ json: { totalAge: 60 } }]
4. 새 아이템 생성 및 추가 ➕
때로는 입력 데이터를 변환하는 것을 넘어, 완전히 새로운 데이터를 생성하여 다음 노드로 전달해야 할 때도 있습니다.
예시: 외부 API 호출 결과를 새로운 아이템으로 생성하기
const axios = require('axios'); // axios는 n8n Code Node에 내장되어 있습니다.
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/todos/1'); // 예시 API 호출
const newTodoItem = response.data;
return [{
json: newTodoItem // API 응답 데이터를 새로운 아이템으로 반환
}];
} catch (error) {
console.error("API 호출 중 오류 발생:", error.message);
// 오류 발생 시 빈 배열 또는 오류 메시지를 포함한 아이템 반환
return [{
json: {
error: "데이터를 불러오지 못했습니다.",
details: error.message
}
}];
}
주의: axios
와 같이 비동기 작업을 수행할 때는 async
함수 내에서 await
를 사용해야 합니다. Code Node 전체를 async
함수로 만들 필요는 없지만, await
를 사용하는 블록만 async
로 지정해주면 됩니다. 위 예시처럼 axios
를 사용할 때는 Code Node의 내용 자체가 비동기적으로 실행된다고 보면 됩니다.
5. 외부 라이브러리 활용 📦
n8n Code Node는 axios
, lodash
등 자주 사용되는 Node.js 라이브러리들을 기본적으로 내장하고 있습니다. 별도의 설치 과정 없이 require()
함수를 통해 바로 사용할 수 있습니다.
-
axios
: HTTP 요청을 보내는 데 사용되는 강력한 라이브러리입니다.const axios = require('axios'); const username = items[0].json.username; // 이전 노드에서 사용자 이름을 받았다고 가정 const githubApiUrl = `https://api.github.com/users/${username}`; try { const response = await axios.get(githubApiUrl); return [{ json: { githubData: response.data } }]; } catch (error) { console.error("GitHub API 호출 실패:", error.message); return [{ json: { error: "GitHub 사용자 정보를 가져오지 못했습니다." } }]; }
-
lodash
: 배열, 객체, 문자열 등을 다루는 데 유용한 유틸리티 함수들을 제공합니다.const _ = require('lodash'); // lodash는 '_'로 관례적으로 불러옵니다. // 복잡한 JSON 구조에서 특정 필드 안전하게 가져오기 const deepNestedValue = _.get(items[0].json, 'user.profile.details.email', 'Not Found'); return [{ json: { userEmail: deepNestedValue } }];
🐛 코드 노드 디버깅 꿀팁 대방출!
코딩은 디버깅의 연속이죠! Code Node도 예외는 아닙니다. 하지만 n8n은 코드를 쉽게 디버깅할 수 있는 강력한 도구들을 제공합니다.
1. console.log()
의 힘! 🐞
JavaScript에서 가장 기본적인 디버깅 도구입니다. 변수 값이나 코드 실행 흐름을 확인하는 데 필수적입니다.
- 사용법: 코드 중간에
console.log(변수명 또는 메시지);
를 삽입합니다. -
결과 확인: Code Node를 실행한 후, n8n 에디터 하단의 “실행 로그 (Execution Log)” 탭에서
console.log
로 출력된 내용을 확인할 수 있습니다.예시:
const inputData = items[0].json; console.log("입력 데이터:", inputData); // 입력 데이터 확인 let processedData = inputData.value * 10; console.log("처리된 데이터:", processedData); // 중간 처리 결과 확인 return [{ json: { result: processedData } }];
실행 로그에 “입력 데이터: { … }”와 “처리된 데이터: XX”가 출력될 것입니다.
2. 결과값 확인의 중요성 🔍
Code Node가 반환하는 데이터는 다음 노드로 전달되기 전에 Code Node 자체의 “Output” 탭에서도 확인할 수 있습니다.
- Code Node를 실행한 후, 노드 박스를 클릭하고 오른쪽 패널에서 “Output” 탭을 확인하세요.
- 여기에 Code Node가 최종적으로 반환한 데이터의 구조와 내용이 나타납니다.
return []
(빈 배열)을 반환하면 다음 노드로 아무것도 전달되지 않으므로, 의도한 동작인지 꼭 확인해야 합니다.
3. 오류 메시지 해독하기 🚨
빨간색 오류 메시지는 처음엔 무섭게 느껴질 수 있지만, 잘 읽어보면 문제 해결의 실마리가 됩니다.
- 오류 유형:
TypeError
,ReferenceError
,SyntaxError
등 다양한 오류가 있습니다.TypeError
: 정의되지 않은 속성에 접근하거나, 예상치 못한 타입의 값을 사용할 때 발생합니다. (items[0].json.undefinedProperty
같은 경우)ReferenceError
: 존재하지 않는 변수나 함수를 참조할 때 발생합니다. (myVariable
을 선언하지 않고 사용할 때)SyntaxError
: JavaScript 문법을 잘못 작성했을 때 발생합니다. (괄호나 따옴표가 짝이 안 맞을 때)
-
스택 트레이스 (Stack Trace): 오류 메시지 아래에 나타나는 여러 줄의 텍스트는 코드가 실행된 경로를 보여줍니다. 가장 위에 있는 줄이 실제 오류가 발생한 지점(파일, 줄 번호)을 알려줍니다.
예시: “Cannot read properties of undefined (reading ‘json’)” ->
items[0]
이undefined
인데, 그undefined
에서json
이라는 속성을 읽으려고 했다는 뜻입니다. 이는items
배열이 비어있거나, 첫 번째 아이템이 예상한 형태가 아닐 때 주로 발생합니다.console.log(items)
로items
의 실제 값을 확인해보세요.
4. 단계별 실행으로 문제 추적 👣
n8n의 “테스트 워크플로우” 기능을 활용하여 Code Node의 실행 흐름을 단계별로 추적할 수 있습니다.
- 워크플로우 에디터 상단의 “테스트 워크플로우 (Test Workflow)” 버튼을 클릭하여 실행합니다.
- 각 노드를 클릭하면 해당 노드의 입력(Input)과 출력(Output) 데이터를 실시간으로 확인할 수 있습니다.
- 특히 Code Node에서 문제가 발생했다면, Code Node의 Input 탭에서 어떤 데이터가 들어왔는지 확인하고, Output 탭에서 어떤 데이터가 나갔는지 (혹은 오류가 발생했는지) 확인하는 것이 중요합니다.
5. 짧게, 자주 테스트하기 ✅
긴 코드를 한 번에 작성하고 테스트하기보다는, 기능을 하나씩 추가하면서 짧게 짧게 테스트하는 것이 좋습니다. 작은 단위로 테스트하면 문제가 발생했을 때 어느 부분에서 오류가 났는지 빠르게 파악할 수 있습니다.
🎉 마치며
n8n Code Node는 여러분의 워크플로우를 무한한 가능성으로 확장시켜주는 강력한 도구입니다. 처음에는 어려워 보일 수 있지만, 기본적인 문법과 디버깅 팁을 잘 익힌다면 어떤 복잡한 자동화 시나리오도 문제없이 구현할 수 있을 것입니다.
이 글에서 다룬 내용들을 바탕으로 직접 코드를 작성하고 실행해보세요. 🛠️ 오류가 나더라도 좌절하지 마시고, console.log
와 실행 로그를 통해 원인을 파악하며 해결하는 과정을 즐겨보세요! 점점 더 능숙하게 Code Node를 다루게 될 것입니다.
궁금한 점이 있다면 n8n 커뮤니티나 공식 문서를 참고하는 것도 좋은 방법입니다. 여러분의 멋진 n8n 워크플로우 개발을 응원합니다! 🚀
Happy Automating! 🌟