일. 8월 17th, 2025

G: 안녕하세요, 자동화와 효율성에 목마른 여러분! 🚀 n8n은 코딩 없이도 복잡한 자동화 워크플로우를 구축할 수 있게 해주는 강력한 도구입니다. 하지만 때로는 n8n의 기본 노드만으로는 해결하기 어려운, 더 정교하고 맞춤화된 로직이 필요할 때가 있죠. 바로 이때, n8n 워크플로우의 ‘마법 지팡이’이자 ‘비밀 병기’인 Code Node가 등장합니다! ✨

Code Node는 n8n 워크플로우에 직접 JavaScript 코드를 삽입하여 실행할 수 있게 해주는 노드입니다. 이를 통해 데이터 변환, 복잡한 조건부 로직, 외부 라이브러리 연동 등 무궁무진한 가능성을 열 수 있습니다.

오늘은 이 강력한 Code Node를 활용하여 여러분의 워크플로우를 한 단계 더 업그레이드할 수 있는 실전 활용 예시 10가지를 자세히 살펴보겠습니다. 지금부터 함께 데이터 마법의 세계로 떠나볼까요? 🧙‍♂️


🌟 n8n Code Node는 무엇인가요?

n8n Code Node는 n8n 워크플로우 내에서 JavaScript 코드를 실행할 수 있는 특별한 노드입니다. n8n의 모든 데이터는 JSON(JavaScript Object Notation) 형식으로 처리되기 때문에, JavaScript를 사용하여 데이터를 자유롭게 조작하고, 새로운 데이터를 생성하며, 복잡한 비즈니스 로직을 구현할 수 있습니다.

Code Node를 사용해야 하는 이유:

  • 무한한 확장성: n8n에 내장된 노드만으로는 불가능한 거의 모든 작업을 구현할 수 있습니다.
  • 맞춤형 데이터 처리: 데이터를 특정 형식으로 변환하거나, 여러 소스의 데이터를 조합하는 등 정교한 데이터 조작이 가능합니다.
  • 복잡한 로직 구현: 단순한 IF 노드로는 처리하기 어려운 다중 조건, 반복 작업 등을 유연하게 처리할 수 있습니다.
  • 외부 라이브러리 연동 (고급): 필요에 따라 uuid, lodash 같은 외부 npm 패키지를 설치하여 활용할 수도 있습니다 (n8n 서버 설정 필요).
  • 디버깅 및 로깅: $node 객체를 통해 경고, 에러 메시지를 콘솔이나 n8n UI에 표시하여 디버깅에 도움을 받을 수 있습니다.

작동 방식:

Code Node는 입력으로 들어오는 데이터를 items라는 배열 형태로 받습니다. 각 itemjson 속성 안에 실제 데이터를 가지고 있습니다. 여러분은 이 items 배열을 JavaScript 코드로 조작한 후, 다시 items 배열 형태로 반환하면 됩니다.

  • 입력 데이터 접근: items[0].json.propertyName
  • 출력 데이터 반환: return items;

💡 n8n Code Node 실전 활용 예시 10가지

이제 Code Node의 강력함을 직접 느껴볼 시간입니다! 각 예시는 시나리오, 문제점, Code Node를 사용한 해결책, 그리고 간단한 코드 스니펫으로 구성됩니다.

1. 🔍 데이터 필터링 및 정제

가장 흔하게 사용되는 용도 중 하나입니다. 특정 조건을 만족하는 데이터만 걸러내거나, 불필요한 데이터를 제거할 때 유용합니다.

  • 시나리오: 온라인 쇼핑몰에서 발생한 주문 중, 결제 금액이 50,000원을 초과하는 주문만 다음 단계로 처리하고 싶습니다.
  • 문제점: 기본 IF 노드로는 단일 조건만 간단히 처리할 수 있지만, 복잡한 OR/AND 조건이나 동적인 필터링에는 한계가 있습니다.
  • Code Node 활용: JavaScript의 filter() 메서드를 사용하여 원하는 조건에 맞는 item만 걸러냅니다.
