직접 만들고, 내 생각을 더하다
세상의 트렌드를 읽고 싶어하는 한 사람으로, 목공 DIY를 좋아하고, AI, n8n을 사용해 자동화 프로세스를 배우고 있다.

n8n 데이터 구조와 흐름 마스터: JSON부터 배열까지 - 초보자도 10분 만에 이해하는 기초 가이드 (n8n 기초 시리즈 6편)

n8n 데이터 구조와 JSON 처리를 완벽 마스터! 배열 분할부터 조건부 처리까지 실습으로 배우는 워크플로우 데이터 흐름 완전 가이드

 

n8n에서 {{$json.something}}이라는 문구를 보고 "이게 대체 뭐지?"라며 멍하니 화면을 바라본 경험이 있는가?

나도 처음 n8n을 시작했을 때 가장 당황스러웠던 부분이 바로 데이터 구조였다.
중괄호({})와 대괄호([])로 가득한 JSON을 보며 "이 암호 같은 걸 언제 다 이해하지?"라고 생각했던 기억이 생생하다.

하지만 지금 돌이켜보면, n8n 데이터 구조는 생각보다 훨씬 단순하고 체계적이다.
마치 러시아 인형처럼 큰 상자 안에 작은 상자들이 질서정연하게 들어있는 구조라고 보면 된다.

오늘은 JSON 데이터 처리부터 워크플로우 데이터 흐름까지, n8n에서 가장 중요하면서도 어려운 개념을 실전 경험을 바탕으로 쉽게 풀어보려고 한다.
이 글을 다 읽고 나면 여러분도 자신 있게 {{$json.email.subject}}를 입력할 수 있을 거라 확신한다!

🎯 n8n 데이터의 기본 개념: 아이템과 배열의 세계

n8n에서 데이터가 흐르는 방식

n8n에서 데이터 흐름을 이해하기 위해 먼저 핵심 개념 두 가지를 알아야 한다:

  1. 아이템(Item): 개별 데이터 단위 (예: 하나의 이메일, 하나의 행)
  2. 배열(Array): 여러 아이템들의 모음 (예: 여러 이메일들, 여러 행들)

물을 예로 들어보자.
아이템은 물방울 하나하나고, 배열은 물방울들이 모인 물줄기라고 생각하면 된다.
n8n 워크플로우에서는 이 물줄기가 노드와 노드 사이를 흘러다니며 각 노드에서 처리된다.

실제 화면에서 확인하는 방법

Gmail 노드에서 이메일을 3개 받았다고 가정해보자.
n8n 하단 실행 결과에서는 이렇게 보인다:

✅ Gmail: 3 items

이 "3 items"가 바로 3개의 아이템(이메일)이 배열로 묶여서 다음 노드로 전달된다는 의미다.

각 아이템을 클릭해보면 다음과 같은 JSON 구조를 볼 수 있다:

{
  "id": "18f2c3a4b5d6e7f8",
  "subject": "n8n 질문있습니다",
  "from": "user@example.com",
  "body": "안녕하세요, n8n 관련 질문이 있습니다...",
  "date": "2025-01-15T09:30:00Z"
}

📊 JSON 구조 완전 정복: 중괄호와 대괄호의 비밀

JSON의 세 가지 기본 형태

n8n JSON 가이드를 위해 JSON의 기본 구조부터 알아보자:

1. 객체 (Object) - 중괄호 {}

{
  "name": "홍길동",
  "age": 30,
  "city": "서울"
}

2. 배열 (Array) - 대괄호 []

[
  "사과",
  "바나나", 
  "오렌지"
]

3. 객체 배열 - 가장 흔한 형태

[
  {
    "name": "홍길동",
    "age": 30
  },
  {
    "name": "김철수", 
    "age": 25
  }
]

n8n에서 자주 보는 JSON 패턴들

실제로 n8n에서 작업하다 보면 이런 패턴들을 자주 만나게 된다:

Google Sheets에서 가져온 데이터:

