이터레이터 iterator 패턴 - 타입스크립트 예시
요약
이터레이터 iterator 패턴을 타입스크립트 코드와 함께 알아봅니다.
이터레이터 (Iterator) 패턴 요약
패턴 종류 | 핵심 키워드 |
---|---|
이터레이터 (Iterator) | 컬렉션의 내부 구조를 노출하지 않고 요소에 순차적으로 접근하는 방법을 제공 |

이터레이터 (Iterator) 패턴
이터레이터 패턴은 배열, 리스트, 트리 등과 같은 컬렉션(Collection) 객체의 내부 표현(구조)을 외부에 노출시키지 않고, 그 요소들을 순차적으로 접근할 수 있는 방법을 제공하는 패턴입니다.
가장 쉬운 비유는 'TV 리모컨의 채널 버튼' 입니다. 우리는 '다음' 버튼(▶)을 누르기만 하면 다음 채널로 넘어갑니다. 우리는 방송국 주파수 목록이 어떻게 저장되어 있는지, 어떤 자료구조로 관리되는지 전혀 알 필요가 없습니다. 이터레이터 패턴은 이처럼 컬렉션의 복잡한 내부를 숨기고, '다음 것(next)', '끝났는가(done)'와 같은 단순한 인터페이스만으로 데이터에 접근하게 해주는 역할을 합니다.
사실 현대 프로그래밍 언어에서는 이 패턴이 이미 깊숙이 내장되어 있습니다. 자바스크립트의 for...of
루프, 배열의 map
, filter
메서드, 자바의 Iterator
인터페이스 등이 모두 이터레이터 패턴의 구현체입니다.
기본 구조
- Iterator: 이터레이터의 공통 인터페이스입니다. 보통 다음 요소를 가져오는
next()
메서드와 순회가 끝났는지 확인하는hasNext()
(또는next()
의 반환값에done
속성을 포함) 메서드를 정의합니다. - ConcreteIterator:
Iterator
인터페이스를 구현한 구체적인 클래스입니다. 특정 컬렉션에 맞춰 순회 로직을 구현하며, 현재 순회 중인 위치를 추적합니다. - Aggregate: 이터레이터를 생성하는
createIterator()
메서드를 가지는 컬렉션의 공통 인터페이스입니다. - ConcreteAggregate:
Aggregate
인터페이스를 구현한 구체적인 컬렉션 클래스입니다.createIterator()
메서드 내에서 자신에게 맞는ConcreteIterator
의 인스턴스를 생성하여 반환합니다.
예시: 자바스크립트 이터러블 프로토콜 구현하기
자바스크립트/타입스크립트에서는 for...of
구문을 사용하기 위해 이터레이터 패턴을 직접 구현할 수 있습니다. [Symbol.iterator]
라는 특별한 메서드를 가진 객체를 '이터러블(iterable)'이라고 부릅니다.
알파벳 순서대로 단어를 순회하는 간단한 단어장(WordCollection
) 클래스를 만들어 보겠습니다.
// Aggregate 인터페이스 (참고용, TS에서는 구조적 타이핑으로 인해 명시적 구현 불필요)
// 제네릭 <T> :클래스나 인터페이스를 선언하는 시점에는 타입을 확정하지 않고, 실제로 사용하는 시점에 타입을 지정할 수 있게 해주는 문법
// 예 : Iterator<string>, Iterator<number> 등
interface Iterable<T> {
[Symbol.iterator](): Iterator<T>;
}
// Iterator 인터페이스 (참고용)
interface Iterator<T> {
next(): { value: T; done: boolean };
}
// ConcreteAggregate: 단어장 컬렉션
class WordCollection {
private words: string[] = [];
add(word: string): void {
this.words.push(word);
}
// 이터레이터 생성 메서드
[Symbol.iterator](): Iterator<string> {
let index = 0;
const sortedWords = [...this.words].sort(); // 알파벳 순으로 정렬
// ConcreteIterator 로직 (익명 객체로 구현)
return {
next: (): { value: string; done: boolean } => {
if (index < sortedWords.length) {
return {
value: sortedWords[index++],
done: false,
};
} else {
return {
value: undefined,
done: true,
};
}
},
};
}
}
// 클라이언트 코드
const collection = new WordCollection();
collection.add("TypeScript");
collection.add("GoF");
collection.add("Design Patterns");
collection.add("Iterator");
console.log("단어장을 순회합니다:");
// WordCollection은 이터러블 프로토콜을 따르므로 for...of 사용 가능
for (const word of collection) {
console.log(word);
}
// 출력:
// Design Patterns
// GoF
// Iterator
// TypeScript
클라이언트는 WordCollection
내부에서 단어들이 어떻게 words
배열에 저장되는지, 정렬이 어떻게 일어나는지 전혀 알 필요가 없습니다. 그저 for...of
라는 표준적인 방법으로 컬렉션의 요소에 하나씩 접근할 수 있습니다. 이것이 바로 이터레이터 패턴이 제공하는 '접근'과 '구현'의 분리입니다.
이터레이터 패턴 중요 키워드
- 컬렉션의 내부 구조를 노출하지 않고 요소에 순차적으로 접근합니다.
- 접근 방식과 컬렉션 구현을 분리하여 결합도를 낮춥니다.
- 하나의 컬렉션에 대해 다양한 순회 방식을 제공할 수 있습니다. (예: 정방향, 역방향 이터레이터)
for...of
,map
,filter
등 현대 언어의 많은 기능이 이 패턴을 기반으로 합니다.
정처기 실기 기출 문제
기출 | |
문제 | 컬렉션의 내부 구조를 노출하지 않고 요소에 순차적으로 접근하는 방법을 제공하는 패턴을 보기에서 고르시오 |
보기 | |
답변 | |
정답 | 정답 보기 |
기출 | |
문제 | Cursor 패턴이라고도 불리는 디자인 패턴을 보기에서 고르시오 |
보기 | |
답변 | |
정답 | 정답 보기 |