n8n 워크플로우에서 흔히 발생하는 JSON 파싱 에러는 대부분 외부 서비스와의 통신 문제입니다. 이 글은 SyntaxError: Unexpected token <, AI 응답 오류 등 4가지 주요 에러 해결 방법을 작성했습니다. n8n의 데이터 구조를 이해하고, Code 노드와 If 노드를 활용한 실전 디버깅 팁을 통해 복잡한 중첩 데이터까지 완벽하게 처리하는 방법으로 n8n 자동화를 구축할 수 있습니다.
목차
- 서론: n8n 워크플로우를 멈추게 하는 에러
- n8n에서 데이터가 흐르는 방식: 모든 것은
[{json: {...}}]이다 - 유형별 JSON 파싱 에러 진단 및 해결
- 복잡한 데이터 구조 처리 팁: 중첩과 배열
- 에러 없는 워크플로우 설계
- 결론: JSON 에러 해결
1. 서론: n8n 워크플로우를 멈추게 하는 에러
n8n으로 워크플로우 자동화를 구축하다 보면 워크플로우를 멈추게 하는 에러가 발생합니다. 이럴때에는 JSON 파싱 에러를 해결하는 방법이 필요합니다. 어제까지 잘 작동하던 워크플로우가 오늘 아침 SyntaxError: Unexpected token < 또는 Invalid JSON 같은 낯선 에러 메시지와 함께 멈춰버리는 상황, 정말 답답한 상황입니다.
하지만 이 에러는 n8n이 외부 서비스와 데이터를 주고받는 과정에서 필연적으로 발생하는 통신 문제입니다. 에러에 대한 원인을 정확히 진단하고 해결하여 n8n 데이터를 처리하는 방법을 알려드리겠습니다.
흔하게 겪는 JSON 에러 상황들
- HTTP Request 노드: 외부 API에서 데이터를 가져온 직후, 다음 노드로 데이터를 넘기는 과정에서 파싱 실패 에러가 발생합니다.
- AI 노드: ChatGPT나 Gemini 같은 AI 모델이 생성한 응답에 불필요한 텍스트가 포함되어 n8n이 JSON으로 인식하지 못합니다.
- 복잡한 데이터: 여러 겹으로 중첩된(nested) 데이터 구조 속에서 원하는 값을 정확히 꺼내지 못하게 됩니다.
위와 같은 JSON 파싱 에러의 4가지 주요 유형과 해결책을 알려드리겠습니다. 또한, n8n의 핵심 노드별 설정과 복잡한 데이터 구조 처리를 통해 2~3중으로 중첩된 데이터도 다루게 될 것입니다.
2. n8n에서 데이터가 흐르는 방식: 모든 것은 [{json: {...}}] 이다
JSON 에러를 해결하기 위해서는, n8n의 모든 노드가 정해진 규칙에 따라 데이터를 주고받는 것을 알아야합니다. 이 규칙의 핵심은 바로 [{json: {...}}] 구조입니다.
n8n 데이터 구조의 핵심 원리
n8n의 모든 데이터는 ‘아이템(Item)’이라는 단위의 배열(Array) 형태입니다. 각 아이템은 기본적으로 다음과 같은 모양을 합니다.
{json: {실제 데이터}, binary: {파일 데이터}}
우리가 주로 다루는 텍스트, 숫자 등의 데이터는 모두 json에 있습니다. 그래서 n8n의 Expression 에디터에서 {{$json.키이름}}과 같은 형태로 데이터에 접근하는 것입니다. 이는 ‘현재 아이템의 json 객체 안에 있는 특정 키의 값을 가져와라’라는 의미입니다. 더 자세한 내용은 n8n 공식 데이터 구조 문서에서 확인할 수 있습니다.
디버깅의 첫걸음: Input/Output 데이터 확인
문제 해결의 90%는 데이터의 ‘입력(Input)’과 ‘출력(Output)’을 직접 눈으로 확인하는 데서 시작합니다. 에러가 발생한 노드를 클릭하고, 우측 상단의 ‘Executions’ 탭에서 실패한 실행 기록을 선택하세요. 그 후 ‘Input’ 탭과 ‘Output’ 탭을 번갈아 눌러보면 데이터가 노드에 들어올 때와 나갈 때의 모습이 어떻게 다른지 명확하게 파악할 수 있습니다.
실무에서 중요한 JSON 타입 구분
JSON 안에서는 데이터의 타입이 매우 중요합니다. 특히 다음 두 가지 경우는 자주 문제를 일으키므로 꼭 기억해야 합니다.
| 구분 | String (문자열) | Number (숫자) | 설명 |
|---|---|---|---|
| 값 | "123" | 123 | 큰따옴표로 감싸여 있으면 문자열, 없으면 숫자입니다. API 응답이 문자열로 온 숫자를 모르고 계산에 사용하면 타입 에러가 발생합니다. |
| 빈 값 | null | undefined | "" (빈 문자열) | null은 ‘값이 의도적으로 비어있음’을, undefined는 ‘값이 정의되지 않음’을, ""는 ‘비어있는 문자열’을 의미합니다. If 노드에서 조건을 분기할 때 이 차이를 이해해야 정확한 로직을 짤 수 있습니다. |

