View

출처: analyticsvidhya.com
10GB CSV 파일을 Pandas로 읽다가 RAM을 터뜨려본 경험이 있다면 공감할 것이다. pd.read_csv() 한 줄을 돌렸는데 노트북 팬이 비행기 이륙하는 소리를 내다가 결국 MemoryError를 뱉고 죽어버리는 그 순간. 이럴 때 옆에서 "Polars를 써봐라"라고 꼬시는 것이 2026년 현재의 상황이다.
Pandas vs Polars 비교는 이제 "언제 갈아타야 하는가" 단계를 지났다. 프로덕션에서 둘 다 쓰는 팀이 많아졌고, 담론은 "둘을 언제 어떻게 섞어 쓰는가"로 이동했다. 다만 한국어 자료는 아직 2023~2024년 기준에 멈춰 있고, 대부분 "Polars가 빠르니 갈아타라" 수준이다. 이 글에서는 2026년 최신 벤치마크, 아키텍처 차이, 솔직한 단점, 그리고 실제 선택 기준까지 팩트 기반으로 정리한다.
Pandas와 Polars의 정체
Python 데이터프레임 라이브러리를 논할 때 이 둘을 빼면 할 말이 없다. 다만 만든 사람, 철학, 내부 구현이 완전히 다르다.
Pandas: 2008년부터 표준이 된 이유
Pandas는 2008년에 Wes McKinney가 AQR Capital에서 일할 때 만든 것이다. 금융 시계열 데이터를 돌리기 위해 NumPy 위에 편의 레이어를 얹은 것이 시작이었다. 철학은 "Python-first"다. 쓰기 편하고 API가 직관적인 것이 최우선이었고, 성능은 후순위였다.
17년 넘게 생태계를 장악한 이유는 단순하다. scikit-learn, matplotlib, seaborn, Jupyter까지 거의 모든 Python 데이터 툴이 Pandas DataFrame을 표준 입력으로 받는다. 튜토리얼, StackOverflow 답변, 업무 코드베이스가 모두 Pandas로 쓰여 있다. 갈아타는 비용이 크다는 뜻이다.
Polars: Rust로 다시 쓴 DataFrame
Polars는 2020년 9월에 Ritchie Vink가 Rust로 처음 공개했다. 원래 본인이 쓰려고 만든 사이드 프로젝트였는데 성능이 너무 잘 나와서 오픈소스로 풀린 케이스다. 2024년 7월에 1.0 GA가 떴고, 2026년 현재 GitHub 스타 30k+를 찍었다(Pandas는 43k+).
철학은 "Performance-first"다. API가 다소 낯설어도 병렬 처리, 메모리 효율, 쿼리 최적화를 기본값으로 박아두었다. Apache Arrow 기반이라 DuckDB, PyArrow 같은 Arrow 생태계 툴과 zero-copy로 데이터를 공유한다.
Polars가 빠른 이유

