파이썬의 비밀스러운 삶: 게으른 제빵사
I’m ready to translate the article for you, but it looks like the body of the text isn’t included in your message. Could you please provide the full content you’d like translated (excluding the source line you already shared)? Once I have the text, I’ll keep the source link at the top and translate the rest into Korean while preserving all formatting and code blocks.
왜 파이썬 코드가 메모리를 다 쓰는지, 그리고 yield가 해결 방법인 이유
라이브러리는 희미하게 오존과 타는 플라스틱 냄새가 났다. 티모시가 노트북 앞에 앉아 있었지만 타이핑을 하고 있지는 않았다. 그는 회전하는 커서를 멍하니 바라보고 있었다. 팬은 크게 윙윙거렸다.
“또 크래시했어,” 티모시가 신음했다.
마가렛은 책에 표시를 하고 고개를 들었다.
“뭘 만들려고 하는 거야?”
“데이터셋을 시뮬레이션해야 해,” 티모시가 설명했다. “새 분석 스크립트를 테스트하려면 1억 개의 무작위 센서 판독값이 필요해. 그걸 만들 함수도 짰고 리스트에 담았어.”
그는 화면에 고정된 코드를 가리켰다.
티모시의 “Eager” 베이커
def produce_readings(n):
results = []
print("Starting production...")
for i in range(n):
# Imagine complex calculation here
results.append(i * 1.5)
print("Production complete!")
return results
# Asking for 100 million items
data = produce_readings(100_000_000)
for reading in data:
process(reading)
“Run 버튼을 눌렀어,” 티모시가 말했다, “그럼 컴퓨터가 멈춰.
process루프에 들어가기조차 못 해. 메모리가 다 떨어져 버려.”
마가렛은 고개를 끄덕이며 말했다.
“너는 Eager Baker를 고용했구나.”
베이커리 비유
“베이커리를 상상해 보세요. 당신이 들어와서 만 천 개의 빵을 달라고 하면,
Eager Baker는 ‘예, 손님!’이라고 대답합니다. 그는 즉시 만 천 개의 반죽을 만들고, 만 천 개의 빵을 구워서, 그것을 쌓아 카운터, 바닥, 뒤쪽 방까지 가득 채웁니다… 베이커리는 폭발 직전이죠. 그는 모든 만 천 개가 완성될 때까지 한 조각도 건네줄 수 없습니다.”
“그게 바로 당신 리스트가 하는 일과 같아요,” 마가렛이 말했다. “당신은 1억 개의 숫자를 요구했어요. 파이썬은 그 모든 숫자를 만들고 RAM에 저장한 뒤에야 첫 번째를 꺼내 주려 합니다. 당신 컴퓨터엔 그런 창고가 없어요.”
“그럼 큰 데이터를 처리할 수 없는 건가요?” 티모시가 물었다.
“가능합니다,” 마가렛이 미소 지으며 답했다. “하지만 Eager Baker를 해고해야 해요. Lazy Baker가 필요합니다.”
마가렛의 “Lazy” 베이커 (제너레이터)
def produce_readings_lazy(n):
print("Starting production...")
for i in range(n):
yield i * 1.5
print("Production complete!")
“리스트는 어디에 있나요?” 티모시가 물었다. “
results.append는요?”
“리스트는 없습니다,” 마가렛이 말했다. “
yield만 있습니다. 이 키워드가 함수를 제너레이터로 바꿔 주죠.”
제너레이터 사용하기
# Create the generator object
baker = produce_readings_lazy(100_000_000)
print(f"Baker object: {baker}")
# Ask for the first loaf
print(next(baker))
# Ask for the second loaf
print(next(baker))
출력
Baker object: <generator object produce_readings_lazy at 0x...>
Starting production...
0.0
1.5
“보이시나요?” 마가렛이 속삭였다. “
baker객체를 만들었을 때는 아무 일도 일어나지 않았어요. 코드도 실행되지 않았고 메모리도 사용되지 않았죠. 베이커는 대기하고 있었습니다.”
“
next(baker)를 호출했을 때 그는 깨어났어요.yield에 도달할 때까지 실행하고, 하나의 값을 건네준 뒤 멈추면서 정확히 어디서 멈췄는지 기억하고 있었습니다.”
“그럼 한 번에 하나씩 구워주는 건가요?” 티모시가 물었다.
“요청이 있을 때마다요,” 마가렛이 확인했다. “그는 하나를 구워서 건네주고, 당신이 다시 오기를 기다립니다. 한 번에 하나 이상의 아이템을 저장하지 않죠.”
메모리 비교
마가렛은 객체 크기를 재기 위해 sys를 임포트했다.
import sys
# The Eager List (small scale to avoid crashing)
eager_list = [i * 1.5 for i in range(1_000_000)]
# The Lazy Generator (same scale)
lazy_gen = (i * 1.5 for i in range(1_000_000))
print(f"List Size in Bytes: {sys.getsizeof(eager_list)}")
print(f"Generator Size in Bytes: {sys.getsizeof(lazy_gen)}")
결과
List Size in Bytes: 8448728
Generator Size in Bytes: 104
“리스트는 약 8 MB이고, 제너레이터는… 104 바이트인가요? 트윗 하나보다도 작네요.”
“리스트는 백만 개의 숫자를 실제로 보관하고 있기 때문이에요. 제너레이터는 다음 숫자를 얻는 레시피만 가지고 있죠. 백만 개를 물어도 메모리 사용량은 변하지 않습니다.”
“그는 영원히 구울 수도 있어요,” 마가렛이 덧붙였다. “
while True: yield n이라고 쓰면 반죽이 절대 바닥나지 않겠죠. 한 번에 하나씩만 요청하면 무한히 구울 수 있어요.”
The Catch
“한 가지 함정이 있어요,” 마가렛이 경고했다. “게으른 제빵사는 선반 공간이 없어요. 빵 한 덩어리를 건네주면 바로 잊어버리죠. ‘빵 번호 5’를 다시 요청하려면 전체 과정을 처음부터 다시 시작해야 해요. 제너레이터는 일방통행이에요.”
“하지만,” 그녀가 재빨리 타이핑하며 말했어요, “이들을 파이프라인으로 연결할 수 있어요.”
# The Pipeline: Data flows through, one item at a time
raw_data = (read_sensor() for _ in range(1_000_000))
clean_data = (x for x in raw_data if x > 0)
final_data = (process(x) for x in clean_data)
“리스트가 아니라,” 티모시가 감탄했다. “그냥 스트림이야.”
Quick Reference (Margaret’s Notebook)
- The Eager Approach (Lists) – 모든 것을 미리 계산합니다. 빠른 랜덤 접근(
my_list[5])이 가능하지만 메모리를 많이 잡아먹어요. - The Lazy Approach (Generators) – 한 번에 하나씩 계산합니다.
yieldKeyword – 함수의 실행을 일시 중지하고 값을 반환하며 현재 상태를 저장합니다.- Generator Expressions –
(x for x in data). 리스트 컴프리헨션과 비슷하지만()를 사용합니다. - Trade‑off – 제너레이터는 엄청난 메모리를 절약하지만 한 번만 사용할 수 있습니다. 인덱싱(
gen[0])하거나 두 번 반복할 수 없어요. - Use Cases – 방대한 데이터셋, 무한 스트림, 데이터 파이프라인.
티모시는 대괄호를 괄호로 바꾸고 Run 버튼을 눌렀다. 노트북의 팬이 즉시 조용해졌고, 데이터가 흐르기 시작했다.
“이렇게 말할 줄은 몰랐어요,” 티모시가 웃으며 말했다, “하지만 나는 게으름을 사랑하게 되었어요.”
“효율성, 티모시,” 마가렛이 차를 마시며 정정했다. “우리는 그것을 효율성이라고 부릅니다.”
*다음 에피소드에서 마가렛과 티모시는 **“마법의 책장”*을 마주하게 됩니다—그곳에서 그들은 데이터 구조를 발견하게 되죠…
Aaron Rose는 tech-reader.blog의 소프트웨어 엔지니어이자 기술 작가이며, Think Like a Genius의 저자입니다.