{
  "이름": "김영희",
  "이메일": "younghee@example.com", 
  "부서": "마케팅",
  "입사일": "2024-03-15"
}

HTTP Request API 응답:

{
  "status": "success",
  "data": {
    "users": [
      {"id": 1, "name": "김철수"},
      {"id": 2, "name": "이영희"}
    ]
  },
  "meta": {
    "total": 2,
    "page": 1
  }
}

Expression 에디터 활용법

n8n에서 데이터 처리를 할 때 가장 중요한 도구가 Expression 에디터다.
= 키를 누르면 나타나는 이 편집기에서 데이터에 접근하는 방법을 알아보자.

기본 문법:

  • {{$json.필드명}}: 현재 아이템의 특정 필드 접근
  • {{$json["필드명"]}}: 공백이나 특수문자가 있는 필드명
  • {{$json.data.users}}: 중첩된 객체 접근
  • {{$json.data.users[0].name}}: 배열의 첫 번째 요소 접근

실전 예시:

Gmail에서 받은 이메일의 제목을 가져오려면:

{{$json.subject}}

Google Sheets에서 "이메일" 컬럼 값을 가져오려면:

{{$json["이메일"]}}

API 응답에서 첫 번째 사용자 이름을 가져오려면:

{{$json.data.users[0].name}}

🌊 데이터 흐름의 마법: 노드 간 데이터 전달 방식

단일 아이템 vs 다중 아이템 처리

n8n에서 가장 중요한 개념 중 하나가 바로 여러 아이템 처리 방식이다.

예시 상황: Google Sheets에서 5행을 가져온 경우

n8n의 동작 방식:

  • 기본적으로 n8n은 각 아이템을 개별적으로 처리한다
  • 5개 아이템이 있으면 다음 노드는 5번 실행된다
  • 각 실행에서는 하나의 아이템만 처리할 수 있다

모든 아이템을 한 번에 처리하는 방법:

Code 노드에서:

// 모든 아이템 가져오기
const allItems = $input.all();

// 모든 아이템 처리
return allItems.map(item => ({
  json: {
    name: item.json.name,
    email: item.json.email,
    processed: true
  }
}));

특정 아이템만 선택:

// 첫 번째 아이템만
const firstItem = $input.first();

// 마지막 아이템만  
const allItems = $input.all();
const lastItem = allItems[allItems.length - 1];

🛠️ 실습 프로젝트: 완성된 직원 데이터 처리 시스템

이론만으로는 아직 부족하다. 직접 손으로 만져봐야 진짜 이해가 된다! 완전히 작동하는 워크플로우를 만들어보자.

프로젝트 개요

목표: 직원 데이터를 나이별로 분류하고 개인화된 메시지 생성 + 최종 통계 리포트 작성

실습 프로젝트 n8n 워크플로우 이미지


워크플로우 구조

Manual Trigger → Set 노드 → Code 노드(분할) → IF 노드 → Code 노드(시니어/주니어) → Merge 노드 → Code 노드(리포트)

🔧 각 노드별 완성 코드

1️⃣ Manual Trigger

설정: 기본 설정 그대로 사용

2️⃣ Set 노드 - 사용자 데이터 생성

설정:

  • Mode: Raw JSON
  • JSON:
{
  "users": [
    {"name": "김철수", "email": "kim@example.com", "age": 30, "department": "개발팀"},
    {"name": "이영희", "email": "lee@example.com", "age": 25, "department": "마케팅팀"},
    {"name": "박민수", "email": "park@example.com", "age": 35, "department": "영업팀"},
    {"name": "최지은", "email": "choi@example.com", "age": 28, "department": "디자인팀"},
    {"name": "정우진", "email": "jung@example.com", "age": 32, "department": "개발팀"}
  ]
}

3️⃣ Code 노드 - 배열을 개별 아이템으로 분할

JavaScript Code:

const data = $input.first().json;
const users = data.users;
const results = [];

for (let i = 0; i < users.length; i++) {
  results.push({ json: users[i] });
}

return results;

