본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 메모리 효율을 극대화하는 제너레이터와 이터레이터의 3가지 핵심 프로토콜 차이와 활용 방법

by Papa Martino V 2026. 3. 2.
728x90

이터레이터(Iterator)와 제너레이터(Generator)
이터레이터(Iterator) 와  제너레이터(Generator)

 

파이썬 프로그래밍에서 대용량 데이터를 다룰 때 가장 먼저 마주하게 되는 벽은 바로 '메모리 관리'입니다. 수백만 개의 데이터를 리스트에 담아 처리하려고 하면 시스템 메모리가 순식간에 고갈되는 현상을 겪게 됩니다. 이러한 문제를 해결하기 위한 파이썬의 핵심 메커니즘이 바로 이터레이터(Iterator)제너레이터(Generator)입니다. 많은 개발자가 이 두 개념을 혼용하여 사용하지만, 내부 구현 방식과 프로토콜(Protocol) 측면에서는 명확한 차이가 존재합니다. 본 글에서는 전문가의 시선에서 이 두 객체의 구조적 차이를 심층 분석하고, 실무에서 성능을 최적화할 수 있는 구체적인 가이드를 제공합니다.


1. 이터레이션 프로토콜(Iteration Protocol)의 이해

파이썬에서 '반복 가능한' 객체를 만들기 위해서는 특정한 약속, 즉 프로토콜을 준수해야 합니다. 이는 클래스 내부에 특정 매직 메서드(Magic Method)를 구현하는 것을 의미합니다.

이터러블(Iterable) vs 이터레이터(Iterator)

  • Iterable: __iter__() 메서드를 구현하여 이터레이터를 반환할 수 있는 객체 (예: list, set, dict, str)
  • Iterator: __next__() 메서드를 구현하여 데이터에 순차적으로 접근하고, 데이터 소진 시 StopIteration 예외를 발생시키는 객체

모든 이터레이터는 이터러블이지만, 모든 이터러블이 이터레이터인 것은 아닙니다. 이터레이터는 현재의 상태(State)를 기억하고 있다는 점이 핵심입니다.


2. 제너레이터(Generator): 이터레이터를 만드는 우아한 방법

제너레이터는 이터레이터를 생성하는 가장 쉽고 세련된 방법입니다. 일반적인 함수와 유사하지만 return 대신 yield 키워드를 사용한다는 점이 다릅니다. yield가 호출되면 함수의 실행 상태가 일시 정지되며, 값이 호출자에게 반환됩니다. 이후 다시 호출되면 정지된 지점부터 실행을 재개합니다.

제너레이터의 독창적 가치: 지연 평가(Lazy Evaluation)

제너레이터의 가장 큰 장점은 모든 값을 한꺼번에 메모리에 올리지 않고, 필요한 시점에만 값을 생성한다는 것입니다. 이는 10GB 짜리 로그 파일을 한 줄씩 읽어 처리할 때 시스템 다운을 방지하는 유일한 해결책이 됩니다.


3. 이터레이터와 제너레이터의 구조적 차이점 비교

두 개념의 기술적 차이를 명확히 이해하기 위해 아래 표로 정리하였습니다.

비교 항목 이터레이터 (Class 기반) 제너레이터 (Function 기반)
구현 방식 클래스 내 __iter__, __next__ 구현 함수 내 yield 키워드 사용
상태 관리 클래스 변수(self)를 통해 수동 관리 로컬 변수와 실행 상태가 자동 저장
코드 간결성 비교적 복잡하고 코드가 김 매우 간결하고 가독성이 높음
메모리 사용량 객체 생성 비용이 발생함 최소한의 메모리만 사용 (매우 효율적)
무한 수열 구현 가능 (StopIteration 조건 미설정 시) 매우 용이 (while True와 yield 조합)

4. 실전 Sample Example: 대용량 데이터 처리 해결 방법

아래는 사용자 리스트에서 특정 조건에 맞는 데이터를 추출할 때, 이터레이터 클래스와 제너레이터 함수를 각각 어떻게 구현하는지 보여주는 예제입니다.

[예제 1] 클래스 기반 이터레이터 구현


class SquareIterator:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.limit:
            result = self.current ** 2
            self.current += 1
            return result
        else:
            raise StopIteration

# 사용
for num in SquareIterator(5):
    print(num)

[예제 2] yield를 이용한 제너레이터 구현 (권장 방법)


def square_generator(limit):
    current = 0
    while current < limit:
        yield current ** 2
        current += 1

# 사용
for num in square_generator(5):
    print(num)

보시다시피 제너레이터를 사용하면 이터레이션 프로토콜(__iter__, __next__, StopIteration)을 파이썬이 내부적으로 자동 처리해주므로 코드가 훨씬 직관적입니다.


5. 전문가의 조언: 언제 무엇을 선택해야 하는가?

  1. 제너레이터를 선택해야 할 때: 로직이 단순하고, 데이터 스트림을 한 방향으로 소비하며, 메모리 절약이 최우선일 때 사용합니다. 대부분의 실무 상황(파일 읽기, API 페이지네이션 등)에 적합합니다.
  2. 이터레이터(클래스)를 선택해야 할 때: 객체 지향적인 설계가 필요하거나, 반복 상태 외에 추가적인 속성이나 메서드가 필요한 복잡한 데이터 구조를 설계할 때 사용합니다.

6. 결론

파이썬의 제너레이터와 이터레이터는 단순한 문법적 차이를 넘어, 시스템의 자원을 효율적으로 분배하는 강력한 도구입니다. yield를 통한 지연 평가 기법을 익히는 것만으로도 여러분의 코드는 "작동하는 코드"에서 "성능이 우수한 코드"로 한 단계 격상될 것입니다. 오늘 소개한 프로토콜의 차이와 구현 방법을 바탕으로 더욱 견고한 파이썬 애플리케이션을 구축해 보시기 바랍니다.


참고 문헌 및 출처

  • Python Software Foundation. "The Python Standard Library - Iterator Types." docs.python.org
  • Luciano Ramalho. "Fluent Python: Clear, Concise, and Effective Programming." O'Reilly Media.
  • David Beazley. "Python Cookbook." O'Reilly Media.
728x90