본문 바로가기
Web Development/Design Patterns

[Design Patterns] 행위 패턴(Behavioral Patterns) | 반복자 (Iterator) 패턴

by Krystal K 2023. 12. 12.

행위 패턴(Behavioral Patterns) | 반복자 (Iterator) 패턴

[index]
1. 반복자 (Iterator) 패턴이란?
2. 반복자 (Iterator)  패턴의 장점
3. 반복자 (Iterator)  패턴의 단점
4. 반복자 (Iterator)  패턴 적용 예시
5. 마무리


+ 디자인 패턴이 무엇인지 모른다면?
https://reveur1996.tistory.com/149

[디자인 패턴] 디자인 패턴이란?

디자인 패턴이란? 1. 디자인 패턴이란? 2. 디자인 패턴 구조 3. 왜 디자인 패턴을 알아야할까? 4. 디자인 패턴에 대한 부정적인 시각 5. 디자인 패턴의 분류 6.마무리 1. 디자인 패턴이란? 패턴은 알

reveur1996.tistory.com

 

1. 반복자 (Iterator)  패턴이란?

반복자(Iterator) 패턴은 소프트웨어 디자인 패턴 중 하나로, 컬렉션(집합) 객체의 내부 구조를 노출하지 않고 순차적으로 접근할 수 있게 하는 패턴입니다. 이 패턴은 객체의 내부 표현 방식에 독립적으로 요소에 접근할 수 있도록 해주며, 반복 프로세스를 캡슐화하여 클라이언트 코드에서는 컬렉션의 구체적인 구현에 종속되지 않도록 합니다.
 
반복자 패턴을 사용하면 컬렉션의 내부 구조를 클라이언트로부터 숨기고, 클라이언트는 오직 반복자를 통해 요소에 접근할 수 있습니다. 이는 컬렉션의 구현이 변경되더라도 클라이언트 코드를 수정할 필요가 없게 만들어줍니다. 또한, 다양한 종류의 컬렉션에 동일한 반복 프로세스를 적용할 수 있게 해줘 코드의 재사용성을 높여줍니다.

 

반복자 (Iterator)  패턴의 구성 요소

  1. 반복자(Iterator)
    객체의 요소에 접근하고 순회하는 인터페이스를 정의합니다. 이 인터페이스에는 다음 요소로 이동하는 메서드와 현재 요소를 반환하는 메서드 등이 포함됩니다.

  2. 컬렉션(Iterable)
    요소의 집합을 나타내는 인터페이스를 정의합니다. 이 인터페이스는 컬렉션 내부의 반복자를 생성하는 메서드를 포함합니다.

 

반복자 (Iterator) 패턴의 활용

  • 컬렉션 탐색
    가장 일반적으로, 반복자 패턴은 컬렉션(리스트, 배열, 집합 등)을 효과적으로 탐색할 때 사용됩니다. 컬렉션의 내부 구조에 독립적으로 반복을 수행하고자 할 때 반복자를 활용하여 각 요소에 접근할 수 있습니다. 다양한 종류의 컬렉션을 사용하는데 있어 동일한 반복 프로세스를 사용하고자 할 때, 반복자 패턴을 적용하여 클라이언트 코드가 특정 컬렉션의 내부 구현에 종속되지 않도록 합니다.

  • 복합 객체 탐색
    복합 객체(Composite)에서 재귀적으로 구조를 탐색할 때 반복자 패턴을 사용할 수 있습니다. 예를 들어, 디렉토리와 파일로 이루어진 복합 객체에서 모든 파일을 순회하거나 특정 조건을 만족하는 파일을 찾을 때 유용합니다.

  • 역순 탐색
    일부 경우에는 역순으로 탐색해야 할 때가 있습니다. 반복자 패턴을 사용하면 컬렉션의 내부 구조를 변경하지 않고도 역순으로 반복할 수 있습니다.

  • 비동기적인 탐색
    비동기적인 상황에서도 반복자 패턴을 사용할 수 있습니다. 비동기적으로 데이터가 추가되고 제거되는 상황에서도 안정적으로 탐색을 수행할 수 있습니다.

 

2. 반복자 (Iterator)  패턴의 장점

  1. 컬렉션의 내부 구현과 분리
    반복자 패턴은 클라이언트 코드와 컬렉션의 내부 구현을 분리합니다. 이는 컬렉션의 구현이 변경되어도 클라이언트 코드를 수정할 필요가 없게 만들어줍니다. 새로운 컬렉션을 도입하거나 기존 컬렉션의 구현을 개선할 때 유연성을 제공합니다.

  2. 다양한 컬렉션에 대한 통일된 접근
    반복자 패턴을 사용하면 다양한 종류의 컬렉션에 대해 동일한 인터페이스를 사용할 수 있습니다. 클라이언트 코드는 특정 컬렉션의 구현과 상관없이 일관된 방식으로 데이터에 접근할 수 있습니다.

  3. 코드 재사용성
    반복자 패턴은 반복 로직을 분리하여 재사용 가능한 코드를 작성할 수 있게 해줍니다. 동일한 반복 로직을 여러 곳에서 사용하거나 수정 없이 새로운 컬렉션에 적용할 수 있습니다.

  4. 안정성과 예측 가능성
    반복자를 사용하면 컬렉션을 안전하게 탐색할 수 있습니다. 인덱스를 직접 다루는 대신 반복자를 통해 안전하게 순회하면서 예측 가능한 동작을 보장합니다.

  5. 역순 및 특별한 탐색 로직의 지원
    반복자 패턴은 역순 탐색이나 특별한 필터링을 적용하는 등의 다양한 탐색 로직을 지원합니다. 클라이언트 코드는 반복자를 통해 원하는 방식으로 데이터를 처리할 수 있습니다.

  6. 비동기적인 처리
    일부 반복자 구현에서는 비동기적으로 데이터를 처리할 수 있는 유연성을 제공합니다. 이는 비동기적인 환경에서도 데이터를 효과적으로 다룰 수 있게 해줍니다.

 