// 입력 데이터 예시:
// [
//   { "json": { "orderId": "ORD001", "amount": 35000, "status": "completed" } },
//   { "json": { "orderId": "ORD002", "amount": 62000, "status": "completed" } },
//   { "json": { "orderId": "ORD003", "amount": 50000, "status": "pending" } }
// ]

const filteredItems = items.filter(item => {
  // 금액이 50000원 초과 AND 상태가 'completed'인 주문만 필터링
  return item.json.amount > 50000 && item.json.status === 'completed';
});

return filteredItems;

// 출력 데이터 예시 (filteredItems):
// [
//   { "json": { "orderId": "ORD002", "amount": 62000, "status": "completed" } }
// ]

2. 🏗️ 데이터 구조 변경 (JSON Flattening/Reshaping)

복잡하게 중첩된 JSON 데이터를 평탄화하거나, 새로운 구조로 재편성해야 할 때 빛을 발합니다.

  • 시나리오: 외부 API에서 받은 고객 데이터가 user: { address: { street: '...', city: '...' } }와 같이 중첩되어 있습니다. 이를 city, street와 같은 최상위 속성으로 변경하고 싶습니다.
  • 문제점: Set 노드로는 중첩된 속성을 직접적으로 최상위로 가져오기 어렵거나, 여러 단계를 거쳐야 합니다.
  • Code Node 활용: map() 메서드를 사용하여 각 아이템의 구조를 원하는 대로 변경합니다.
// 입력 데이터 예시:
// [
//   { "json": { "id": 1, "name": "Alice", "contact": { "email": "alice@example.com", "phone": "123-4567" } } },
//   { "json": { "id": 2, "name": "Bob", "contact": { "email": "bob@example.com", "phone": "987-6543" } } }
// ]

const transformedItems = items.map(item => {
  const originalJson = item.json;
  return {
    json: {
      id: originalJson.id,
      name: originalJson.name,
      email: originalJson.contact.email, // 중첩된 contact.email을 최상위 email로
      phone: originalJson.contact.phone  // 중첩된 contact.phone을 최상위 phone으로
    }
  };
});

return transformedItems;

// 출력 데이터 예시 (transformedItems):
// [
//   { "json": { "id": 1, "name": "Alice", "email": "alice@example.com", "phone": "123-4567" } },
//   { "json": { "id": 2, "name": "Bob", "email": "bob@example.com", "phone": "987-6543" } }
// ]

3. 🚦 복잡한 조건부 로직 구현

여러 조건을 동시에 고려하거나, AND/OR 조합이 복잡하여 IF 노드 하나로 처리하기 어려울 때 유용합니다.

  • 시나리오: 고객의 구매 금액, 멤버십 등급, 최근 구매 이력을 종합하여 VIP 고객에게만 특별 할인 코드를 발급하고 싶습니다.
  • 문제점: 여러 IF 노드를 연결하면 워크플로우가 복잡해지고 가독성이 떨어집니다.
  • Code Node 활용: JavaScript의 if/else if/else 문을 사용하여 모든 조건을 한곳에서 처리합니다.
// 입력 데이터 예시:
// [
//   { "json": { "id": "C001", "totalPurchase": 1200, "membership": "Gold", "lastPurchaseDaysAgo": 10 } },
//   { "json": { "id": "C002", "totalPurchase": 800, "membership": "Silver", "lastPurchaseDaysAgo": 5 } }
// ]

const resultItems = items.map(item => {
  const customer = item.json;
  let discountCode = "NONE";

  if (customer.totalPurchase >= 1000 && customer.membership === "Gold" && customer.lastPurchaseDaysAgo = 500 && customer.membership === "Silver") {
    discountCode = "SILVER_10%"; // 실버 등급, 구매액 500 이상
  } else {
    discountCode = "WELCOME_5%"; // 그 외 일반 고객
  }

  // 기존 데이터에 discountCode 추가
  return {
    json: {
      ...customer,
      discountCode: discountCode
    }
  };
});