3. 유형별 JSON 파싱 에러 진단 및 해결
이제 본격적으로 실제 마주치는 에러 유형별로 원인을 진단하고 해결하는 방법을 알아보겠습니다.
유형 1: SyntaxError: Unexpected token < in JSON at position 0
이 에러 메시지를 만났다면 99% 확률로 JSON이 아닌 HTML 코드를 받았기 때문입니다. < 문자는 HTML 태그의 시작을 의미하는데, n8n이 이것을 JSON으로 해석하려다 실패한 것입니다. 보통 API 서버가 정상적인 데이터 대신 ‘404 Not Found’나 ‘500 Internal Server Error’ 같은 HTML 에러 페이지를 반환했을 때 발생합니다.
- 1단계: 응답 형식 변경
HTTP Request 노드의 설정에서 Response Format을 ‘JSON’에서 ‘String’으로 변경합니다. 이렇게 하면 n8n이 응답을 그대로 문자열로 받아들입니다. - 2단계: 내용 확인
워크플로우를 다시 실행하여 ‘Output’ 탭에서 어떤 내용이 들어오는지 확인합니다. 아마도 우리가 흔히 보는 웹페이지의 HTML 코드가 보일 것입니다. - 3단계: 원인 해결
서버 에러가 원인이라면 API 요청 주소, 헤더, 파라미터가 올바른지 다시 확인하고 수정합니다. 만약 API는 정상이지만 특정 조건에서 HTML을 반환하는 경우라면, 이후 노드에서 해당 내용을 처리하는 별도의 로직을 추가해야 합니다.
유형 2: AI 응답이 유효한 JSON이 아닐 때 (Invalid JSON)
ChatGPT 같은 LLM(거대 언어 모델)은 항상 완벽한 JSON 형식만 생성하지는 않습니다. “결과는 다음과 같습니다:” 같은 친절한 설명이 붙거나, 코드 블록을 감싸는 마커(```json ... ```)가 포함되거나, JSON 문법에 맞지 않는 작은 실수들이 포함될 수 있습니다.
- 1단계: 프롬프트 수정
AI 노드에 보내는 프롬프트에 다음과 같은 제약 조건을 명확하게 추가하여 오류 가능성을 줄입니다.
Your output must be only a valid JSON object, without any extra text, explanations, or code block markers. - 2단계: Code 노드로 데이터 정제
AI 노드 바로 다음에 Code 노드를 추가하여, 어떤 응답이 오더라도 JSON 부분만 정확하게 추출하도록 만듭니다. 정규식(Regular Expression)을 사용하면 효과적입니다.
const text = $json.text;
// 중괄호로 시작하고 끝나는 JSON 부분을 찾습니다.
const match = text.match(/\{.*\}/s);
try {
// 찾은 JSON 문자열을 객체로 변환하여 반환합니다.
return JSON.parse(match[0]);
} catch (e) {
// 파싱에 실패하면 에러 정보와 원본 텍스트를 반환합니다.
return {error: "Failed to parse JSON", originalText: text};
}
유형 3: 빈 응답(Empty Response) 또는 null 값 처리 실패
API가 검색 결과가 없을 때 빈 문자열("")이나 null 값을 반환하는 경우가 있습니다. 후속 노드가 이 값을 JSON.parse() 하려고 시도하면 당연히 에러가 발생합니다.
- 방법 1: If 노드로 사전 검사
데이터를 사용하기 전에 If 노드를 배치하여 응답이 비어있지 않은지 먼저 확인합니다. Expression에{{$json.data != null && $json.data != ""}}와 같은 조건을 넣어주면null이거나 빈 문자열일 경우를 모두 걸러낼 수 있습니다. - 방법 2: 기본값(Fallback) 설정
Expression 안에서||연산자를 사용하여 값이 없을 경우 사용할 기본값을 설정할 수 있습니다. 예를 들어,{{$json.optionalField || "기본값"}}이라고 작성하면optionalField가 비어있을 때 “기본값”이라는 문자열을 대신 사용합니다.
유형 4: 이스케이프된 문자열(\") 처리 문제
JSON 데이터 안에 또 다른 JSON 형식의 문자열이 포함될 때가 있습니다. 이때 내부 문자열의 따옴표는 문법 오류를 막기 위해 \" 와 같이 이스케이프(escaped) 처리됩니다. 이 값을 다시 사용하려면 이스케이프를 해제하는 파싱 과정이 한 번 더 필요합니다.
- 해결책: 이중 파싱
이런 데이터는 Code 노드에서JSON.parse()를 두 번 실행하여 해결할 수 있습니다.
// 1. 외부 JSON 문자열을 파싱하여 내부 문자열에 접근합니다.
const outer = JSON.parse($json.body);
// 2. 이스케이프된 내부 JSON 문자열을 다시 파싱합니다.
const inner = JSON.parse(outer.escaped_json_string);
return inner;

4. 복잡한 데이터 구조 처리 팁: 중첩과 배열
단순한 에러 해결을 넘어, 여러 겹으로 싸인 복잡한 데이터를 자유자재로 다루는 것은 워크플로우 자동화의 수준을 한 단계 높여줍니다. 이 복잡한 데이터 구조 처리 팁 섹션에서는 중첩된 객체와 배열 데이터를 정복하는 실전 기술을 다룹니다.
중첩된 객체(Nested Object) 값에 접근하기
데이터가 여러 단계로 구성된 경우, 점(.)과 대괄호([])를 사용하여 원하는 값까지 차근차근 찾아 들어갈 수 있습니다.
- 예시 데이터:
{
"user": {
"id": 123,
"details": {
"name": "Alice",
"address": [
{ "type": "home", "city": "Seoul" }
]
}
}
}
- n8n Expression으로 접근:
위 데이터에서 ‘Seoul’이라는 값을 꺼내려면 다음과 같이 작성합니다.
{{$json.user.details.address[0].city}}
이는user객체 안의details객체, 그 안의address배열의 첫 번째([0]) 요소에 있는city키의 값을 의미합니다.
배열(Array) 데이터 반복 처리
배열 형태의 데이터를 다룰 때는 n8n이 제공하는 강력한 노드들을 활용할 수 있습니다.
| 노드 이름 | 주요 용도 | 사용 예시 |
|---|---|---|
| Item Lists | 배열의 각 요소를 별개의 아이템으로 분리하여 하나씩 처리 | 고객 목록 배열을 받아 각 고객을 CRM에 한 명씩 추가하기 |
| SplitInBatches | 대량의 데이터를 지정된 크기의 묶음으로 분할하여 처리 | 10,000명의 이메일 목록을 100개씩 묶어 API에 순차적으로 요청하기 |
데이터 구조 재구성(Transformation): Set 노드와 Code 노드
때로는 들어온 데이터를 그대로 사용하지 않고, 필요한 형태로 가공해야 합니다.
- Set 노드: 간단한 변환 작업에 최적화되어 있습니다. 필드 이름 변경, 여러 필드를 조합하여 새로운 필드 생성, 또는
{{parseInt($json.price_string)}}처럼 데이터 타입을 문자열에서 숫자로 바꾸는 등의 작업에 유용합니다. - Code 노드 (JavaScript): 여러 배열을 하나로 합치거나(flatMap), 특정 조건에 맞는 데이터만 걸러내고(filter), 전혀 다른 구조의 객체로 새롭게 만드는(map) 등 복잡한 변환이 필요할 때 사용합니다. JavaScript의 기본 배열 함수(MDN 문서 참고)를 활용하면 거의 모든 데이터 가공이 가능합니다.
여러 데이터 소스 병합: Merge 노드
두 개 이상의 데이터 흐름을 하나로 합쳐야 할 때 Merge 노드를 사용합니다.
- Append 모드: 두 데이터 소스를 단순히 순서대로 이어붙입니다.
- Merge By Key 모드: 데이터베이스의 JOIN 연산처럼, 두 데이터 소스에 공통으로 존재하는 키(예:
user_id)를 기준으로 데이터를 합쳐줍니다.
5. 에러 없는 워크플로우 설계
문제가 터진 뒤에 해결하는 것보다 좋은 것은 문제가 아예 발생하지 않도록 설계하는 것입니다. 몇 가지 방어적 코딩 원칙을 적용하면 워크플로우의 안정성을 크게 높일 수 있습니다.
- 외부 API는 믿지 않는다: HTTP Request 노드를 처음 설정할 때는 Response Format을 항상 ‘String’으로 두고, Continue On Fail 옵션을 활성화하세요. 이를 통해 예기치 않은 응답에도 워크플로우가 멈추지 않고, 어떤 데이터가 들어왔는지 직접 확인할 수 있습니다.
- 모든 가능성을 고려한다: 데이터가
null일 경우, 빈 배열일 경우, 예상과 다른 타입일 경우를 항상 대비해야 합니다. If 노드로 미리 조건을 검사하거나 Code 노드에서 예외 처리를 기본으로 추가하는 습관을 들이세요. - Try-Catch로 에러 핸들링: Code 노드에서
JSON.parse()처럼 실패 가능성이 있는 코드는 반드시try { ... } catch (error) { ... }블록으로 감싸주세요.catch블록에서는 에러 내용과 원본 데이터를 포함한 객체를 반환하여, 후속 노드에서 에러 발생을 인지하고 Slack 알림을 보내는 등의 대체 로직을 수행하도록 설계할 수 있습니다. - 재사용 가능한 서브-워크플로우 구축: AI 응답에서 JSON을 안전하게 추출하는 로직처럼 반복적으로 사용되는 작업은 별도의 서브-워크플로우로 만들어 두세요. ‘Execute Workflow’ 노드를 이용해 필요할 때마다 불러와 사용하면 관리 효율성이 극대화됩니다.

6. 결론: JSON 에러 해결
이 글을 통해 우리는 n8n에서 발생하는 JSON 파싱 에러의 다양한 원인과 해결책을 체계적으로 살펴보았습니다. 이제 에러가 발생하더라도 당황하지 않고 다음 3단계 진단법을 떠올리세요.
- 응답 포맷 확인: 내가 받은 것이 정말 JSON인가, 아니면 HTML인가?
- 데이터 타입 확인: 데이터가 이미 객체인데 또 파싱하려 하지는 않는가? 문자열인가, 객체인가?
- 문법 오류 확인: AI 응답처럼 불완전한 문법을 가지고 있지는 않은가?
이 가이드를 통해 당신은 더 이상 n8n의 JSON 에러를 두려워할 필요가 없습니다. 문제의 원인을 체계적으로 분석하고, n8n의 강력한 도구들을 활용해 어떤 복잡한 데이터 구조도 자신 있게 처리할 수 있게 되었습니다. 이제 이 지식을 바탕으로 더욱 견고하고 안정적인 자동화 워크플로우를 구축해 보세요.
이 글이 도움이 되셨다면, n8n 활용에 어려움을 겪는 동료에게 공유해주세요. 더 궁금한 점이나 다루었으면 하는 주제가 있다면 댓글로 알려주시면 감사하겠습니다.
[참고할 페이지] n8n 트리거 노드 문제 해결법
자주 묻는 질문 (FAQ)
Q1: HTTP Request 노드에서 `Unexpected token <` 에러가 계속 발생합니다. 가장 먼저 무엇을 확인해야 하나요?
A: HTTP Request 노드의 ‘Response Format’ 설정을 ‘JSON’에서 ‘String’으로 변경하여 실제 응답 내용을 확인하는 것이 가장 중요합니다. 대부분의 경우, API 서버가 정상적인 JSON 데이터 대신 HTML 에러 페이지(예: 404 Not Found)를 반환했기 때문입니다. 응답이 HTML인 것을 확인했다면 API 요청 주소나 파라미터가 올바른지 점검해야 합니다.
Q2: AI가 생성한 JSON에 불필요한 텍스트가 포함되어 파싱 에러가 납니다. 가장 효과적인 해결책은 무엇인가요?
A: 두 단계로 해결할 수 있습니다. 먼저, AI에게 보내는 프롬프트에 “오직 유효한 JSON 객체만 출력하고, 다른 설명이나 텍스트, 코드 블록 마커는 포함하지 마.” 와 같이 명확한 제약 조건을 추가하세요. 두 번째로, AI 노드 바로 다음에 Code 노드를 추가하여 정규식(Regular Expression)으로 응답에서 중괄호 `{…}`로 둘러싸인 JSON 부분만 정확히 추출하는 로직을 구현하면 안정성을 크게 높일 수 있습니다.
Q3: API가 때때로 빈 응답을 보내 워크플로우가 멈춥니다. 어떻게 방지할 수 있나요?
A: If 노드를 사용하여 후속 작업을 실행하기 전에 응답 데이터가 비어있지 않은지(`null` 또는 `””`가 아닌지) 먼저 검사하는 것이 좋은 방법입니다. 또는 HTTP Request 노드의 ‘Settings’ 탭에서 ‘Continue On Fail’ 옵션을 활성화하면, API 요청이 실패하거나 빈 응답을 받아도 워크플로우 전체가 멈추는 것을 방지하고 후속 노드에서 에러 처리를 할 수 있습니다.