[Javascript]JavaScript 이터러블과 이터레이터
JavaScript에서 데이터를 순회할 때 이터러블(iterable)과 이터레이터(iterator) 개념을 이해하는 것이 중요합니다. for...of, 스프레드 연산자(...), Array.from() 등이 이터러블 프로토콜을 기반으로 동작하기 때문입니다. 오늘은 이터러블과 이터레이터의 개념부터, 내부 동작 방식, 그리고 실전 예제까지 확실하게 이해해보겠습니다! 🔥
1️⃣ 이터러블(Iterable)과 이터레이터(Iterator)란?
✅ 이터러블(Iterable) 객체
이터러블 객체란 Symbol.iterator 메서드를 구현한 객체입니다. 즉, Symbol.iterator를 호출하면 이터레이터(Iterator) 객체를 반환해야 합니다.
const myIterable = {
data: ['A', 'B', 'C'],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.data.length) {
return { value: this.data[index++], done: false };
} else {
return { done: true };
}
}
};
}
};
📌 이터러블 객체(myIterable)는 Symbol.iterator를 구현했기 때문에 for...of, ... 연산자에서 사용할 수 있습니다.
✅ 이터레이터(Iterator) 객체
이터레이터는 .next() 메서드를 가지고 있으며, { value, done } 형식의 객체를 반환해야 합니다.
const iterator = myIterable[Symbol.iterator]();
console.log(iterator.next()); // { value: 'A', done: false }
console.log(iterator.next()); // { value: 'B', done: false }
console.log(iterator.next()); // { value: 'C', done: false }
console.log(iterator.next()); // { done: true } (순회 종료)
✔ 이터레이터는 내부적으로 .next()를 계속 호출하면서 데이터를 순차적으로 반환합니다. ✔ done: true가 되면 반복이 종료됩니다.
2️⃣ for...of 문과 이터러블 프로토콜
for...of 문은 내부적으로 이터러블 객체의 Symbol.iterator를 호출하여 이터레이터 객체를 얻고, .next()를 반복 실행하는 방식으로 동작합니다.
for (const value of myIterable) {
console.log(value);
}
// 출력: A, B, C
📌 for...of 문을 직접 구현하면?
const iterator = myIterable[Symbol.iterator]();
let result;
while (!(result = iterator.next()).done) {
console.log(result.value);
}
✅ for...of는 위 코드를 내부적으로 자동 실행해주는 문법적인 편의 기능입니다.
3️⃣ 스프레드 연산자 (...)의 동작 원리
...(스프레드 연산자)도 이터러블 프로토콜을 기반으로 동작하며, 내부적으로 Symbol.iterator()를 호출한 후 .next()를 반복 실행하여 배열을 생성합니다.
const spreadResult = [...myIterable];
console.log(spreadResult); // ['A', 'B', 'C']
📌 스프레드 연산자를 직접 구현하면?
const iterator = myIterable[Symbol.iterator]();
const spreadResult = [];
let result;
while (!(result = iterator.next()).done) {
spreadResult.push(result.value);
}
console.log(spreadResult); // ['A', 'B', 'C']
✅ ... 연산자는 내부적으로 for...of와 유사한 방식으로 동작하며, 최종적으로 배열을 반환합니다.
4️⃣ Array.from()과 스프레드 연산자의 차이
Array.from()도 이터러블 객체를 배열로 변환하는 역할을 하지만, 추가적인 기능이 있습니다.
기능 | Array.from() | ... (스프레드 연산자) |
내부 동작 방식 | Symbol.iterator 호출 후 .next() 반복 실행 | Symbol.iterator 호출 후 .next() 반복 실행 |
유사 배열 지원 | ✅ 지원 (length 속성 있는 객체 변환 가능) | ❌ 미지원 |
매핑 기능 | ✅ 지원 (Array.from(iterable, mapFn)) | ❌ 미지원 |
📌 Array.from() 예제
const set = new Set([1, 2, 3]);
console.log(Array.from(set)); // [1, 2, 3]
✅ Array.from()은 map()처럼 변환 기능도 제공합니다.
const doubled = Array.from(set, x => x * 2);
console.log(doubled); // [2, 4, 6]
🚀 즉, Array.from()은 ...보다 더 유연하며, 유사 배열도 처리할 수 있습니다.
5️⃣ 유사 배열(Array-like)란?
✅ 유사 배열은 index와 length 속성을 가진 객체이지만, Array의 메서드(map, push 등)는 사용할 수 없는 객체를 의미합니다.**
📌 유사 배열 예제
const arrayLike = { 0: 'x', 1: 'y', 2: 'z', length: 3 };
console.log(arrayLike[0]); // 'x'
console.log(arrayLike.length); // 3
✅ 유사 배열을 배열로 변환하려면 Array.from()을 사용해야 합니다.
console.log(Array.from(arrayLike)); // ['x', 'y', 'z']
❌ 스프레드 연산자로는 변환할 수 없습니다.
console.log([...arrayLike]); // ❌ TypeError: arrayLike is not iterable
📌 마무리 정리
✔ 이터러블(Iterable): Symbol.iterator를 구현한 객체.
✔ 이터레이터(Iterator): .next() 메서드를 통해 { value, done }을 반환하는 객체.
✔ for...of: Symbol.iterator()를 호출하고 .next()를 자동으로 반복 실행.
✔ 스프레드 연산자(...): 내부적으로 for...of와 동일한 방식으로 작동, 배열 반환.
✔ Array.from(): 이터러블 및 유사 배열 변환 가능, 매핑 기능 제공.
✔ 유사 배열(Array-like): index와 length 속성을 가진 객체로, Array.from()으로 배열 변환 가능.