Post
Python 제너레이터와 이터레이터 실전: 메모리 효율적인 데이터 처리
왜 제너레이터가 중요한가?
실무에서 로그 파일, 대용량 CSV, 배치 데이터처럼 한 번에 메모리에 올리기 부담스러운 데이터를 다룰 일이 많습니다. 이때 리스트로 전부 읽어오면 메모리 사용량이 급격히 증가합니다.
제너레이터는 필요한 시점에 한 건씩 값을 생성하기 때문에, 메모리 효율이 중요한 백엔드 작업에서 매우 유리합니다.
핵심 개념
- Iterator:
__next__()로 다음 값을 하나씩 꺼낼 수 있는 객체 - Generator:
yield를 사용해 간단하게 iterator를 만드는 문법 - Lazy Evaluation: 미리 전부 계산하지 않고 필요할 때 계산
리스트 vs 제너레이터
numbers = [i * 2 for i in range(1_000_000)] # 메모리 사용량 큼
numbers_gen = (i * 2 for i in range(1_000_000)) # lazy evaluation
yield 예제
def read_lines(path):
with open(path, 'r', encoding='utf-8') as f:
for line in f:
yield line.strip()
for line in read_lines('app.log'):
if 'ERROR' in line:
print(line)
배치 처리 예제
def chunked(iterable, size):
batch = []
for item in iterable:
batch.append(item)
if len(batch) == size:
yield batch
batch = []
if batch:
yield batch
for batch in chunked(range(1, 21), 5):
print(batch)
언제 쓰면 좋은가?
- 대용량 파일 처리
- DB 조회 결과 스트리밍
- API 페이지네이션 처리
- 배치 파이프라인 구성
흔한 실수
- 제너레이터는 한 번 소비하면 끝난다는 점을 놓침
- 디버깅 편하다고 중간에
list()로 바꿔 메모리 이점 상실 - 제너레이터와 비동기 스트림을 혼동
한 줄 정리
제너레이터는 Python에서 대용량 데이터를 다룰 때 가장 먼저 떠올려야 하는 메모리 절약 패턴입니다.
댓글