"그냥 Rust라서 빠른 것이 아닌가?"라고 하면 반만 맞다. 언어도 있지만 구조 자체가 다르다.
Apache Arrow 기반 컬럼형 스토리지
Pandas는 기본적으로 NumPy 블록매니저를 쓴다. 행(row) 단위로 데이터가 섞여 저장되는 구조라 특정 컬럼만 뽑아 연산할 때 캐시 미스가 많이 난다. Pandas 2.0(2023년 4월)부터 PyArrow 백엔드 옵션이 생기긴 했으나 기본값은 여전히 NumPy다.
Polars는 처음부터 Apache Arrow 컬럼형 포맷으로 설계됐다. 같은 컬럼의 데이터가 메모리에 연속해서 쌓여 있어서 SIMD 명령어로 벡터 연산을 때릴 수 있다. 이것이 집계나 필터링에서 수 배의 차이를 만든다.
멀티스레딩이 기본값이다
Pandas는 GIL(Global Interpreter Lock) 때문에 단일 스레드로 돌아간다. 코어가 16개 있어도 1개만 쓴다. swifter, modin 같은 병렬화 래퍼가 있긴 하지만 공식은 아니다.
Polars는 Rust로 작성되어 GIL의 영향을 받지 않는다. group_by, join, filter 같은 연산이 기본적으로 모든 코어를 다 굴린다. M2 Pro 10코어 기준으로 Pandas 대비 6~8배 빨라지는 체감이 여기서 나온다.
Lazy Evaluation과 쿼리 옵티마이저
이것이 진짜 핵심이다. pl.scan_csv()로 파일을 여는 순간 데이터를 읽지 않는다. 대신 쿼리 플랜만 쌓아두다가 .collect()를 호출하면 그때 한 번에 실행한다.
이 과정에서 쿼리 옵티마이저가 predicate pushdown(필터를 스캔 단계로 밀어넣기), projection pushdown(필요한 컬럼만 읽기), common subplan elimination 같은 최적화를 자동으로 적용한다. 쉽게 말해 사용자가 짠 코드보다 실행 계획이 더 똑똑해진다. Pandas에는 이런 개념이 아예 없다 — 쓴 순서대로 그대로 돌린다.
벤치마크로 보는 속도 차이
숫자 없이 "빠르다"만 언급하는 글은 믿지 말 것. 실제 숫자가 중요하다.
TPC-H 벤치마크 결과 (10GB 기준)
TPC-H는 데이터베이스 성능 표준 벤치마크다. Polars 공식 팀이 2025년에 업데이트한 10GB scale factor 기준으로 주요 쿼리 결과를 정리하면 다음과 같다.
| 쿼리 | Pandas 2.2 (초) | Polars 1.8 (초) | 속도 배수 |
| Q1 (집계) | 88.4 | 5.2 | 17배 |
| Q3 (join + group) | 142.1 | 8.7 | 16배 |
| Q5 (multi-join) | 198.5 | 12.3 | 16배 |
| Q6 (filter + sum) | 45.2 | 1.8 | 25배 |
| Q10 (join + order) | 167.3 | 11.1 | 15배 |
연산에 따라 5~30배 차이가 난다. 단순 필터링은 차이가 적고, 복잡한 join + group_by 조합으로 갈수록 Polars 쿼리 옵티마이저의 효과가 커진다.
메모리 사용량 차이
속도보다 더 체감되는 것이 메모리다. 1GB CSV를 읽을 때 Pandas는 RAM 2.5~3GB를 쓰는 반면 Polars는 1.2~1.5GB 선에서 끝난다. 데이터 크기가 커질수록 격차가 벌어진다. 10GB 파일을 Pandas로 열려면 32GB RAM 노트북도 터지지만, Polars는 스트리밍 모드로 16GB에서도 돌아간다.

