본문 바로가기
Thinking/Concept

이터레이터 패턴(Iterator Pattern) 이해하기

by Dev_카페인 2024. 11. 16.
반응형

이터레이터 패턴(Iterator Pattern) 이해하기

이터레이터 패턴컬렉션(Collection) 객체를 순차적으로 접근할 수 있는 방법을 제공하면서도, 컬렉션의 내부 구조를 노출하지 않는 행동 디자인 패턴입니다. 이 패턴을 사용하면 다양한 컬렉션을 일관된 방식으로 순회할 수 있어, 코드의 재사용성과 확장성을 높일 수 있습니다.

이번 포스트에서는 이터레이터 패턴의 개념, 구조, 구현 방법, 장단점, 사용 사례 등을 구체적인 예제와 함께 살펴보겠습니다.

이터레이터 패턴이란?

이터레이터 패턴은 컬렉션 객체의 요소를 순차적으로 접근하기 위한 표준화된 인터페이스를 제공합니다. 이 패턴은 컬렉션 객체를 직접 탐색하는 대신, 별도의 이터레이터 객체를 통해 요소를 순회하도록 설계됩니다.

주요 개념은 컬렉션 객체의 내부 구조를 노출하지 않고도, 각 요소에 접근할 수 있도록 하는 것입니다. 이를 통해 클라이언트는 컬렉션의 동작 방식이나 구조에 종속되지 않고도 컬렉션의 요소를 사용할 수 있습니다.

 

이터레이터 패턴의 구조

이터레이터 패턴은 다음과 같은 구성 요소로 이루어집니다.

  1. Iterator (인터페이스):
    • 컬렉션 요소를 순회하는 데 필요한 메서드(예: HasNext(), Next())를 정의합니다.
  2. ConcreteIterator (구체적인 이터레이터):
    • Iterator 인터페이스를 구현하여, 특정 컬렉션의 요소를 순회하는 기능을 제공합니다.
  3. Aggregate (집합체 인터페이스):
    • 이터레이터 객체를 생성하는 인터페이스를 정의합니다.
  4. ConcreteAggregate (구체적인 집합체):
    • Aggregate 인터페이스를 구현하며, 컬렉션 데이터를 관리하고 이터레이터 객체를 반환합니다.
  5. Client (클라이언트):
    • Iterator 객체를 사용하여 컬렉션의 요소를 순회합니다.

이터레이터(Iterator)

이터레이터 패턴의 구현 방법

예제 코드: 사용자 리스트 순회

사용자(User) 리스트를 컬렉션으로 구현하고, 이터레이터 패턴을 활용하여 리스트를 순회하는 예제를 살펴보겠습니다.

// Iterator 인터페이스
public interface IIterator<T>
{
    bool HasNext();
    T Next();
}

// ConcreteIterator 클래스
public class UserIterator : IIterator<string>
{
    private List<string> _users;
    private int _position = 0;

    public UserIterator(List<string> users)
    {
        _users = users;
    }

    public bool HasNext()
    {
        return _position < _users.Count;
    }

    public string Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more elements.");
        return _users[_position++];
    }
}

// Aggregate 인터페이스
public interface IAggregate<T>
{
    IIterator<T> CreateIterator();
}

// ConcreteAggregate 클래스
public class UserCollection : IAggregate<string>
{
    private List<string> _users = new List<string>();

    public void AddUser(string user)
    {
        _users.Add(user);
    }

    public IIterator<string> CreateIterator()
    {
        return new UserIterator(_users);
    }
}

// Client 코드
class Program
{
    static void Main()
    {
        // 사용자 컬렉션 생성
        UserCollection users = new UserCollection();
        users.AddUser("Alice");
        users.AddUser("Bob");
        users.AddUser("Charlie");

        // 이터레이터 생성
        IIterator<string> iterator = users.CreateIterator();

        // 컬렉션 순회
        Console.WriteLine("User List:");
        while (iterator.HasNext())
        {
            Console.WriteLine(iterator.Next());
        }
    }
}

실행 결과

User List:
Alice
Bob
Charlie

 