return resultItems;

4. ⏰ 날짜 및 시간 조작

날짜/시간 데이터를 특정 형식으로 변환하거나, 날짜 간의 차이를 계산하는 등 다양한 조작이 필요할 때 활용합니다.

  • 시나리오: 데이터베이스에서 timestamp 형식으로 받은 날짜를 YYYY-MM-DD HH:MM:SS 형식의 문자열로 변환하여 보고서에 포함하고 싶습니다.
  • 문제점: 기본 노드로는 날짜 형식 변환이 제한적이거나 복잡할 수 있습니다.
  • Code Node 활용: JavaScript의 Date 객체와 메서드를 사용하여 원하는 형식으로 날짜를 포맷합니다. (Moment.js와 같은 라이브러리를 사용하면 더욱 편리하지만, n8n 기본 환경에서는 Date 객체를 활용합니다.)
// 입력 데이터 예시:
// [
//   { "json": { "eventName": "Login", "timestamp": "2023-10-26T10:30:00.000Z" } },
//   { "json": { "eventName": "Logout", "timestamp": "2023-10-26T11:45:00.000Z" } }
// ]

const formattedItems = items.map(item => {
  const date = new Date(item.json.timestamp);

  // 날짜와 시간 구성
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0'); // 월은 0부터 시작하므로 +1
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');

  const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;

  return {
    json: {
      ...item.json,
      formattedTimestamp: formattedDate
    }
  };
});

return formattedItems;

// 출력 데이터 예시:
// [
//   { "json": { "eventName": "Login", "timestamp": "2023-10-26T10:30:00.000Z", "formattedTimestamp": "2023-10-26 10:30:00" } },
//   // ...
// ]

5. 🔠 문자열 조작 (정규표현식 포함)

텍스트에서 특정 패턴을 추출하거나, 문자열을 결합, 분리, 대체하는 등 복잡한 문자열 처리가 필요할 때 유용합니다.

  • 시나리오: 사용자 입력 텍스트에서 이메일 주소를 추출하거나, 특정 키워드를 다른 단어로 대체하고 싶습니다.
  • 문제점: 기본적인 문자열 함수만으로는 한계가 있으며, 정규표현식을 사용해야 할 때가 많습니다.
  • Code Node 활용: JavaScript의 String 메서드와 정규표현식(RegExp)을 사용하여 고급 문자열 조작을 수행합니다.
// 입력 데이터 예시:
// [
//   { "json": { "text": "문의사항은 support@example.com으로 보내주세요." } },
//   { "json": { "text": "긴급 연락처: admin@company.com 또는 ceo@company.com" } }
// ]

const processedItems = items.map(item => {
  const originalText = item.json.text;

  // 이메일 주소 추출 (정규표현식 사용)
  const emailRegex = /[\w.-]+@[\w.-]+\.\w+/g;
  const emails = originalText.match(emailRegex) || []; // 일치하는 모든 이메일 배열로 반환

  // 특정 키워드 대체
  const replacedText = originalText.replace(/문의사항/g, "궁금한 점");

  return {
    json: {
      originalText: originalText,
      extractedEmails: emails,
      modifiedText: replacedText
    }
  };
});

return processedItems;

// 출력 데이터 예시:
// [
//   { "json": { "originalText": "문의사항은 support@example.com으로 보내주세요.", "extractedEmails": ["support@example.com"], "modifiedText": "궁금한 점은 support@example.com으로 보내주세요." } },
//   // ...
// ]

6. 💫 동적 변수 생성 및 할당

