Iterator
이터레이터
컬렉션 요소를 순회하는 객체. for 루프의 기반.
이터레이터
컬렉션 요소를 순회하는 객체. for 루프의 기반.
Iterator(이터레이터)는 컬렉션의 요소들을 하나씩 순차적으로 접근할 수 있게 해주는 객체입니다. 배열, Set, Map 등 다양한 자료구조의 내부 구현을 몰라도 일관된 방식으로 요소를 순회할 수 있게 해주며, 이를 통해 데이터 구조와 알고리즘을 분리하는 디자인 패턴의 핵심이 됩니다.
JavaScript에서 이터레이터는 `next()` 메서드를 가진 객체로, 호출할 때마다 `{ value, done }` 형태의 결과를 반환합니다. value는 현재 요소의 값이고, done은 순회가 끝났는지를 나타내는 불리언 값입니다. 이 프로토콜을 따르는 객체는 `for...of` 루프에서 자동으로 사용될 수 있습니다.
Python에서는 `__iter__()`와 `__next__()` 매직 메서드로 이터레이터를 구현합니다. Java에서는 `Iterator` 인터페이스의 `hasNext()`와 `next()` 메서드를 사용합니다. 언어마다 문법은 다르지만 "현재 요소 반환 + 다음으로 이동"이라는 핵심 개념은 동일합니다.
실무에서 이터레이터는 대용량 데이터 처리, 지연 평가(Lazy Evaluation), 무한 시퀀스 생성 등에 활용됩니다. 제너레이터(Generator)와 함께 사용하면 메모리 효율적인 데이터 파이프라인을 구축할 수 있어, 스트림 처리나 페이지네이션 구현에 특히 유용합니다.
// 1. 기본 이터레이터 사용법
const numbers = [10, 20, 30];
const iterator = numbers[Symbol.iterator]();
console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
// 2. for...of 루프 (내부적으로 이터레이터 사용)
const fruits = ['사과', '바나나', '딸기'];
for (const fruit of fruits) {
console.log(fruit); // 사과, 바나나, 딸기 순서대로 출력
}
// 3. 커스텀 이터레이터 구현 - Range 객체
class Range {
constructor(start, end, step = 1) {
this.start = start;
this.end = end;
this.step = step;
}
[Symbol.iterator]() {
let current = this.start;
const end = this.end;
const step = this.step;
return {
next() {
if (current <= end) {
const value = current;
current += step;
return { value, done: false };
}
return { value: undefined, done: true };
}
};
}
}
// 사용 예시
const range = new Range(1, 5);
console.log([...range]); // [1, 2, 3, 4, 5]
for (const num of new Range(0, 10, 2)) {
console.log(num); // 0, 2, 4, 6, 8, 10
}
// 4. 제너레이터로 이터레이터 쉽게 만들기
function* fibonacci(limit) {
let [prev, curr] = [0, 1];
while (curr <= limit) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
console.log([...fibonacci(100)]);
// [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
// 5. Map과 Set의 이터레이터
const userMap = new Map([
['alice', { age: 25 }],
['bob', { age: 30 }]
]);
for (const [name, info] of userMap) {
console.log(`${name}: ${info.age}세`);
}
"대용량 CSV 파일을 처리할 때 전체를 메모리에 올리면 OOM이 발생합니다. 이터레이터 패턴으로 한 줄씩 읽어서 처리하면 메모리 사용량을 일정하게 유지할 수 있어요."
"JavaScript의 이터러블 프로토콜은 Symbol.iterator 메서드를 구현하면 됩니다. 이 메서드가 next()를 가진 이터레이터 객체를 반환하면, for...of나 스프레드 연산자에서 자동으로 순회가 가능합니다."
"여기 for...in 대신 for...of를 사용하세요. for...in은 객체의 열거 가능한 속성을 순회하고, for...of는 이터러블의 값을 순회합니다. 배열에 for...in을 쓰면 인덱스가 문자열로 나와서 버그가 생길 수 있어요."
이터레이터는 한 번 순회하면 재사용할 수 없습니다. 다시 순회하려면 새 이터레이터를 생성해야 합니다. `[...iterator]`로 소진된 이터레이터를 다시 펼치면 빈 배열이 됩니다.
`for...in`은 객체의 키(속성명)를 순회하고, `for...of`는 이터러블의 값을 순회합니다. 배열에 `for...in`을 사용하면 인덱스가 문자열로 반환되어 의도치 않은 버그가 발생할 수 있습니다.
커스텀 이터레이터를 직접 구현하는 것보다 제너레이터 함수(function*)를 사용하면 yield 키워드로 훨씬 간결하게 이터레이터를 만들 수 있습니다. 상태 관리도 자동으로 처리됩니다.