개발공부/Javascript

[Javascript]JavaScript 이터러블과 이터레이터

Grapefruitgreentealoe 2025. 2. 12. 23:06
반응형

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()으로 배열 변환 가능.

 

반응형