워크플로우 내에서 고유 ID를 생성하거나, 현재 시간, 난수 등 동적인 값을 만들어 데이터에 추가해야 할 때 사용합니다.

  • 시나리오: 새로운 고객 등록 시, 고유한 고객 ID와 등록 시각을 자동으로 생성하여 데이터베이스에 저장하고 싶습니다.
  • 문제점: 기본 노드로는 복잡한 고유 ID 생성이나 여러 정보의 조합이 어렵습니다.
  • Code Node 활용: Date.now(), Math.random(), UUID 생성 로직 등을 사용하여 동적인 값을 생성합니다.
// 입력 데이터 예시:
// [
//   { "json": { "name": "Charlie", "email": "charlie@example.com" } }
// ]

const newItems = items.map(item => {
  const customer = item.json;

  // 간단한 고유 ID 생성 (실제 UUID는 외부 라이브러리 필요)
  const uniqueId = `CUST-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
  const creationDate = new Date().toISOString(); // ISO 8601 형식

  return {
    json: {
      ...customer,
      customerId: uniqueId,
      registeredAt: creationDate
    }
  };
});

return newItems;

// 출력 데이터 예시:
// [
//   { "json": { "name": "Charlie", "email": "charlie@example.com", "customerId": "CUST-1678888888888-123", "registeredAt": "2023-10-26T14:30:00.000Z" } }
// ]

7. 📊 배열 데이터 집계 (Aggregation)

여러 항목으로 구성된 배열 데이터에서 합계, 평균, 개수 등을 계산하여 요약 정보를 만들 때 매우 유용합니다.

  • 시나리오: 특정 주문에 포함된 여러 상품들의 총 가격을 계산하고 싶습니다.
  • 문제점: Item Lists 노드로는 합계, 평균 등의 계산이 제한적입니다.
  • Code Node 활용: reduce() 메서드를 사용하여 배열의 값을 집계합니다.
// 입력 데이터 예시:
// [
//   { "json": {
//     "orderId": "ORD001",
//     "products": [
//       { "name": "Laptop", "price": 1200, "quantity": 1 },
//       { "name": "Mouse", "price": 25, "quantity": 2 }
//     ]
//   } },
//   { "json": {
//     "orderId": "ORD002",
//     "products": [
//       { "name": "Keyboard", "price": 75, "quantity": 1 }
//     ]
//   } }
// ]

const aggregatedItems = items.map(item => {
  const order = item.json;

  // products 배열의 각 상품에 대해 (가격 * 수량)을 더하여 총합 계산
  const totalAmount = order.products.reduce((sum, product) => {
    return sum + (product.price * product.quantity);
  }, 0); // 초기 합계는 0

  return {
    json: {
      ...order,
      totalOrderAmount: totalAmount
    }
  };
});

return aggregatedItems;

// 출력 데이터 예시:
// [
//   { "json": { "orderId": "ORD001", "products": [...], "totalOrderAmount": 1250 } },
//   { "json": { "orderId": "ORD002", "products": [...], "totalOrderAmount": 75 } }
// ]

8. 🌐 맞춤형 API 요청/응답 처리

HTTP Request 노드만으로는 처리하기 어려운 복잡한 API 요청 바디 구성이나, 비정형적인 API 응답을 파싱해야 할 때 사용합니다.

  • 시나리오: 특정 API가 XML 형식의 요청을 받거나, 응답이 중첩된 문자열로 되어 있어 추가적인 파싱이 필요합니다.
  • 문제점: HTTP Request 노드의 설정으로는 한계가 있습니다.
  • Code Node 활용: XML을 파싱하는 라이브러리(Node.js 환경에 설치된 경우)를 사용하거나, JSON.parse()를 이용한 다중 파싱 등을 구현합니다. (이 예시에서는 간단한 JSON 문자열 파싱을 보여줍니다.)
// 입력 데이터 예시 (HTTP Request 노드의 응답이라고 가정):
// [
//   { "json": { "apiResponseString": "{ \"status\": \"success\", \"data\": { \"user_id\": 123, \"username\": \"johndoe\" } }" } }
// ]

const parsedItems = items.map(item => {
  const responseString = item.json.apiResponseString;
  let parsedData = {};

  try {
    // 문자열로 된 JSON 응답을 다시 파싱
    const jsonObject = JSON.parse(responseString);
    parsedData = jsonObject.data; // "data" 필드만 추출
    $node.warn('API 응답 파싱 성공!'); // 디버깅 메시지
  } catch (error) {
    $node.error(`API 응답 파싱 실패: ${error.message}`); // 에러 로깅
    parsedData = { error: "Failed to parse API response" };
  }

  return {
    json: {
      ...item.json,
      parsedApiResponse: parsedData
    }
  };
});

return parsedItems;

// 출력 데이터 예시:
// [
//   { "json": { "apiResponseString": "...", "parsedApiResponse": { "user_id": 123, "username": "johndoe" } } }
// ]

9. ✅ 데이터 유효성 검사

입력 데이터가 특정 조건을 만족하는지 (예: 필수 필드 누락 여부, 데이터 타입 일치 여부, 값 범위) 확인하고, 유효하지 않은 데이터를 걸러낼 때 사용합니다.

  • 시나리오: 사용자 등록 폼에서 받은 데이터에 emailpassword 필드가 모두 존재하는지, 그리고 이메일 형식이 유효한지 확인하고 싶습니다.
  • 문제점: 여러 IF 노드와 정규표현식 노드를 조합해야 하므로 복잡해집니다.
  • Code Node 활용: JavaScript의 조건문과 정규표현식을 사용하여 여러 유효성 검사 규칙을 한 번에 적용합니다.
// 입력 데이터 예시:
// [
//   { "json": { "name": "Alice", "email": "alice@example.com", "password": "pass" } },
//   { "json": { "name": "Bob", "email": "bob.com" } }, // 이메일 형식 오류, password 누락
//   { "json": { "name": "Charlie", "email": "charlie@valid.com" } }
// ]

const validatedItems = items.map(item => {
  const data = item.json;
  let isValid = true;
  let validationErrors = [];

  // 1. 필수 필드 확인
  if (!data.email) {
    isValid = false;
    validationErrors.push("Email field is missing.");
  }
  if (!data.password) {
    isValid = false;
    validationErrors.push("Password field is missing.");
  }

  // 2. 이메일 형식 확인 (간단한 정규표현식)
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (data.email && !emailRegex.test(data.email)) {
    isValid = false;
    validationErrors.push("Invalid email format.");
  }

  return {
    json: {
      ...data,
      isValid: isValid,
      validationErrors: validationErrors
    }
  };
});

return validatedItems;

// 출력 데이터 예시 (부분):
// [
//   { "json": { "name": "Alice", "email": "alice@example.com", "password": "pass", "isValid": true, "validationErrors": [] } },
//   { "json": { "name": "Bob", "email": "bob.com", "isValid": false, "validationErrors": ["Password field is missing.", "Invalid email format."] } }
// ]

10. 🚨 오류 처리 및 로깅

워크플로우 실행 중 발생할 수 있는 잠재적 오류를 감지하고, 이에 대한 맞춤형 메시지를 생성하거나 특정 에러 로직을 실행할 때 사용합니다.

  • 시나리오: 데이터를 처리하는 과정에서 특정 필드가 누락되어 예기치 않은 에러가 발생할 수 있습니다. 에러 발생 시 워크플로우를 중단하지 않고, 에러 정보를 기록하거나 후속 처리(예: 에러 알림 전송)를 하고 싶습니다.
  • 문제점: 기본 노드로는 try-catch와 같은 고급 오류 처리가 어렵습니다.
  • Code Node 활용: JavaScript의 try...catch 블록을 사용하여 안전하게 코드를 실행하고, 에러 발생 시 사용자 정의 액션을 수행합니다.
// 입력 데이터 예시:
// [
//   { "json": { "id": 1, "value": 10 } },
//   { "json": { "id": 2, "value": "invalid_number" } }, // 에러 유발 데이터
//   { "json": { "id": 3, "value": 20 } }
// ]

const processedItems = items.map(item => {
  try {
    const originalValue = item.json.value;
    const numericValue = parseInt(originalValue);

    if (isNaN(numericValue)) {
      throw new Error(`Value '${originalValue}' is not a valid number.`);
    }

    // 정상 처리 로직
    const doubledValue = numericValue * 2;
    return {
      json: {
        ...item.json,
        processedValue: doubledValue,
        status: "success"
      }
    };
  } catch (error) {
    // 에러 발생 시 처리
    $node.warn(`Error processing item ${item.json.id}: ${error.message}`); // n8n UI에 경고 표시
    return {
      json: {
        ...item.json,
        processedValue: null,
        status: "error",
        errorMessage: error.message
      }
    };
  }
});

return processedItems;

// 출력 데이터 예시 (부분):
// [
//   { "json": { "id": 1, "value": 10, "processedValue": 20, "status": "success" } },
//   { "json": { "id": 2, "value": "invalid_number", "processedValue": null, "status": "error", "errorMessage": "Value 'invalid_number' is not a valid number." } },
//   // ...
// ]

🚀 Code Node 활용 팁!

Code Node를 효율적으로 사용하기 위한 몇 가지 팁입니다.

  1. 점진적으로 테스트하세요: 복잡한 코드를 한 번에 작성하기보다, 작은 단위로 작성하고 console.log() 또는 $node.warn()을 사용하여 중간 결과를 확인하며 디버깅하는 것이 좋습니다.
  2. items 배열 이해: Code Node는 항상 items라는 배열을 입력으로 받고, 이 배열을 반환해야 합니다. 단일 데이터를 처리할 때는 items[0].json에 접근하고, 여러 데이터를 처리할 때는 items.map()이나 items.filter()를 활용하세요.
  3. 오류 처리: try...catch 블록을 사용하여 예외 상황을 처리하고, $node.error()$node.warn()으로 n8n UI에 로그를 남기세요.
  4. 가독성 유지: 코드가 복잡해질수록 주석을 달아 코드의 목적과 로직을 명확히 하는 것이 중요합니다.
  5. 대안 고려: 항상 Code Node가 최선의 선택은 아닙니다. 간단한 데이터 조작이나 조건 분기는 Expression, Set, IF, Merge Node 등 n8n의 기본 노드로도 충분할 수 있습니다. Code Node는 다른 노드로 해결하기 어려운 “마지막 보루”로 생각하세요.
  6. 성능 고려: 매우 큰 데이터셋을 Code Node로 처리할 경우 성능 문제가 발생할 수 있습니다. 가능한 경우, n8n의 빌트인 노드를 활용하는 것이 더 효율적일 수 있습니다.

🎉 마치며

n8n Code Node는 워크플로우 자동화에 있어 여러분에게 무한한 자유와 유연성을 제공합니다. 기본 노드의 한계를 넘어, 복잡하고 정교한 맞춤형 로직을 구현할 수 있게 해주는 진정한 ‘데이터 마법 지팡이’라고 할 수 있죠. 🧙‍♀️✨

오늘 살펴본 10가지 실전 예시를 통해 Code Node의 강력함을 느끼셨기를 바랍니다. 처음에는 어렵게 느껴질 수 있지만, 작은 코드부터 시작하여 점진적으로 익숙해지면 여러분의 n8n 워크플로우를 혁신적으로 변화시킬 수 있을 것입니다.

주저하지 말고 직접 Code Node를 추가하고, 여러분의 아이디어를 코드로 구현해보세요! 질문이 있다면 n8n 커뮤니티나 관련 자료를 찾아보면서 해결해나가는 과정 자체가 큰 배움이 될 것입니다.

자동화의 새로운 지평을 여는 여러분의 여정을 응원합니다! 🚀 다음 글에서 또 만나요!

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다