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

[PYTHON] itertools 모듈을 활용한 메모리 효율적 5가지 반복 처리 방법과 리스트 처리의 차이

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

itertools 모듈
itertools 모듈

 

1. 파이썬 반복문의 한계와 itertools의 등장 배경

파이썬은 데이터 처리에 매우 강력한 언어지만, 대용량 데이터를 다룰 때 메모리 관리라는 큰 숙제를 안고 있습니다. 단순히 list에 모든 데이터를 담아 반복 처리하는 방식은 데이터가 수백만 건 이상으로 늘어날 경우 MemoryError를 유발하거나 시스템 속도를 현저히 저하시키는 원인이 됩니다. 이러한 문제를 해결하기 위해 파이썬은 표준 라이브러리로 itertools 모듈을 제공합니다. 이 모듈은 '이터레이터(Iterator)'를 생성하여 데이터 전체를 메모리에 올리지 않고, 필요할 때마다 하나씩 값을 꺼내 쓰는 지연 평가(Lazy Evaluation) 방식을 채택합니다. 이는 메모리 사용량을 획기적으로 줄이면서도 복잡한 반복 로직을 간결하게 구현할 수 있게 해줍니다.

2. 리스트 방식 vs itertools 방식의 결정적 차이

일반적인 리스트 컴프리헨션과 itertools가 제공하는 이터레이터 방식의 차이를 명확히 이해하는 것이 중요합니다.

비교 항목 일반 List 처리 itertools 처리
메모리 점유 데이터 전체 크기에 비례 (높음) 현재 처리 중인 요소만 점유 (매우 낮음)
실행 시점 생성 시 즉시 계산 (Eager) 반복문 호출 시 계산 (Lazy)
대용량 처리 메모리 부족 위험 존재 무한에 가까운 데이터 처리 가능
데이터 타입 가변적(Mutable) 리스트 한 번 소비되면 사라지는 이터레이터

3. 실무 효율을 높이는 itertools 5가지 핵심 활용 방법

① chain(): 여러 컨테이너를 하나로 결합

서로 다른 리스트나 튜플을 합칠 때 새로운 리스트를 만들지 않고 연결합니다.

import itertools
list1 = [1, 2, 3]
list2 = [4, 5, 6]
# 메모리 낭비 없이 두 리스트를 연결
combined = itertools.chain(list1, list2)
for item in combined:
    print(item)

② cycle(): 반복 가능한 객체의 무한 순환

리스트의 요소를 무한히 반복해야 할 때 유용하며, 별도의 인덱스 관리 없이 방법을 간소화합니다.

# 로딩 애니메이션이나 상태 순환에 활용
colors = itertools.cycle(['Red', 'Green', 'Blue'])
# next()를 호출할 때마다 다음 색상 반환

③ accumulate(): 누적 합계 및 연산 처리

중간 단계의 계산 결과값을 효율적으로 보관하며 처리합니다.

# 기본적으로 누적 합계를 구함
data = [1, 2, 3, 4, 5]
result = itertools.accumulate(data) # [1, 3, 6, 10, 15]

④ product(): 데카르트 곱(Cartesian Product) 생성

다중 중첩 for문을 깔끔하게 한 줄로 대체하여 코드 가독성을 높입니다.

# 중첩 루프 대체
for i, j in itertools.product(range(3), range(3)):
    print(f"({i}, {j})")

⑤ islice(): 이터레이터 전용 슬라이싱

리스트 슬라이싱과 달리 원본의 복사본을 만들지 않고 특정 범위만 추출합니다.

large_range = range(1000000)
# 메모리 소모 없이 앞의 10개만 가져옴
limited = itertools.islice(large_range, 0, 10)

4. Sample Example: 대규모 로그 파일 분석 시나리오

수 기가바이트(GB)에 달하는 로그 파일에서 특정 키워드가 포함된 라인만 추출하여 분석하는 상황을 가정해 보겠습니다.

import itertools

def analyze_logs(file_path):
    with open(file_path, 'r') as f:
        # 1. 파일 객체 자체가 이터레이터이므로 메모리에 로드되지 않음
        # 2. chain을 사용하여 여러 로그 파일을 연결할 수도 있음
        # 3. islice를 사용하여 상위 100개의 에러만 추출
        error_logs = (line for line in f if "ERROR" in line)
        top_100_errors = itertools.islice(error_logs, 100)
        
        for log in top_100_errors:
            process_log(log) # 필요한 로직 처리

# 전체 파일을 메모리에 올리지 않고도 안전하게 처리 가능

5. 결론 및 주의사항

itertools를 활용하는 방법은 단순히 코드를 짧게 만드는 것이 아니라, 서버 자원을 효율적으로 관리하는 전문적인 개발자의 필수 덕목입니다. 다만, 이터레이터는 한 번 소비(Iteration)되면 재사용이 불가능하므로, 같은 데이터를 여러 번 참조해야 할 경우에는 itertools.tee를 사용하거나 필요한 시점에 리스트로 변환해야 한다는 점을 유의해야 합니다.


참고 문헌 및 출처

  • Python Official Documentation - itertools 
  • Fluent Python by Luciano Ramalho (O'Reilly Media)
  • Real Python - Python Itertools 
728x90