3. 반복자 (Iterator)  패턴의 단점

  1. 복잡성
    반복자 패턴을 구현하면서 추가적인 클래스와 인터페이스를 도입해야 합니다. 이로 인해 코드의 복잡성이 증가할 수 있습니다. 특히 단순한 반복이 필요한 간단한 상황에서는 이를 도입하는 것이 과하게 느껴질 수 있습니다.

  2. 성능
    일부 경우에는 반복자 패턴이 직접 인덱스를 사용하는 방식보다 성능이 떨어질 수 있습니다. 특히 매번 객체를 생성하는 등의 오버헤드가 발생할 수 있습니다. 성능이 중요한 상황에서는 신중한 사용이 필요합니다.

  3. 한정된 접근
    반복자 패턴은 순차적인 접근을 제공하는데, 일부 상황에서는 뒤로 이동하거나 임의의 위치에 바로 접근해야 하는 요구사항이 있을 수 있습니다. 반복자 패턴은 이러한 요구사항을 지원하기 어려울 수 있습니다.

  4. 콜렉션의 상태 변경
    반복자 패턴을 사용하여 컬렉션을 순회하는 동안 컬렉션의 상태가 변경되면 예측 불가능한 동작이 발생할 수 있습니다. 이를 방지하기 위해 컬렉션의 동기화에 주의해야 합니다.

  5. 언어 종속성
    어떤 언어나 환경에서는 반복자 패턴이 자연스럽게 구현되기도 하지만, 다른 환경에서는 추가적인 작업이 필요할 수 있습니다. 특히 일부 언어나 프레임워크에서는 반복자 패턴을 지원하지 않을 수 있습니다.

 

4. 반복자 (Iterator) 패턴 적용 예시

// 반복자 인터페이스 정의
class Iterator {
  constructor(collection) {
    this.collection = collection;
    this.index = 0;
  }

  hasNext() {
    return this.index < this.collection.length;
  }

  next() {
    return this.hasNext() ? this.collection[this.index++] : null;
  }
}

// 컬렉션 클래스 정의
class IterableCollection {
  constructor() {
    this.items = [];
  }

  addItem(item) {
    this.items.push(item);
  }

  // 반복자 생성 메서드
  createIterator() {
    return new Iterator(this.items);
  }
}

// 사용 예시
const collection = new IterableCollection();
collection.addItem("Item 1");
collection.addItem("Item 2");
collection.addItem("Item 3");

const iterator = collection.createIterator();

while (iterator.hasNext()) {
  console.log(iterator.next());
}

 
이 예시에서는 Iterator 클래스를 정의하여 컬렉션을 순회하는 역할을 수행합니다. IterableCollection 클래스는 컬렉션을 나타내며, createIterator 메서드를 통해 해당 컬렉션에 대한 반복자를 생성합니다.
마지막으로, 컬렉션을 만들고 반복자를 통해 순회하는 예시에서는 while 루프를 통해 모든 요소를 출력합니다. 이러한 구조를 통해 컬렉션과 반복 프로세스를 분리하고, 클라이언트 코드에서는 반복자를 통해 일관된 방식으로 컬렉션에 접근할 수 있습니다.

 

5. 마무리

반복자 패턴은 소프트웨어 디자인에서 유용한 도구로, 코드의 유연성과 유지보수성을 향상시킵니다. 이 패턴은 컬렉션의 내부 구조를 외부로부터 숨기고, 일관된 방식으로 컬렉션에 접근할 수 있도록 해주는데, 이로써 코드의 확장성이 향상되고 클라이언트 코드는 특정 컬렉션의 구현에 종속되지 않습니다. 반복자 패턴은 다양한 상황에서 활용될 수 있습니다. 컬렉션을 효과적으로 탐색하고 데이터에 접근할 수 있는 일관된 방법을 제공함으로써 코드를 간결하게 작성할 수 있습니다. 또한, 다양한 종류의 컬렉션에 대해 동일한 인터페이스를 제공하여 코드의 재사용성을 높이고, 유연성을 제공합니다.
 
그러나 반복자 패턴을 적용할 때에는 몇 가지 고려할 점이 있습니다. 코드의 복잡성이 증가할 수 있고, 성능 측면에서는 주의가 필요합니다. 또한, 특정한 요구사항에 따라 뒤로 이동이나 특정 위치로 바로 이동하는 등의 다양한 상황에 대한 대응이 제한될 수 있습니다.
 
종합적으로, 반복자 패턴은 코드의 일관성과 유연성을 높이는 데에 기여하며, 특히 컬렉션과 데이터의 관리가 중요한 소프트웨어 시스템에서 유용하게 활용될 수 있습니다. 따라서 프로젝트의 특성과 요구사항을 고려하여 적절하게 적용하는 것이 중요합니다.
 


참고문헌
https://robdodson.me/posts/javascript-design-patterns-iterator/
https://www.geeksforgeeks.org/iterator-method-javascript-design-pattern/
https://learnersbucket.com/examples/interview/iterator-design-pattern-in-javascript/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
https://betterprogramming.pub/understanding-the-iterator-pattern-in-javascript-typescript-using-symbol-iterator-ab400d46b14a
https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/ch12s05.html
https://www.dofactory.com/javascript/design-patterns/iterator

728x90