코드 설명

  1. Iterator:
    • IIterator<T> 인터페이스는 컬렉션의 요소를 순회하기 위한 HasNext()와 Next() 메서드를 정의합니다.
  2. ConcreteIterator:
    • UserIterator 클래스는 IIterator<T>를 구현하며, 리스트 요소를 순회하는 기능을 제공합니다.
  3. Aggregate:
    • IAggregate<T> 인터페이스는 컬렉션 객체가 이터레이터를 생성할 수 있도록 CreateIterator() 메서드를 정의합니다.
  4. ConcreteAggregate:
    • UserCollection 클래스는 사용자 데이터를 저장하고, CreateIterator() 메서드를 통해 UserIterator 객체를 반환합니다.
  5. Client:
    • 클라이언트는 UserCollection 객체를 통해 이터레이터를 생성하고, 이를 사용하여 컬렉션 요소를 순회합니다.

 

이터레이터 패턴의 장단점

장점

  1. 컬렉션 구조에 독립적:
    • 컬렉션의 내부 구조와 관계없이 동일한 방식으로 요소를 순회할 수 있습니다.
  2. 단일 책임 원칙 준수:
    • 순회 로직을 별도의 이터레이터 객체로 분리하여, 컬렉션 클래스와 순회 로직이 독립적으로 동작합니다.
  3. 유연한 순회:
    • 이터레이터 객체를 커스터마이즈하여 다양한 순회 방식(예: 역순, 특정 조건 기반 순회)을 구현할 수 있습니다.

단점

  1. 클래스 수 증가:
    • 컬렉션마다 별도의 이터레이터 클래스를 만들어야 하므로 클래스 수가 증가할 수 있습니다.
  2. 간단한 순회를 위한 오버헤드:
    • 단순한 순회 작업에 이터레이터를 추가하면 코드가 복잡해질 수 있습니다.

 

언제 이터레이터 패턴을 사용해야 할까?

이터레이터 패턴은 다음과 같은 상황에서 유용합니다.

  1. 컬렉션 요소를 일관되게 순회해야 할 때:
    • 배열, 리스트, 해시맵 등 다양한 컬렉션을 동일한 방식으로 순회해야 할 때.
  2. 컬렉션의 내부 구조를 숨기고 싶을 때:
    • 클라이언트가 컬렉션의 구체적인 구현을 몰라도, 요소를 순회할 수 있도록 할 때.
  3. 다양한 순회 방식이 필요한 경우:
    • 정방향, 역방향 또는 특정 조건에 따라 순회 방식을 변경해야 할 때.

 

이터레이터 패턴과 관련 패턴 비교

이터레이터 패턴은 컬렉션의 요소를 순회하기 위한 표준화된 방법을 제공합니다. 유사한 디자인 패턴과의 차이를 살펴보겠습니다.

  • 컴포지트 패턴:
    • 객체들을 트리 구조로 구성하여 계층적으로 처리할 때 사용됩니다. 컴포지트 패턴에서 이터레이터를 활용해 트리를 순회할 수 있습니다.
  • 책임 연쇄 패턴:
    • 요청을 처리할 객체를 체인 형태로 연결하는 패턴으로, 요청의 순회가 핵심입니다. 이터레이터 패턴은 컬렉션 순회가 중심입니다.
  • 컬렉션 프레임워크:
    • 대부분의 프로그래밍 언어에서 제공하는 컬렉션 프레임워크(예: C#의 IEnumerator, IEnumerable)는 이터레이터 패턴의 구현에 기반합니다.

 

실무에서 이터레이터 패턴 활용하기

이터레이터 패턴은 다음과 같은 실무 상황에서 활용됩니다.

  1. 컬렉션 순회 표준화:
    • 여러 유형의 컬렉션을 동일한 인터페이스로 순회해야 하는 경우(예: 데이터베이스 결과, 파일 시스템의 디렉토리 트리).
  2. 조건부 순회:
    • 특정 조건에 따라 컬렉션의 요소를 필터링하며 순회하는 기능을 구현할 때.
  3. UI 컴포넌트:
    • UI 요소(예: 버튼, 텍스트 박스)를 순차적으로 탐색하거나, 특정 상태의 요소만 선택하는 기능을 구현할 때.

 

마무리하며

이터레이터 패턴은 컬렉션의 내부 구조를 숨기면서도 일관된 방식으로 요소를 순회할 수 있도록 하는 유용한 디자인 패턴입니다. 이 패턴을 사용하면 코드의 재사용성과 확장성이 향상되며, 다양한 컬렉션 구조를 다룰 때 더욱 효과적으로 작업할 수 있습니다.

컬렉션 순회가 필요한 시스템을 설계할 때 이터레이터 패턴을 활용해보세요. 이를 통해 코드의 유지보수성과 가독성을 크게 향상시킬 수 있습니다.

반응형