Get to know MDN better
This page was translated from English by the community. Learn more and join the MDN Web Docs community.
순회 프로토콜은 새로운 내장 객체 또는 구문이 아닌 프로토콜입니다. 이러한 프로토콜은 몇 가지 규칙에 따라 모든 객체에서 구현될 수 있습니다.
프로토콜은 순회 가능 프로토콜과 반복자 프로토콜로 두 가지가 있습니다.
순회 가능 프로토콜을 사용하면 JavaScript 객체를 for...of 구조에서 반복되는 값과 같은 순회 동작을 정의하거나 사용자 지정할 수 있습니다. Object와는 달리 Array 또는 Map과 같은 일부 내장 유형은 기본 순회 동작이 있는 내장 순회 가능 항목입니다.
순회 가능이 되기위해 객체는 반드시 @@iterator 메서드를 구현해야 합니다. 즉, 객체(또는 프로토타입 체인의 객체 중 하나)에 상수 Symbol.iterator를 통해 이용할 수 있는 @@iterator 키가 있는 속성이 있어야 합니다.
[Symbol.iterator]반복자 프로토콜을 준수하는 객체를 반환하는 인수가 없는 함수.
객체를 순회해야 할 때마다(예: for...of 루프 시작 시) @@iterator 메서드는 인수 전달 없이 호출되고, 반환된 반복자는 반복할 값을 가져오는 데 사용됩니다.
이 인수가 없는 함수는, 순회 가능 객체의 메서드로 호출됩니다. 따라서 함수 내에서 this 키워드를 사용하여 순회 가능 객체의 속성에 접근하고 순회 중에 제공할 항목을 결정할 수 있습니다.
이 함수는 평범한 함수이거나 제너레이터 함수일 수 있고, 호출 시 반복자 객체가 반환됩니다. 제너레이터 함수 내에서 각 항목은 yield를 사용하여 제공될 수 있습니다.
반복자 프로토콜은 유한하거나 무한한 일련의 값을 생성하는 표준 방법을 정의하고, 모든 값이 생성되었을 때 잠재적으로 반환 값을 정의합니다.
객체는 다음 의미 체계를 사용하여 next() 메서드를 구현할 때 반복자가 됩니다.
next()0개 또는 1개의 인수를 허용하고 IteratorResult 인터페이스(아래 참조)를 준수하는 객체를 반환하는 함수입니다. 내장 언어 기능(for...of 등)이 반복자를 사용할 때 객체가 아닌 값(false 또는 undefined 등)이 반환되면 TypeError ("iterator.next() returned a non-object value")가 발생합니다.
모든 반복자 프로토콜 메서드(next(), return(), 그리고 throw())는 IteratorResult 인터페이스를 구현하는 객체를 반환해야 합니다. 다음 속성이 반드시 있어야 합니다.
done Optional불리언 값으로, 반복자가 시퀀스에서 다음 값을 생성할 수 있는 경우엔 false입니다. (이는 done 속성을 지정하지 않는 것과 같습니다.)
반복자가 시퀀스를 완료한 경우에 이 값은 true입니다. 이때 value는 반복자의 반환 값을 선택적으로 지정합니다.
value Optional반복자가 반환하는 모든 JavaScript 값입니다. done이 true이면 생략할 수 있습니다.
실제로 두 속성이 모두 엄격하게 요구되진 않습니다. 속성이 없는 객체가 반환되면 사실상 { done: false, value: undefined }와 동일합니다.
반복자가 done: true로 결과를 반환하면 next()에 대한 모든 후속 호출도 done: true를 반환할 것으로 예상되지만 이는 언어 수준에서 강제되지 않습니다.
next 메서드는 메서드 본문에서 사용할 수 있는 값을 받을 수 있습니다. 내장 언어 기능은 어떠한 값도 전달하지 않습니다. 제너레이터의 next 메서드로 전달된 값은 해당 yield 표현식의 값이 됩니다.
반복자는 선택적으로 return(value)와 throw(exception) 메서드를 구현할 수 있습니다. 이 메서드는 호출될 때 호출자가 순회를 완료했으며, 필요한 정리(예: 데이터베이스 연결 닫기)를 수행할 수 있음을 반복자에게 알립니다.
return(value) Optional0개 또는 1개의 인수를 허용하고 IteratorResult 인터페이스를 준수하는 객체를 반환하는 함수입니다. 일반적으로 value는 전달된 vlaue와 같고 done은 true입니다. 이 메서드를 호출하면 반복자에게 호출자가 더 이상 next()를 호출을 할 의도가 없으며, 정리 작업을 수행할 수 있음을 알립니다.
throw(exception) Optional0개 또는 1개의 인수를 허용하고 IteratorResult 인터페이스를 준수하는 객체를 반환하는 함수입니다. 일반적으로 done은 true입니다. 이 메서드를 호출하면 반복자에게 호출자가 오류 조건을 감지했음을 알리며, exception은 일반적으로 Error 인스턴스입니다.
참고 : 특정 객체가 반복자 프로토콜을 구현하는지 여부를 반사적으로(즉, 실제로 next()를 호출하고 반환된 결과를 확인하지 않고는) 알 수 없습니다.
반복자를 순회 가능으로 만드는 것은 매우 쉽습니다. this를 반환하는 [@@iterator]() 메서드를 구현하기만 하면 됩니다.
이러한 객체를 순회 가능 반복자라고 합니다. 이렇게 하면 순회 가능을 기대하는 다양한 구문에서 반복자를 사용할 수 있습니다. 따라서 순회 가능을 구현하지 않고 반복자 프로토콜을 구현하는 것은 거의 유용하지 않습니다. (실제로 거의 모든 구문과 API는 반복자가 아니라 순회 가능을 기대합니다.) 제너레이터 객체가 그 예입니다.
모든 내장 반복자는 this를 반환하는 [@@iterator]() 메서드를 구현하는 Iterator.prototype에서 상속되었기 때문에 내장 반복자도 순회 가능입니다.
그러나 가능하다면 iterable[Symbol.iterator]가 Set.prototype[@@iterator]()처럼 항상 처음부터 시작하는 별개의 반복자를 반환하는 것이 좋습니다.
비동기 반복자와 비동기 순회 가능 프로토콜 이라는 비동기 순회에 사용되는 또 다른 프로토콜 쌍이 있습니다. 순회 가능과 반복자 프로토콜과 비교했을 때 매우 유사한 인터페이스를 가지고 있고, 반복자 메서드 호출의 각 반환 값이 프로미스로 래핑된다는 점만 다릅니다.
객체는 다음 메서드를 구현할 때 비동기 순회 가능 프로토콜을 구현합니다.
[Symbol.asyncIterator]비동기 반복자 프로토콜을 준수하는 객체를 반환하는 인수가 없는 함수입니다.
객체는 다음 메서드를 구현할 때 비동기 반복자 프로토콜을 구현합니다.
next()0개 또는 1개의 인수를 허용하고 프로미스를 반환하는 함수입니다. 프로미스는 IteratorResult 인터페이스를 준수하는 객체로 이행되며, 속성은 동기 반복자와 동일한 의미 체계를 갖습니다.
return(value) Optional0개 또는 1개의 인수를 허용하고 프로미스를 반환하는 함수입니다. 프로미스는 IteratorResult 인터페이스를 준수하는 객체로 이행되며, 속성은 동기 반복자와 동일한 의미 체계를 갖습니다.
throw(exception) Optional0개 또는 1개의 인수를 허용하고 프로미스를 반환하는 함수입니다. 프로미스는 IteratorResult 인터페이스를 준수하는 객체로 이행되며, 속성은 동기 반복자와 동일한 의미 체계를 갖습니다.
언어는 순회 가능과 반복자를 생성하거나 소비하는 API를 지정합니다.
String, Array, TypedArray, Map, Set, 그리고 Intl.Segmenter.prototype.segment()에서 반환된 Segments는 각각의 prototype 객체가 @@iterator 메서드를 구현하기 때문에 모두 내장 순회 가능입니다. 또한 인수 객체와 NodeList와 같은 일부 DOM 컬렉션 유형도 순회 가능입니다. ReadableStream은 이 문서를 작성할 당시의 유일한 내장 비동기 순회 가능입니다.
제너레이터 함수는 순회 가능 반복자인 제너레이터 객체를 반환합니다. 비동기 제너레이터 함수는 비동기 순회 가능 반복자인 비동기 제너레이터 객체를 반환합니다.
내장 순회 가능에서 반환된 반복자는 실제로 모두 앞서 언급한 [Symbol.iterator]() { return this; } 메서드를 사용하여 순회 가능 반복자로 만드는 공통 클래스(현재 노출되어있지 않음)를 상속받습니다. 앞으로 이러한 내장 반복자는 next() 메서드 외에 추가적으로 반복자 프로토콜에서 필요한 도우미 메서드를 가지고 있을 수 있습니다. 그래픽 콘솔에 로그하여 반복자의 프로토타입 체인을 검사해볼 수 있습니다.
console.log([][Symbol.iterator]()); Array Iterator {} [[Prototype]]: Array Iterator ==> 모든 배열 반복자가 공유하는 프로토타입입니다. next: ƒ next() Symbol(Symbol.toStringTag): "Array Iterator" [[Prototype]]: Object ==> 모든 내장 반복자가 공유하는 프로토타입입니다. Symbol(Symbol.iterator): ƒ [Symbol.iterator]() [[Prototype]]: Object ==> Object.prototype 입니다.순회 가능을 허용하는 많은 API가 있습니다. 몇 가지 예는 다음과 같습니다.
for...of 루프, 배열 및 매개변수 전개, yield*, 그리고 배열 구조 분해와 같은 일부 명령문과 표현식에는 순회 가능이 필요합니다.
내장 구문이 반복자를 순회하고 마지막 결과의 done이 false(즉, 반복자가 더 많은 값을 생성할 수 있음)이지만 더 이상 값이 필요하지 않은 경우 return 메서드가 있는경우, 해당 메서드가 호출됩니다. 예를 들어 break 또는 return이 for...of 루프에서 발생하거나 모든 식별자가 배열 구조 분해에 이미 바인딩된 경우에 이러한 상황이 발생할 수 있습니다.
비동기 제너레이터 함수 (동기 제너레이터 함수는 아님)의 for await...of 루프와 yield*는 비동기 순회 가능과 상호 작용하는 유일한 방법입니다. for...of, 배열 전개 등을 동기 순회 가능도 아닌 비동기 순회 가능과 사용하면(즉, [@@asyncIterator]()는 있지만 [@@iterator]()는 없음) TypeError(x is not iterable.)가 발생합니다.
순회 가능의 @@iterator 메서드가 반복자 객체를 반환하지 않으면 잘못 구성된 순회 가능으로 간주됩니다.
이렇게 사용하면 런타임 오류 또는 버그가 발생할 수 있습니다.
여러분은 다음과 같이 여러분만의 순회 가능을 만들 수 있습니다.
반복자는 본래 stateful입니다. 위의 예와 같이 제너레이터 함수로 정의하지 않으면, 여러분은 상태를 클로저에 캡슐화하고 싶을 것입니다.
상태 캡슐화는 프라이빗 속성으로도 수행할 수 있습니다.
예를 들어 String은 내장 순회 가능 객체입니다.
String의 기본 반복자는 다음과 같이 문자열의 코드 포인트를 하나씩 반환합니다.
여러분은 여러분만의 @@iterator를 제공하여 순회 동작을 재정의할 수 있습니다.
@@iterator 재정의가 순회 프로토콜을 사용하는 내장 생성 동작에 어떤 영향을 미치는지 확인해보세요.
| ECMAScript® 2027 Language Specification # sec-iteration |
This page was last modified on 2025년 7월 24일 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.