역할: 1개의 아이템(users 배열)을 → 5개의 개별 아이템으로 분할

4️⃣ IF 노드 - 30세 이상 필터링

조건 설정:

  • Value 1: {{ $json.age }}
  • Operation: Larger Equal
  • Value 2: 30

5️⃣ Code 노드 - 시니어 직원 처리 (TRUE 경로)

JavaScript Code:

const allItems = $input.all();
const results = [];

for (const item of allItems) {
  const userData = item.json;
  
  results.push({
    json: {
      category: "시니어",
      name: userData.name,
      email: userData.email,
      age: userData.age,
      department: userData.department,
      greeting: "안녕하세요 " + userData.name + " 선배님! " + userData.department + "에서 좋은 성과 기대하겠습니다.",
      emailSubject: "[시니어] " + userData.name + "님께 중요 공지사항",
      priority: "high",
      experience: (userData.age - 22) + "년차",
      benefits: ["멘토링 자격", "선임 수당", "특별 휴가"]
    }
  });
}

return results;

6️⃣ Code 노드 - 주니어 직원 처리 (FALSE 경로)

JavaScript Code:

const allItems = $input.all();
const results = [];

for (const item of allItems) {
  const userData = item.json;
  
  results.push({
    json: {
      category: "주니어",
      name: userData.name,
      email: userData.email,
      age: userData.age,
      department: userData.department,
      greeting: "안녕하세요 " + userData.name + "님! " + userData.department + "에서 많은 것을 배워나가세요.",
      emailSubject: "[주니어] " + userData.name + "님 환영합니다",
      priority: "normal",
      experience: (userData.age - 22) + "년차",
      benefits: ["교육 프로그램", "멘토링 수혜", "성장 지원금"]
    }
  });
}

return results;

7️⃣ Merge 노드 - 두 경로 병합

설정: Mode를 Append로 설정 (기본값)

8️⃣ Code 노드 - 최종 리포트 생성

JavaScript Code:

const allItems = $input.all();

const stats = {
  total: allItems.length,
  senior: allItems.filter(item => item.json.category === "시니어").length,
  junior: allItems.filter(item => item.json.category === "주니어").length,
  departments: {}
};

allItems.forEach(item => {
  const dept = item.json.department;
  if (!stats.departments[dept]) {
    stats.departments[dept] = { total: 0, senior: 0, junior: 0 };
  }
  stats.departments[dept].total++;
  stats.departments[dept][item.json.category === "시니어" ? "senior" : "junior"]++;
});

return [
  {
    json: {
      type: "summary",
      timestamp: new Date().toISOString(),
      statistics: stats,
      message: "총 " + stats.total + "명의 직원 데이터를 처리했습니다. (시니어: " + stats.senior + "명, 주니어: " + stats.junior + "명)"
    }
  },
  ...allItems.map(item => ({
    json: {
      type: "individual",
      ...item.json,
      processedAt: new Date().toISOString()
    }
  }))
];

📊 실행 결과 - 완벽한 성공!

최종 출력 (6개 아이템):

  1. 요약 통계: 전체 직원 분석 데이터
  2. 개별 처리 결과: 5명의 직원별 상세 정보

요약 통계 예시:

{
  "type": "summary",
  "timestamp": "2025-07-17T03:19:28.691Z",
  "statistics": {
    "total": 5,
    "senior": 3,
    "junior": 2,
    "departments": {
      "개발팀": {"total": 2, "senior": 2, "junior": 0},
      "영업팀": {"total": 1, "senior": 1, "junior": 0},
      "마케팅팀": {"total": 1, "senior": 0, "junior": 1},
      "디자인팀": {"total": 1, "senior": 0, "junior": 1}
    }
  },
  "message": "총 5명의 직원 데이터를 처리했습니다. (시니어: 3명, 주니어: 2명)"
}

개별 처리 결과 예시:

{
  "type": "individual",
  "category": "시니어",
  "name": "김철수",
  "email": "kim@example.com",
  "age": 30,
  "department": "개발팀",
  "greeting": "안녕하세요 김철수 선배님! 개발팀에서 좋은 성과 기대하겠습니다.",
  "emailSubject": "[시니어] 김철수님께 중요 공지사항",
  "priority": "high",
  "experience": "8년차",
  "benefits": ["멘토링 자격", "선임 수당", "특별 휴가"],
  "processedAt": "2025-07-17T03:19:28.691Z"
}

🔧 실전 팁과 문제해결

자주 사용하는 데이터 접근 패턴

1. 안전한 필드 접근

// 존재하지 않는 필드에 안전하게 접근
const email = userData.email || "이메일 없음";
const phone = userData.phone ? userData.phone : "전화번호 없음";

2. 한글 필드명 처리

// 한글 필드명은 대괄호 표기법 사용
const name = $json["이름"];
const dept = $json["부서"];

3. 배열 데이터 처리

// 배열의 첫 번째 요소 가져오기
const firstSkill = userData.skills && userData.skills[0];

// 배열을 문자열로 변환
const skillsText = userData.skills ? userData.skills.join(", ") : "스킬 없음";

디버깅의 황금 팁들

1. 데이터 구조 확인

Code 노드에서 데이터 구조를 확인하고 싶을 때:

console.log('현재 데이터:', JSON.stringify($input.first().json, null, 2));
return $input.first().json;

2. JSON vs Table View 활용

  • JSON View: 정확한 데이터 구조 확인
  • Table View: 여러 아이템을 한눈에 비교
  • Schema View: 데이터 타입과 구조 파악

3. Expression 에디터의 자동완성

Expression 에디터에서 {{$json.까지 입력하면 사용 가능한 필드가 자동으로 나타난다.
이 기능을 적극 활용하자!

🚀 실행 방법

방법 1: 수동으로 노드별 생성 (학습 추천)

  1. 각 노드를 순서대로 추가
  2. 위의 설정 코드를 각 노드에 입력
  3. 노드들을 연결선으로 연결
  4. Execute Workflow 버튼으로 실행

방법 2: 빠른 체험 (JSON 가져오기)

위의 모든 설정이 포함된 완전한 워크플로우 JSON을 제공할 수 있다.
댓글로 요청하시면 바로 가져오기(Import) 할 수 있는 코드를 공유해드린다!

💡 학습 포인트 체크리스트

이 실습을 통해 배우게 되는 것들:

  • JSON 데이터 구조 이해와 활용
  • 배열 ↔ 개별 아이템 변환 방법
  • 조건부 데이터 처리 (IF 노드 활용)
  • Code 노드로 고급 데이터 변환
  • $input.all() vs $input.first() 차이점
  • 여러 경로 병합 (Merge 노드)
  • 통계 데이터 생성 (집계 함수 활용)
  • Expression 문법 실전 활용

🎯 마무리: 이제 여러분도 데이터 마스터!

오늘 우리가 함께 만든 워크플로우를 통해 n8n 데이터 구조와 흐름의 핵심을 완전히 이해하셨을 거라 확신한다.

기억하자.
처음에는 복잡해 보이는 중괄호와 대괄호들도 결국은 체계적인 패턴이 있다는 것을. 마치 새로운 언어를 배우는 것처럼, 처음에는 어색하지만 계속 사용하다 보면 자연스럽게 익숙해진다.

지금 당장 해볼 것:

  • 위의 실습 프로젝트 따라하기
  • 자주 사용하는 서비스(Gmail, Google Sheets 등)의 데이터 구조 살펴보기
  • Expression 에디터에서 {{$json.을 입력해보고 자동완성 확인하기
  • $input.all()$input.first()의 차이점 체험하기

다음 편에서는 트리거와 액션의 모든 것을 다루면서, 워크플로우를 언제 시작하고 어떻게 실행할지에 대한 완벽한 가이드를 준비하고 있다.
데이터 구조를 마스터했으니 이제 실제 자동화의 세계로 본격 진입할 차례다! 💪

댓글 쓰기