Python 멀티프로세싱으로 크롤러 성능 개선
문제 상황
5만 개 상품 데이터를 수집하는 크롤러가 12시간 이상 소요되고 있었다. Threading으로 개선을 시도했지만 GIL 때문에 CPU 코어를 제대로 활용하지 못했다.
multiprocessing 적용
concurrent.futures.ProcessPoolExecutor를 사용해 프로세스 풀을 구성했다.
from concurrent.futures import ProcessPoolExecutor, as_completed
import requests
from bs4 import BeautifulSoup
def crawl_product(url):
response = requests.get(url, timeout=10)
soup = BeautifulSoup(response.content, 'html.parser')
return {
'url': url,
'title': soup.select_one('.product-title').text,
'price': soup.select_one('.price').text
}
if __name__ == '__main__':
urls = load_urls() # 5만개 URL
results = []
with ProcessPoolExecutor(max_workers=8) as executor:
futures = {executor.submit(crawl_product, url): url for url in urls}
for future in as_completed(futures):
try:
result = future.result(timeout=30)
results.append(result)
except Exception as e:
print(f"Error: {e}")
주의사항
프로세스 생성 오버헤드가 있어서 작업 단위가 너무 작으면 오히려 느려진다. 배치 단위를 500개씩 묶어서 처리했더니 더 효율적이었다.
if __name__ == '__main__' 가드를 반드시 추가해야 Windows 환경에서 무한 프로세스 생성을 막을 수 있다.
결과
12시간 → 2시간으로 단축되었다. CPU 사용률도 15%에서 85%로 올라갔다. 다만 메모리 사용량이 4배 증가해서 프로세스 수를 조정할 필요가 있었다.