x is not iterable — 원인·해결·예방
자바스크립트에서 for...of로 무언가를 돌리거나 전개 연산자(...)로 펼치다가 "TypeError: x is not iterable"이 뜨면, 순회하려는 대상이 이터러블(iterable)이 아니라는 뜻이다. 이터러블은 for...of·전개·구조 분해처럼 "하나씩 꺼내는" 동작을 지원하는 값인데, 일반 객체나 undefined 같은 값은 그 능력이 없다. 그래서 배열인 줄 알고 for...of를 돌렸는데 사실은 객체였거나, 데이터가 아직 안 와서 undefined였을 때 자주 난다. 콘솔에는 종종 "undefined is not iterable (cannot read properties of undefined (reading 'Symbol(Symbol.iterator)'))" 같은 긴 형태로 나오기도 한다(정확한 문구는 브라우저·버전마다 조금씩 다르다). 이 글은 이 에러의 의미, 무엇이 이터러블이고 아닌지, 그리고 객체 순회를 제대로 나누는 해결법을 정리한다.

이 글의 구성
🔎 에러 메시지의 의미
이 에러는 TypeError로, 이터러블이 아닌 값을 순회하려 할 때 발생한다. 자바스크립트에서 for...of, 전개 연산자(...), 배열 구조 분해([a, b] = x) 같은 동작은 "이터러블 규약"을 따르는 값에만 쓸 수 있다. 이터러블이란 내부에 Symbol.iterator라는 특별한 메서드를 가진 값으로, 그 메서드가 "요소를 하나씩 꺼내는 방법"을 정의한다. 이게 없는 값을 순회하려 하면 "이건 순회할 수 없다"며 막힌다.
메시지가 알려주는 단서가 있다. 그 순회 대상이 무엇이었는지다. "undefined is not iterable"이라면 대상이 undefined였다는 뜻이고, 뒤에 붙는 "cannot read ... Symbol(Symbol.iterator)"는 "그 값에서 순회 방법을 찾을 수 없었다"는 설명이다. 즉 순회하려던 값의 정체를 확인하는 게 첫걸음이다.
핵심 — 순회할 수 있는 값이 아니다
for...of·전개·구조 분해는 "하나씩 꺼내는" 동작이라, 그 능력(Symbol.iterator)을 가진 값에만 통한다. 배열·문자열·Map·Set은 이터러블이지만, 일반 객체·숫자·undefined·null은 아니다. 그래서 순회 대상이 정말 배열인지, 혹시 객체나 undefined는 아닌지부터 console.log로 확인한다.
⚖️ 이터러블 vs 아닌 것
이 에러를 이해하는 핵심은 "무엇이 순회 가능한 값인가"를 아는 것이다. 헷갈리는 대상을 표로 정리했다.
| 이터러블 (순회 O) | 이터러블 아님 (순회 X) |
|---|---|
| 배열 [1, 2, 3] | 일반 객체 { a: 1 } |
| 문자열 "abc" | 숫자 42 |
| Map · Set | undefined · null |
| NodeList · arguments · 제너레이터 | 유사 배열(Symbol.iterator 없는) |
가장 자주 걸리는 게 일반 객체다. 객체는 속성을 가지지만 "요소를 순서대로 꺼내는" 규약이 없어 for...of나 전개로 직접 순회할 수 없다. 배열처럼 생긴 유사 배열(예: length와 인덱스만 있는 객체)도 Symbol.iterator가 없으면 순회가 안 된다. 반대로 배열·문자열·Map·Set·NodeList는 이터러블이라 자유롭게 순회된다. 이 경계를 알면 "왜 이건 되고 저건 안 되나"가 정리된다.
🧩 자주 나오는 발생 원인 4가지
원인 1 — 일반 객체를 for...of로 순회
가장 흔하다. { a: 1, b: 2 } 같은 객체를 for...of로 돌리려 한 경우다. 객체는 이터러블이 아니라 막힌다. 객체 순회에는 for...of가 아니라 Object.keys·values·entries나 for...in을 써야 한다.
원인 2 — undefined·null을 전개·구조 분해
const [a, b] = undefined나 [...null]처럼 없는 값을 펼치거나 분해한 경우다. 데이터가 아직 안 왔거나 함수가 아무것도 반환하지 않아 undefined인 상태에서 자주 생긴다. 참고로 배열 전개([...null])·구조 분해는 막히지만, 객체 전개({...null})는 nullish를 그냥 무시해 에러가 나지 않는다.
원인 3 — API가 배열 아닌 객체를 반환
배열을 기대했는데 서버가 { data: [...] }처럼 객체로 감싸 준 경우다. 응답 전체를 for...of로 돌리면 막힌다. 실제 배열은 그 안의 data 속성이라, 그걸 꺼내 순회해야 한다.
원인 4 — Map·Set 생성자에 비이터러블 전달
new Map()·new Set()이나 Promise.all()에 이터러블이 아닌 값을 넘긴 경우다. 이 함수들은 인자로 이터러블을 기대하는데, 객체나 undefined를 주면 순회할 수 없어 같은 에러가 난다.
💻 재현과 진단
전형적인 재현이다. 일반 객체를 for...of로 순회하면 막힌다.
// 일반 객체를 for...of → 막힘
const user = { name: "김개발", age: 30 };
for (const v of user) { ... }
// ✗ TypeError: user is not iterable
// undefined 전개 → 막힘
const copy = [...user.tags]; // tags가 undefined면
// ✗ undefined is not iterable
진단은 순회 대상의 정체를 확인하는 것이다. console.log로 값을 찍고, Array.isArray로 배열인지 본다. 배열이 아니면 왜 아닌지(객체·undefined·API 구조)를 추적한다.
// ✓ 순회 전에 정체 확인
console.log(data, Array.isArray(data));
// 객체면 {...} false, 배열이면 [...] true
🛠 해결 — 객체 순회 나누기
핵심은 대상에 맞는 순회 방법을 쓰는 것이다. 배열은 for...of, 객체는 Object 메서드로 나눈다.
// ✓ 객체는 Object.entries 로 키·값 순회
const user = { name: "김개발", age: 30 };
for (const [key, value] of Object.entries(user)) {
console.log(key, value);
}
// ✓ 값만 필요하면 Object.values
for (const v of Object.values(user)) { ... }
Object.keys·values·entries는 객체를 배열로 바꿔 주므로, 그 결과는 이터러블이라 for...of로 순회된다. 상황별로 정리하면 이렇다.
상황별 해결 방법
데이터가 아직 안 왔을 수 있는 자리라면, 순회 전에 빈 배열을 기본값으로 보장하는 게 깔끔하다. (data || [])나 (data ?? [])로 감싸면 undefined일 때도 for...of가 그냥 0번 도는 것으로 지나가 에러가 안 난다.
// ✓ 기본값으로 빈 배열 보장
for (const item of (items ?? [])) {
console.log(item);
}
💬 자주 묻는 질문 5가지
Q1객체는 왜 for...of가 안 되나요?
일반 객체는 이터러블이 아니기 때문입니다. for...of는 Symbol.iterator를 가진 값(배열·문자열·Map·Set 등)만 순회할 수 있는데, 객체엔 그게 없죠. 객체는 Object.keys·values·entries로 배열을 얻어 순회하거나, 키만 필요하면 for...in을 쓰세요.
Q2for...in과 for...of는 뭐가 다른가요?
for...in은 객체의 키(속성 이름)를 순회하고, for...of는 이터러블의 값을 순회합니다. 객체엔 for...in, 배열·문자열·Map·Set엔 for...of가 어울립니다. 배열에 for...in을 쓰면 인덱스가 문자열로 나오는 등 예상 밖 동작이 있어 배열엔 for...of를 권합니다.
Q3API 응답을 도는데 나요.
응답이 배열이 아니라 객체로 감싸여 온 경우가 많습니다. { data: [...] } 형태라면 응답 전체가 아니라 res.data를 순회해야 합니다. console.log로 응답 구조를 확인하고, 실제 배열이 어느 속성인지 찾아 그걸 도세요. Array.isArray로 확인하면 확실합니다.
Q4undefined is not iterable은 뭔가요?
순회하려던 대상이 undefined였다는 뜻입니다. 데이터가 아직 안 왔거나, 없는 속성을 전개·구조 분해한 경우죠. 뒤에 붙는 Symbol(Symbol.iterator) 문구는 "그 값에서 순회 방법을 못 찾았다"는 설명입니다. 기본값(?? [])으로 빈 배열을 보장하면 막을 수 있습니다.
Q5유사 배열은 왜 안 되나요?
length와 인덱스는 있지만 Symbol.iterator가 없는 값(일부 유사 배열 객체)은 배열처럼 보여도 이터러블이 아닙니다. Array.from(x)나 전개가 가능한 경우엔 진짜 배열로 바꿔 순회하세요. 참고로 arguments나 NodeList는 이터러블이라 for...of가 됩니다.
📌 결론
"x is not iterable"은 for...of·전개·구조 분해로 순회하려는 대상이 이터러블이 아닐 때 나는 TypeError다. 배열·문자열·Map·Set은 순회되지만, 일반 객체·숫자·undefined·null은 안 된다. 그래서 순회 대상의 정체부터 확인하는 게 출발점이다.
실무 원칙은 다음과 같다.
🔁 순회 대상을 확인한다. console.log와 Array.isArray로 그 값이 배열인지, 객체·undefined는 아닌지 본다.
🧾 객체는 Object 메서드로 돈다. 객체 순회엔 for...of가 아니라 Object.keys·values·entries(배열 반환)나 for...in을 쓴다.
🛡 배열을 보장하고 방어한다. API 응답은 실제 배열 속성을 찾아 순회하고, undefined 가능성엔 기본값(?? [])으로 빈 배열을 보장한다.
not iterable 에러 체크리스트
본 글은 자바스크립트 TypeError(not iterable)의 일반적 원인과 해결 방법을 정리한 자료다. 코드 수정은 영향 범위를 확인한 뒤 신중히 적용한다.
#JavaScript #TypeError #notiterable #이터러블 #자바스크립트에러 #forof #forin #전개연산자 #구조분해 #Objectentries #Arrayfrom #Symboliterator #프론트엔드 #JS디버깅 #웹개발
'IT' 카테고리의 다른 글
| Cannot convert undefined or null to object — 원인·해결·예방 (0) | 2026.07.02 |
|---|---|
| Cannot access 'x' before initialization — TDZ 원인·해결·예방 (0) | 2026.07.02 |
| Unexpected token < in JSON — HTML 응답을 JSON으로 파싱할 때 원인·해결 (0) | 2026.07.01 |
| Assignment to constant variable — const 재할당 원인·해결·예방 (0) | 2026.07.01 |
| Unexpected end of JSON input — JSON.parse 원인·해결·예방 (1) | 2026.07.01 |
댓글