반복자와 제너레이터

반복자와 제너레이터 (Iterators and Generators)

TypeScript에서 반복 가능한 객체를 다루는 방법과 함께, for..of문과 for..in문의 차이, 그리고 컴파일 목표에 따라 반복 코드가 어떻게 생성되는지를 설명하는 문서예요. 코드를 작성하면서 자연스럽게 익힐 수 있도록 정리할게요.

출처: TypeScript 핸드북

반복 가능한 객체 (Iterables)

객체가 반복 가능(iterable)하다는 것은, 그 객체에 Symbol.iterator 속성의 구현이 있다는 뜻이에요. Array, Map, Set, String, Int32Array, Uint32Array 같은 일부 내장 타입은 이미 Symbol.iterator 속성이 구현되어 있어요. 객체의 Symbol.iterator 함수는 반복할 값들의 목록을 반환하는 역할을 담당합니다.

Iterable 인터페이스

Iterable은 위에 나열한 것처럼 반복 가능한 타입들을 인자로 받고 싶을 때 사용할 수 있는 타입이에요. 예를 들면:

function toArray<X>(xs: Iterable<X>): X[] {
  return [...xs]
}

for..of

for..of는 반복 가능한 객체를 순회하면서, 그 객체의 Symbol.iterator 속성을 호출해요. 배열을 순회하는 간단한 for..of 루프를 볼게요:

let someArray = [1, "string", false];

for (let entry of someArray) {
  console.log(entry); // 1, "string", false
}

for..offor..in의 차이

for..offor..in은 둘 다 목록을 순회하지만, 순회하는 값이 서로 달라요. for..in은 순회 중인 객체의 키(key) 목록을 반환하고, for..of는 순회 중인 객체의 숫자 속성들의 값(value) 목록을 반환합니다.

이 차이를 보여주는 예시를 볼게요:

let list = [4, 5, 6];

for (let i in list) {
  console.log(i); // "0", "1", "2",
}

for (let i of list) {
  console.log(i); // 4, 5, 6
}

또 하나의 차이는, for..in이 어떤 객체에든 동작한다는 점이에요. 객체의 속성을 검사하는 용도로 쓰이죠. 반면 for..of는 반복 가능한 객체의 값에 주로 관심이 있어요. Map이나 Set 같은 내장 객체는 Symbol.iterator 속성을 구현하고 있어서 저장된 값에 접근할 수 있습니다.

let pets = new Set(["Cat", "Dog", "Hamster"]);
pets["species"] = "mammals";

for (let pet in pets) {
  console.log(pet); // "species"
}

for (let pet of pets) {
  console.log(pet); // "Cat", "Dog", "Hamster"
}

코드 생성 (Code generation)

ES5 대상 (Targeting ES5)

ES5 호환 엔진을 대상으로 할 때, 반복자는 Array 타입의 값에서만 허용돼요. Symbol.iterator 속성을 구현한 비-Array 값이라도, 그 값에 for..of 루프를 쓰는 것은 에러랍니다.

컴파일러는 for..of 루프에 대해 간단한 for 루프를 생성해요. 예를 들어:

let numbers = [1, 2, 3];
for (let num of numbers) {
  console.log(num);
}

이 코드는 다음과 같이 생성됩니다:

var numbers = [1, 2, 3];
for (var _i = 0; _i < numbers.length; _i++) {
  var num = numbers[_i];
  console.log(num);
}

ECMAScript 2015 이상 대상 (Targeting ECMAScript 2015 and higher)

ECMAScript 2015 호환 엔진을 대상으로 할 때, 컴파일러는 for..of 루프를 생성하면서 엔진에 내장된 반복자 구현을 사용합니다.

더 알아보기 (Learn more)