[JavaScript] 이터레이션(iteration)

이터레이션(iteration)이란?

이터레이션이란 어떠한 데이터 컬렉션을 순회하거나 반복하는 것을 의미하는데, 자바스크립트에는 for 루프, map(), filter() 등 이터레이션을 위한 다양한 내장 메서드들이 존재한다.

이터레이션 프로토콜(Iteration Protocol)

ES6에서 새롭게 추가된 이터레이션 프로토콜(iteration protocol)을 활용하면 사용자가 직접 이 프로토콜을 준수하는 객체를 만들어 for..of문 등으로 이터레이션의 핵심 매커니즘을 구현하여 사용이 가능하다. 이터레이션 프로토콜은 두 가지로 분류할 수 있다.

이터러블 프로토콜(Iterable Protocol)

이터러블 프로토콜을 준수한 객체는 이터러블(iterable)하다고 할 수 있으며, 이 객체는 for..of를 기반으로 어떤 값을 순회할지에 대해 정의 및 설정을 할 수 있다. 객체가 이터러블하려면 반드시 Symbol.iterator 메서드를 상속해야 하며, 자바스크립트에 내장된 이터러블로는 String, Array, TypedArray, Map, Set, 그리고 Intl.Segments 등이 있다.

const array = [1, 2, 3];

console.log(Symbol.iterator in array); // true

for (let i of array) {
  console.log(i);
} // 1 2 3

상술했듯이 Array는 이터러블 프로토콜을 준수하고 있기 때문에 Symbol.iterator 메서드를 소유하며, for..of 문으로 순회가 가능하다.

const obj = { a: 1, b: 2 };

console.log(Symbol.iterator in obj); // false

for (let i of obj) {
  console.log(i);
} // TypeError: obj is not iterable

일반 객체는 이터러블 프로토콜을 준수하고 있지 않기 때문에 Symbol.iterator 메서드를 소유하지 않으며, for..of문으로 순회가 불가능하다.

이터레이터 프로토콜(Iterator Protocol)

이터레이터 프로토콜은 연속적인 값들을 생성하기 위한 기준이 정의되어 있고 값의 생성이 완료되면 반환값을 갖게 되는 규칙을 의미한다. 이 프로토콜을 준수하는 객체는 next,return, throw 메서드를 통해 valuedone 속성을 갖는 객체(iterator result)를 반환할 수 있다.

const array = [1, 2, 3];

const iterator = array[Symbol.iterator]();

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2', done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

next 메서드를 호출할 때마다 이터러블을 순회하며 valuedone 속성을 반환하는 것을 확인할 수 있다.

이터레이션 프로토콜의 의의

만약 이터레이션 프로토콜이 존재하지 않고 Array, String, Map, DOM data structure(NodeList, HTMLCollection) 등 다양한 데이터 소스가 각자의 순회 방식을 갖는다면 사용자는 그 순회 방식을 모두 익혀야 하고 프로그램에 모두 적용해줘야 했을 것이다. 이러한 비효율을 해소해준 것이 이터레이션 프로토콜이다.

for..of 문

for..of문은 이터레이터 프로토콜을 준수하는 객체의 next 메서드를 호출하고, 호출로부터 반환된 value 값을 for..of 문의 변수에 할당한다. 이터레이터 리절트 값의 done 값이 false면 계속해서 순회하고, true면 순회를 중단한다.

const array = [1, 2, 3];

for (let item of array) {
  console.log(item);
} // 1 2 3

const string = "hello";

for (let letter of string) {
  console.log(letter);
} // 'h' 'e' 'l' 'l' 'o'

const map = new Map([
  ["a", "1"],
  ["b", "2"],
  ["c", "3"],
]);

for (let [key, value] of map) {
  console.log(key, value);
} // a, 1 b, 2 c, 3

이 코드는 내부적으로

const array = [1, 2, 3];

const iterator = array[Symbol.iterator]();

for (;;) {
  const res = iterator.next();

  if (res.done) break;

  console.log(res);
}

처럼 작동한다고 볼 수 있는 것이다.

참고: MDN - 반복기 및 생성기
참고: MDN - Iteration protocols
참고: PoiemaWeb

Categories:

Published: