Python 멀티프로세싱으로 데이터 처리 성능 개선
문제 상황
사용자가 업로드한 원본 이미지를 여러 크기로 리사이징하는 배치 작업이 있었다. 단일 프로세스로 10,000장을 처리하는데 약 40분이 걸렸고, 이는 운영상 허용할 수 없는 시간이었다.
GIL과 멀티스레딩의 한계
처음에는 threading 모듈을 시도했지만 개선이 거의 없었다. Python의 GIL(Global Interpreter Lock) 특성상 CPU 집약적 작업에서는 멀티스레딩이 효과가 없다는 것을 다시 확인했다.
multiprocessing 적용
multiprocessing.Pool을 사용해 CPU 코어 수만큼 워커 프로세스를 생성했다.
from multiprocessing import Pool, cpu_count
from PIL import Image
import os
def resize_image(args):
input_path, output_path, size = args
try:
img = Image.open(input_path)
img.thumbnail(size, Image.ANTIALIAS)
img.save(output_path, quality=85)
return True
except Exception as e:
print(f"Error: {input_path} - {e}")
return False
def batch_resize(image_list, sizes):
tasks = []
for img_path in image_list:
for size in sizes:
output_path = generate_output_path(img_path, size)
tasks.append((img_path, output_path, size))
with Pool(processes=cpu_count()) as pool:
results = pool.map(resize_image, tasks)
return sum(results)
결과
4코어 서버에서 처리 시간이 약 10분으로 단축되었다. 프로세스 간 통신 오버헤드가 있지만, 이미지 처리는 각 작업이 독립적이라 효율이 좋았다.
주의사항
- 프로세스 생성 비용이 있어 작업 단위가 너무 작으면 오히려 느려진다
- 메모리 사용량이 프로세스 수만큼 증가하므로 모니터링 필요
- Windows에서는
if __name__ == '__main__':가드가 필수
I/O 바운드 작업이라면 asyncio나 스레딩이 더 나을 수 있지만, CPU 바운드에서는 멀티프로세싱이 확실한 해법이었다.