출처: vedanganalytics.com
문법 비교: 같은 일을 다르게 하는 방식
문법 차이가 Pandas vs Polars 갈아타기 진입 장벽의 대부분이다. 익숙해지면 Polars 쪽이 더 일관적이지만, 처음에는 Pandas 손가락 기억을 버리는 것이 진짜 고통스럽다.
CSV 읽고 필터링 → 집계
Pandas 버전:
import pandas as pd
df = pd.read_csv('sales.csv')
result = (df[df['amount'] > 1000]
.groupby('category')
.agg({'amount': 'sum', 'order_id': 'count'}))
Polars 버전:
import polars as pl
result = (pl.scan_csv('sales.csv')
.filter(pl.col('amount') > 1000)
.group_by('category')
.agg([
pl.col('amount').sum(),
pl.col('order_id').count()
])
.collect())
Polars는 scan_csv로 lazy를 시작하고 collect()로 실행을 트리거한다. Expression API(pl.col(...))가 필수라 처음에는 장황해 보이지만, 체이닝이 일관적이라 복잡해질수록 가독성이 역전된다.
Expression API vs 체이닝
Pandas는 같은 일을 하는 방법이 여러 개다. df.loc, df[], df.query()가 모두 다르게 동작하고 엣지 케이스가 다르다. SettingWithCopyWarning을 띄우면서 초보자를 괴롭히는 원인이 이것이다.
Polars는 pl.col() 기반의 Expression 하나로 통일된다. 읽기, 쓰기, 필터, 변환 전부 같은 패턴을 쓴다. 처음에는 불편하지만 나중에는 "Pandas가 이상했구나" 싶어진다.
null 처리 방식 차이
Pandas는 NaN과 None을 섞어 쓴다. 정수 컬럼에 null이 섞이면 float로 자동 변환되는 기괴한 동작을 한다. Pandas 2.0 nullable 타입으로 개선됐지만 기본값은 아니다.
Polars는 처음부터 null이 타입별로 제대로 분리되어 있다. Int64 컬럼은 null이 들어가도 그대로 Int64로 유지된다. 데이터 엔지니어링에서 이것이 진짜 중요하다.
Polars의 현실적 단점
Polars 예찬만 한다면 거짓말이다. 2026년 현재 기준으로 Polars 단점을 정직하게 짚으면 다음과 같다.
생태계가 아직 좁다
scikit-learn은 1.4부터 Polars DataFrame 직접 지원이 들어갔으나, matplotlib, seaborn, statsmodels 같은 시각화·통계 라이브러리는 아직 Pandas 입력을 가정한다. 결국 ML 파이프라인 중간에 .to_pandas()를 한 번 찍고 진행하는 경우가 많다.
Feature Store, MLflow, Airflow 같은 인프라 툴들도 대부분 Pandas 중심으로 문서화되어 있다. Polars로 가도 내부 변환이 일어나면 속도 이점이 반감될 수 있다.
학습 곡선: Pandas 머슬 메모리를 버리는 비용
10년 Pandas를 쓴 사람이 Polars로 넘어가면 첫 2주는 진짜 답답하다. df['col'] 대신 pl.col('col')을 쓰는 것을 자꾸 까먹고, reset_index()를 찾다가 Polars에는 인덱스 개념 자체가 없다는 사실을 나중에 알게 된다. 팀 단위로 갈아타려면 교육 비용을 시간으로 환산해야 한다.
한국어 자료가 적다
영어 블로그, 유튜브는 넘쳐나지만 한국어 심층 자료는 매우 적다. 2026년 현재 네이버는 거의 비어 있고, 구글 한국어 SERP 상위도 짧은 velog 글 몇 개가 전부다. StackOverflow 한국어 답변도 거의 Pandas를 전제로 쓰여 있다. 팀에서 주니어가 막혔을 때 레퍼런스를 찾기 힘든 것이 현실 비용이다.
언제 Pandas를 쓰고 언제 Polars를 쓰는가

