
파이썬으로 대용량 데이터를 처리하거나 복잡한 알고리즘을 설계할 때, 가장 먼저 직면하는 벽은 바로 '메모리 부족' 현상입니다. 수백만 개의 요소를 리스트에 담아 반환하려고 하면 시스템은 순식간에 느려지거나 멈춰버리고 맙니다. 이러한 성능 병목 현상을 우아하게 해결할 수 있는 파이썬의 핵심 기능이 바로 제너레이터(Generator)와 yield 키워드입니다. 본 포스팅에서는 전문가의 시선으로 제너레이터의 내부 동작 원리와 실무 적용 방법을 심도 있게 다룹니다.
1. 제너레이터(Generator)와 yield란 무엇인가?
일반적인 함수는 return을 만나면 실행을 종료하고 모든 지역 변수를 메모리에서 해제합니다. 반면, 제너레이터는 실행 중간에 멈췄다가 나중에 다시 시작할 수 있는 특수한 형태의 반복자(Iterator)입니다. 그 중심에는 yield 키워드가 있습니다.
- yield의 역할: 함수 실행 중 값을 밖으로 전달하면서, 함수의 상태(현재 변수 값, 명령어 위치 등)를 그대로 유지합니다.
- 지연 평가(Lazy Evaluation): 모든 데이터를 한꺼번에 메모리에 올리지 않고, 요청이 있을 때만 데이터를 생성하여 전달합니다.
2. 리스트와 제너레이터의 5가지 결정적 차이
단순한 반복문 사용법은 비슷해 보이지만, 내부적인 데이터 처리 메커니즘은 완전히 다릅니다. 이를 이해하는 것이 고급 파이썬 개발자로 가는 첫걸음입니다.
| 비교 항목 | 리스트(List / Iterable) | 제너레이터(Generator / Iterator) |
|---|---|---|
| 메모리 점유 | 모든 요소를 메모리에 저장 (높음) | 현재 값 하나만 메모리에 유지 (매우 낮음) |
| 생성 시점 | 선언 즉시 모든 데이터 생성 | next() 호출 시점에 데이터 생성 |
| 데이터 접근 | 인덱싱, 슬라이싱 가능 | 순차적 접근만 가능 (일회성) |
| 무한 루프 | 구현 불가 (메모리 초과 발생) | 무한한 데이터 스트림 구현 가능 |
| 사용 편의성 | 데이터 재사용이 용이함 | 대규모 데이터 처리에 압도적 유리 |
3. yield를 활용한 대용량 파일 처리 해결 방법
예를 들어, 10GB 크기의 로그 파일을 한 줄씩 읽어야 한다고 가정해 봅시다. readlines()를 쓰면 서버 메모리가 터지겠지만, 제너레이터를 사용하면 단 몇 MB의 메모리만으로도 안정적인 처리가 가능합니다.
[Sample Example] 실전 제너레이터 구현
# 1. 일반적인 리스트 방식 (비효율적)
def get_large_list(n):
result = []
for i in range(n):
result.append(i)
return result
# 2. yield를 사용한 제너레이터 방식 (최적화)
def get_large_generator(n):
for i in range(n):
yield i
# 실행 비교
gen = get_large_generator(10000000)
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 2
# 필요한 순간에만 루프를 돌며 값을 가져옴
for value in get_large_generator(5):
print(f"현재 값: {value}")
4. 제너레이터 표현식(Generator Expression)
리스트 컴프리헨션(List Comprehension)과 유사한 문법을 사용하면서도 메모리 이점을 챙길 수 있는 방법입니다. 대괄호[] 대신 소괄호()를 사용하면 간단히 생성됩니다.
squares_gen = (x*x for x in range(1000000))
이 코드는 실행 즉시 백만 개의 제곱값을 만들지 않습니다. 실제로 값이 필요한 시점까지 연산을 미룹니다.
5. 전문가의 조언: 언제 제너레이터를 써야 하는가?
모든 상황에서 제너레이터가 정답은 아닙니다. 데이터 규모가 작고 여러 번 재사용해야 한다면 리스트가 편리합니다. 하지만 다음과 같은 상황에서는 반드시 제너레이터 도입을 고려해야 합니다.
- 데이터의 크기가 예측 불가능할 정도로 클 때
- 데이터를 한꺼번에 처리하기보다 순차적으로 소비(Consume)할 때
- 중간 연산 결과를 보관할 필요 없이 파이프라인 형태로 데이터를 넘길 때
글의 출처 및 참고 자료
- Python Software Foundation: Python Language Reference - Yield expressions
- Luciano Ramalho: Fluent Python (고성능 파이썬 프로그래밍)
- David Beazley: Generator Tricks for Systems Programmers
'Artificial Intelligence > 60. Python' 카테고리의 다른 글
| [PYTHON] 데이터 저장의 핵심, 텍스트 파일과 바이너리 파일의 3가지 결정적 차이와 처리 방법 (0) | 2026.03.13 |
|---|---|
| [PYTHON] 파일이 존재하는지 확인하는 효율적인 3가지 방법과 예외 처리 해결 가이드 (0) | 2026.03.13 |
| [PYTHON] 파일 관리의 정석 : 절대 경로와 상대 경로의 3가지 결정적 차이 및 경로 오류 해결 방법 (0) | 2026.03.13 |
| [PYTHON] 데이터 스트림 최적화 방법 : 이터레이터(Iterator) 직접 구현과 2가지 핵심 프로토콜 차이 및 해결 (0) | 2026.03.13 |
| [PYTHON] 문자열 검색의 99% 해결 방법 : 정규 표현식(Regex) 기초 개념과 일반 검색의 차이 및 3단계 활용법 (0) | 2026.03.13 |