[Troubleshooting] 파이썬(Python) Pandas 대용량 엑셀/CSV 처리 중 MemoryError 완벽 해결 아키텍처
"5기가바이트짜리 로그 데이터를 Pandas로 읽어 들이는데, 컴퓨터 램(RAM)이 100%를 치더니 파이썬이 강제 종료되었습니다."
데이터 분석 실무자들이 파이썬(Python)의 Pandas 라이브러리를 찬양하다가 처음으로 배신감을 느끼는 순간이다. Pandas의 read_csv()나 read_excel() 함수는 데이터를 분석하기 위해 파일 전체를 컴퓨터의 메인 메모리(RAM)에 한 번에 올려버리는 구조를 띄고 있다. 만약 당신의 램 용량이 16GB인데, 읽어 들일 데이터가 5GB라면? Pandas는 내부적으로 데이터를 변환하고 인덱싱하는 과정에서 원본 용량의 3~5배에 달하는 메모리를 집어삼키며 결국 'MemoryError (메모리 초과)'를 뱉어내고 장렬히 전사한다.
이 에러를 만난 초보자들은 비싼 돈을 들여 컴퓨터 램을 64GB로 증설하거나 클라우드 서버 사양을 높인다. 하지만 진정한 데이터 아키텍트는 하드웨어를 돈으로 바르기 전에, 소프트웨어의 파이프라인을 최적화한다. 본 가이드에서는 대용량 데이터를 조각내어 처리하는 '청크(Chunk)' 아키텍처를 단호하게 제시한다.
1단계: 핵심 원인 분석 (In-Memory 연산의 한계)
Pandas는 빠르다. 그 빠른 속도의 비결은 모든 데이터를 메모리에 올려두고 연산(In-Memory)하기 때문이다. 하지만 빅데이터 시대에 수천만 행의 데이터를 한 번에 메모리에 올리는 것은 자살 행위다. 데이터베이스에서 쿼리를 날리듯, 필요한 만큼만 꺼내서 쓰고 버리는 스트리밍(Streaming) 방식의 접근이 필수적이다.
2단계: 완벽한 해결책 - Chunksize를 활용한 데이터 분할 처리
Pandas는 이미 대용량 처리를 위한 chunksize 파라미터를 제공하고 있다. 이 옵션을 사용하면 1천만 행의 데이터를 한 번에 읽지 않고, 10만 행씩 100번에 걸쳐 쪼개어 읽어 들인다. 메모리 점유율을 획기적으로 낮추면서도 모든 데이터에 대한 연산을 수행할 수 있다.
아래는 실무에서 대용량 데이터를 안전하게 필터링하고 병합할 때 사용하는 Python 트러블슈팅 코드다.
import pandas as pd
FILE_PATH = 'massive_log_data.csv'
CHUNK_SIZE = 100000 # 한 번에 메모리에 올릴 행(Row)의 수
def process_massive_data(file_path):
# 빈 리스트를 생성하여 정제된 데이터 조각들을 담을 준비를 한다
processed_chunks = []
# chunksize를 지정하면 TextFileReader 객체(제너레이터)가 반환된다
chunk_iterator = pd.read_csv(file_path, chunksize=CHUNK_SIZE)
for i, chunk in enumerate(chunk_iterator):
print(f"[{i+1}번째 청크 처리 중...] 메모리 최적화 가동")
# 1. 불필요한 열(Column) 제거로 메모리 다이어트
chunk = chunk[['date', 'user_id', 'action', 'revenue']]
# 2. 필요한 조건만 필터링 (예: 결제 완료 액션만 추출)
filtered_chunk = chunk[chunk['action'] == 'purchase']
# 3. 데이터 타입 다운캐스팅 (float64 -> float32 등)으로 추가 메모리 확보
filtered_chunk['revenue'] = pd.to_numeric(filtered_chunk['revenue'], downcast='float')
# 4. 정제된 가벼운 조각만 리스트에 저장
processed_chunks.append(filtered_chunk)
# 모든 조각을 하나의 깔끔한 데이터프레임으로 병합
final_dataframe = pd.concat(processed_chunks, ignore_index=True)
print("대용량 데이터 병합 완료! MemoryError 방어 성공.")
return final_dataframe
if __name__ == "__main__":
df = process_massive_data(FILE_PATH)
3단계: 추가 최적화 (Data Type Downcasting)
청크 처리와 함께 반드시 병행해야 하는 것이 '데이터 타입 최적화(Downcasting)'다. Pandas는 숫자를 읽을 때 무조건 가장 무거운 64비트 타입(int64, float64)을 할당한다. 만약 회원 나이 데이터가 1부터 100 사이라면 8비트(int8)로도 충분하다. 위 코드의 주석 3번처럼 pd.to_numeric(downcast='float')를 습관적으로 적용하라. 이것만으로도 전체 메모리 사용량의 50% 이상을 가볍게 날려버릴 수 있다.
아키텍트의 시선 (Insight)
MemoryError는 컴퓨터가 고장 난 것이 아니라, 당신의 코드가 데이터의 무게를 감당할 만큼 유연하지 못하다는 시스템의 경고다. 모든 것을 한 번에 집어삼키려는 탐욕을 버리고, 데이터를 잘게 쪼개어 소화하는 청킹(Chunking) 파이프라인을 구축하라. 이는 단순히 에러를 피하는 것을 넘어, 한정된 컴퓨터 자원으로 무한한 데이터를 다루는 데이터 엔지니어링의 정수다.
댓글
댓글 쓰기