출처: merishnasuwal.com.np
"무조건 Polars"는 틀린 답이다. 각설하고, 상황별로 정리한다.
Pandas가 아직 나은 경우 3가지
- 데이터 1GB 이하 + 탐색 분석(EDA): 캐글 노트북, 사내 리포트 같은 맥락이다. 속도 차이가 체감되지 않고 시각화를 붙이면 결국 Pandas를 경유해야 한다.
- 기존 레거시 코드베이스: 5년을 쓴 Pandas 파이프라인 5만 줄을 Polars로 옮기는 것은 ROI가 나오지 않는다. 핫패스만 Polars로 리팩터링하는 것이 현실적이다.
- scikit-learn 기반 ML 파이프라인: 전처리가 가벼우면 Pandas로 충분하고, 결국 fit 단계 전에 Pandas 변환이 필요하다.
Polars로 바로 갈아타야 하는 경우 3가지
- 데이터 5GB 이상 상시 처리: Pandas로는 메모리·속도 둘 다 답이 없다. ETL 배치 작업이 여기에 해당한다.
- 프로덕션 ETL/데이터 엔지니어링: 매일 새벽 돌아가는 파이프라인이라면 속도 30배 차이가 곧 클라우드 비용 30배 차이다. JP Morgan, ING가 이 케이스로 도입했다.
- 새 프로젝트 시작: 마이그레이션 비용이 없으면 Polars로 시작하는 것이 미래 가치 측면에서 유리하다. 3년 뒤에는 생태계 격차도 좁혀질 것이다.
같이 쓰는 하이브리드 전략
현실적으로 많은 팀이 선택하는 방식이다. 무거운 ETL은 Polars로 돌리고, 결과를 Parquet로 떨궈서 분석가/ML 엔지니어는 Pandas로 받는다. Apache Arrow 기반이라 Parquet 경유가 zero-copy에 가깝게 빠르다.
# ETL 단계: Polars
(pl.scan_parquet('raw/*.parquet')
.filter(pl.col('date') > '2026-01-01')
.group_by('user_id')
.agg(pl.col('amount').sum())
.sink_parquet('processed/agg.parquet'))
# 분석 단계: Pandas
import pandas as pd
df = pd.read_parquet('processed/agg.parquet')
df.plot(kind='hist')
이것이 2026년 현재 "프로덕션에서 많이 보이는 패턴"이다.
마이그레이션 체크리스트
Pandas에서 Polars로 점진적으로 옮길 때 주의할 포인트를 정리했다.
syntax 차이 주요 5가지
| 작업 | Pandas | Polars |
| 컬럼 선택 | `df['col']` | `df.select(pl.col('col'))` |
| 필터링 | `df[df['a'] > 1]` | `df.filter(pl.col('a') > 1)` |
| 그룹 집계 | `df.groupby('a').sum()` | `df.group_by('a').agg(pl.all().sum())` |
| 컬럼 추가 | `df['c'] = df['a'] + 1` | `df.with_columns((pl.col('a') + 1).alias('c'))` |
| join | `df1.merge(df2, on='id')` | `df1.join(df2, on='id')` |
주의해야 할 동작 차이
- 인덱스 없음: Polars에는 reset_index, set_index 개념이 없다. 필요하면 컬럼으로 들고 있어야 한다.
- group_by 결과 정렬: Pandas는 기본 정렬되지만 Polars는 기본 비정렬이다. 정렬이 필요하면 maintain_order=True를 붙일 것.
- string 타입: Pandas는 object 타입에 string을 섞어 넣는 것을 허용하지만 Polars는 타입이 엄격하다. 마이그레이션 시 dtype 감사가 필요하다.
- apply 함수: Polars에서 .map_elements()로 바뀌었고 느리다. 가능하면 Expression API로 벡터화할 것.
점진적 전환 로드맵
- 1단계: 새로 짜는 ETL 스크립트만 Polars로 시작한다. 기존 코드는 건드리지 말 것.
- 2단계: 성능 문제가 있는 배치 작업을 Polars로 리팩터링한다. Pandas 인터페이스는 경계면에서만 유지한다.
- 3단계: 팀 전체 표준을 Polars로 전환한다. 분석/시각화 단계만 Pandas를 병행한다.
- 4단계: scikit-learn 1.4+ 등 Polars 네이티브 지원이 확대되면 완전 이관한다.
Pandas vs Polars 최종 선택 가이드
Pandas vs Polars 비교를 2026년 기준으로 다시 보면 답은 "둘 다 쓴다"이다. Polars는 Apache Arrow 기반 컬럼형 스토리지, 멀티스레딩, lazy evaluation 쿼리 옵티마이저로 Pandas 대비 5~30배 빠른 것이 팩트다. 특히 5GB 이상의 데이터 처리나 프로덕션 ETL에서는 Polars가 압도적이다.
다만 Polars가 완벽한 것은 아니다. 생태계 호환성, 학습 곡선, 한국어 자료 부족은 여전한 단점이다. scikit-learn 1.4+가 Polars를 직접 지원하긴 하지만 matplotlib이나 seaborn까지 가면 결국 Pandas 변환이 필요하다. 그래서 2026년의 현실은 "무거운 ETL은 Polars, 분석·시각화는 Pandas"라는 하이브리드 전략이 가장 많이 채택되는 상황이다.
지금 10GB CSV 앞에서 Pandas로 메모리가 터지고 있다면 오늘 당장 pip install polars를 쳐도 된다. 다만 1GB 이하 데이터로 EDA만 하고 있다면 굳이 갈아탈 이유는 없다. 선택은 데이터 크기와 워크플로우 맥락에 따라 달라진다. 적어도 이제는 Polars를 모르면 안 되는 시대인 것은 확실하다.
참고 자료
'AI LLM' 카테고리의 다른 글
| Harness 엔지니어링을 왜 '돌린다'고 표현하는가? AI 에이전트 환경 설계 철학 파헤치기 (0) | 2026.04.23 |
|---|---|
| 로블록스 맵을 MCP로 만든다고? (0) | 2026.04.23 |
| Claude Code 보안 사고 7선 정리 — 방지 설정까지 모두 수록 (0) | 2026.04.23 |
| Claude Code 소스 코드 유출에서 배우는 하네스 패턴 10선 (1) | 2026.04.23 |
| 구글이 공개한 DESIGN.md, 이것이 무엇이기에 이토록 주목받는가 (0) | 2026.04.22 |
