https://2stndard.tistory.com/notice/203
[발간예정][EPL과 유튜브로 배우는 DuckDB] 실습 코드와 데이터
EPL과 유튜브 데이터로 배우는 DuckDB에서 사용되는 실습 데이터와 코드를 제공합니다. EPL_DATA&samplefile.zip : 책에서 사용하는 영국 프리미어리그 데이터 셋과 샘플로 사용하는 파일espn.duckdb.zip : 책
2stndard.tistory.com
모든 데이터 과학자는 이런 순간이 한 번쯤 찾아옵니다. 바로 Pandas의 read_csv() 함수가 갑자기… 멈춰버리는 순간이죠. 맥북 팬이 요란하게 돌아가기 시작하고, 커널이 다운되며, 진행률 바는 40%를 넘지 못한 채 멈춰 서 있습니다. 이런 벽에 부딪혀 본 적이 있다면, 이 글이 무엇에 관한 것인지 이미 짐작하셨을 겁니다.
수년 동안 Pandas는 파이썬 데이터 작업의 확실한 공통 언어였습니다. 사실상 파이썬에서 DataFrame이라는 개념을 창안해낸 주역이기도 하죠. 하지만 Pandas가 설계된 당시의 세계—적당한 규모의 데이터셋, 싱글 스레드 노트북, 대규모 언어 모델(LLM) 이전의 시대—는 더 이상 데이터 분석가들이 살아가는 현실이 아닙니다.
폴라(Polars)와 덕DB(DuckDB)가 등장했습니다. 두 가지 도구, 두 가지 철학, 하나의 공통된 사명: 대규모 데이터 분석을 빠르고, 메모리 효율적이며, 개발자 친화적으로 만드는 것입니다. 하지만 과연 이들이 정말로 판다스를 몰아내고 있을까요? 아니면 파이썬 커뮤니티가 또다시 반짝이는 새 도구를 과대평가하고 있는 것일까요?
코드, 벤치마크, 그리고 솔직한 의견을 통해 그 답을 찾아봅시다.
세 가지 프레임워크를 만나봅시다
다음은 중요한 배경입니다. Polars와 DuckDB는 Pandas의 문제점이 널리 알려진 후에 설계되었습니다. 이 라이브러리의 개발자들은 지난 10년 동안 커뮤니티가 겪어온 불편함을 교훈으로 삼았을 뿐만 아니라, Apache Arrow와 최신 CPU 명령어 세트, 그리고 분산 시스템 사고방식에서 얻은 통찰력을 활용할 수 있었습니다.
속도 벤치마크: 1억 행, 가차 없는 테스트
다음 결과는 필자의 노트북(ntel(R) Core(TM) Ultra 5 125H(3.60 GHz), 16.0GB)에서 실행한 5.7GB CSV(trending_yt_videos_113_countries.csv)을 대상으로 수행한 결과입니다.

Pandas는 5GB 크기의 CSV 파일을 불러오는 데 48초 이상 걸렸습니다. Polars는 20초도 채 걸리지 않았습니다. 디스크에서 직접 같은 파일을 조회한 DuckDB는 1초도 걸리지 않았습니다. 이 격차가 워낙 커서 논의의 맥락 자체가 완전히 달라집니다.
Polars는 순수 인메모리 필터링 분야에서 압도적인 성능을 자랑합니다. 1억 행의 데이터 처리 시 Pandas보다 4배 이상 더 빠릅니다. 이는 Pandas가 단일 스레드에서 작업하는 반면, Polars는 모든 CPU 코어를 동시에 활용하기 때문입니다.

“Polars와 DuckDB는 대개 동일한 작업을 30초 이내에 완료합니다. Pandas가 하나의 코어만 사용하는 동안, Polars는 8개 코어 모두를 활용하고 있습니다.” ANALYTICS INSIGHT, 2026
Pandas: 즉각적인 처리를 지향하는 단일 스레드 베테랑
Pandas는 NumPy 배열과 즉각적인 실행 모델을 기반으로 구축되었습니다. df.groupby()를 작성하면 Pandas는 이를 즉시 실행하며 모든 데이터를 RAM에 불러옵니다. Pandas에는 쿼리 최적화기가 없으며, 필요 없는 데이터를 건너뛸 수 있는 기능도 없고, 무엇보다도 대부분의 연산에서 두 개 이상의 CPU 코어를 활용할 방법이 없습니다.
2008년 당시에는 이러한 설계가 완전히 타당했습니다. 대부분의 데이터셋은 RAM에 들어갈 수 있었고, 대부분의 노트북에는 활용할 만한 코어가 하나 정도 있었기 때문입니다. 하지만 오늘날의 데이터는 더 이상 그런 규칙을 따르지 않습니다.
import pandas as pd
# Loads ENTIRE file into RAM before you can do anything
df = pd.read_csv("./trending_yt_videos_113_countries.csv") # 💀 5GB+ = pray
result = (
df[df["view_count"] > 1_000_000]
.groupby("country")["view_count"]
.sum()
.reset_index()
.sort_values("view_count", ascending=False)
)
Polars: Rust로 구현된 데이터프레임 킬러
Polars는 가비지 컬렉터 없이 속도와 안전성을 위해 설계된 언어인 Rust로 완전히 작성되었습니다. 이 라이브러리의 주요 혁신은 세 가지입니다. 첫째, 열 기반이며 캐시 효율이 뛰어난 Apache Arrow를 메모리 내 형식으로 사용합니다. 둘째, 기본적으로 멀티스레드 실행을 지원하여 사용 가능한 모든 CPU 코어를 자동으로 활용합니다. 셋째, 지연 평가(lazy) API를 통해 쿼리 계획을 먼저 수립한 후, 실제로 필요한 부분만 실행하는 '프레디케이트 푸시다운(predicate pushdown)' 기법을 사용합니다.
import polars as pl
# Nothing executes yet — Polars builds an optimized query plan
result = (
pl.scan_csv("./trending_yt_videos_113_countries.csv") # lazy scan, not loaded yet
.filter(pl.col("view_count") > 1_000_000)
.group_by("country")
.agg(pl.col("view_count").sum())
.sort("view_count", descending=True)
.collect() # ⚡ NOW it executes, optimized, multi-threaded
)
DuckDB: Python 프로세스 내에서 SQL을 실행하세요
DuckDB는 근본적으로 다른 접근 방식을 취합니다. 이는 데이터프레임(DataFrame) 라이브러리가 아니라, Python 프로세스 내에서 직접 실행되는 임베디드 OLAP 데이터베이스입니다. 별도의 서버나 Docker 컨테이너, 연결 문자열이 필요하지 않습니다. pip install duckdb만 실행하면 CSV 파일, Parquet 파일, 기존 데이터프레임은 물론 원격 S3 버킷에 대해서도 SQL 쿼리를 작성할 수 있습니다.
import duckdb
# Query a file directly — it never fully loads into RAM
result = duckdb.sql("""
SELECT
country,
SUM(view_count) AS total
FROM './trending_yt_videos_113_countries.csv'
WHERE view_count > 1000000
GROUP BY country
ORDER BY total DESC
""") # convert to pandas if needed — zero-copy via Arrow
DuckDB는 별도의 변환이나 복사 과정 없이 SQL을 사용하여 기존 Pandas DataFrame을 쿼리할 수 있습니다. 이 도구는 DataFrame을 프로세스 내에 등록하여 데이터베이스 테이블처럼 처리합니다. 이 기능만으로도 현재 사용 중인 어떤 도구와 함께 설치할 가치가 충분합니다.
메모리: RAM만으로는 부족할 때
속도도 중요하지만, 실제 운영 환경에서는 메모리 문제가 가장 큰 걸림돌이 됩니다.
Pandas는 쿼리 한 줄도 실행하기 전에 전체 데이터셋을 RAM에 불러옵니다. 이것이 바로 ‘이거어 실행(eager execution)’ 문제입니다. CSV 파일 크기가 10GB이고 RAM이 16GB라면 운이 좋으면 괜찮겠지만, 그렇지 않으면 데모 직전에 MemoryError가 발생하고 커널이 다운될 수 있습니다.
Polars의 지연(lazy) API는 투영(projection) 프루닝을 적용하여, 데이터를 읽기 전에 필요한 열과 행을 파악하고 나머지는 모두 건너뜁니다. 독립적인 벤치마크 결과, 동일한 조인 작업에서 Pandas에 비해 피크 메모리 사용량이 30~60% 더 낮게 나타났습니다.
DuckDB는 한 걸음 더 나아갑니다. 사용 가능한 RAM을 초과하는 데이터가 있을 경우 SSD를 임시 작업 공간으로 활용하여 자동으로 디스크에 데이터를 스필(spill)할 수 있습니다. 순수 RAM 실행보다 속도는 느리지만, 시스템이 다운되는 것보다는 훨씬 낫습니다. 덕분에 DuckDB는 이 세 가지 도구 중 유일하게 노트북에서 진정한 아웃-오브-코어(out-of-core) 워크로드를 현실적으로 처리할 수 있는 도구입니다.
인체공학: 어떤 것이 코딩하기 더 편할까?
API 때문에 노트북을 창밖으로 던져버리고 싶게 만든다면, 순수한 속도만으로는 아무 소용이 없습니다. 그렇다면 이 세 가지 도구는 개발자 경험 측면에서 어떻게 비교될까요?
Pandas: 익숙한 혼란
Pandas는 15년 동안 축적된 API 설계 결정들을 가지고 있는데, 그중에는 훌륭한 것도 있고 당혹스러운 것도 있습니다.
df.apply()의 함정. .loc과 .iloc 사이의 모호함. 악명 높은 SettingWithCopyWarning.
하지만 익숙함은 강력한 힘입니다. 수년 동안 Pandas를 사용해 왔다면, 그 관성으로 사용합니다.
Polars: 엄격하고, 조합 가능하며, 중독성 있는
Polars는 사용자가 명시적으로 표현하도록 강요하는, 더 확고한 견해를 가진 API를 가지고 있습니다. 암시적 인덱스도, 모호한 열 선택도 없습니다. pl.col("x").cast(pl.Float64).round(2)를 연결하는 표현식 API는 DataFrame과 씨름하는 것이 아니라 함수를 조합하는 듯한 느낌을 줍니다. 일단 익숙해지면, 이 엄격함은 버그가 아닌 장점이 됩니다. 스키마 오류는 실행 시점이 아닌 실행 계획 수립 시점에 드러납니다.
DuckDB: SQL을 사랑하는 모든 이를 위해
DuckDB의 장점은 간단합니다. SQL을 안다면, 이미 DuckDB를 아는 셈입니다. 새로운 Python API를 배우는 대신, SELECT * FROM 'data.csv' WHERE amount > 100을 작성하면 결과를 얻을 수 있습니다. 데이터 웨어하우징이나 BI 배경을 가진 분석가들에게 이는 해방감을 줍니다. 외워야 할 새로운 메서드도, 배워야 할 표현식 DSL도 없습니다. 이미 알고 있는 SQL만으로도, 데이터베이스 속도로 로컬에서 실행할 수 있습니다.
하이브리드 스택: 선택은 그만, 조합을 시작하라
대부분의 비교 블로그가 간과하는 가장 중요한 점은 바로 이것입니다. 꼭 하나만 골라야 할 필요는 없다는 것입니다.
Apache Arrow 덕분에 Pandas, Polars, DuckDB는 사실상 복사 비용 없이 서로 데이터를 주고받을 수 있습니다. 이들은 동일한 기본 메모리 형식을 공유하므로, Polars DataFrame을 Pandas DataFrame으로 변환하거나 DuckDB 쿼리를 실행할 때 시리얼라이제이션 오버헤드가 발생하지 않습니다.
경험이 풍부한 데이터 팀들이 점차 수렴해 가는 패턴은 다음과 같습니다

그렇다면 Pandas는 이제 끝난 걸까요?
아닙니다. 솔직히 말해, 그 질문 자체가 잘못된 관점입니다.
Pandas는 사라지는 것이 아니라 그 영역이 좁아지고 있을 뿐입니다. Pandas의 영역은 여전히 확실한 강점을 발휘하는 분야, 즉 파이프라인의 마지막 단계, 소규모 데이터셋, Jupyter에서의 탐색적 분석, 그리고 머신러닝 생태계에서 DataFrame 객체가 필요한 모든 곳으로 축소되고 있습니다. Pandas는 여전히 파이썬 데이터 처리 분야에서 초보자에게 가장 친숙하고, 문서화가 가장 잘 되어 있으며, 가장 폭넓게 지원되는 도구입니다.
하지만 매일 수백 메가바이트가 넘는 CSV 파일을 로드하면서도 여전히 판다스만 사용하고 있다면, 상당한 성능 향상의 기회를 놓치고 있는 셈입니다. Polars와 DuckDB는 판다스를 대체하는 도구가 아닙니다. 이들은 판다스로도 충분했던 워크플로우의 특정 부분을 업그레이드해 주는 도구들입니다.그렇다면 Pandas는 이제 끝난 걸까요?
아닙니다. 솔직히 말해, 그 질문 자체가 잘못된 관점입니다.
Pandas는 사라지는 것이 아니라 그 영역이 좁아지고 있을 뿐입니다. Pandas의 영역은 여전히 확실한 강점을 발휘하는 분야, 즉 파이프라인의 마지막 단계, 소규모 데이터셋, Jupyter에서의 탐색적 분석, 그리고 머신러닝 생태계에서 DataFrame 객체가 필요한 모든 곳으로 축소되고 있습니다. Pandas는 여전히 파이썬 데이터 처리 분야에서 초보자에게 가장 친숙하고, 문서화가 가장 잘 되어 있으며, 가장 폭넓게 지원되는 도구입니다.
하지만 매일 수백 메가바이트가 넘는 CSV 파일을 로드하면서도 여전히 판다스만 사용하고 있다면, 상당한 성능 향상의 기회를 놓치고 있는 셈입니다. Polars와 DuckDB는 판다스를 대체하는 도구가 아닙니다. 이들은 판다스로도 충분했던 워크플로우의 특정 부분을 업그레이드해 주는 도구들입니다.
빠른 활용 가이드
Pandas를 사용할 때
데이터가 RAM에 쉽게 들어갈 때, 탐색적 분석을 수행할 때, sklearn 모델에 데이터를 입력할 때, 또는 DataFrame을 사용하는 시각화 라이브러리가 필요할 때.
Polars를 사용할 때
중대형 데이터에 대한 대량의 변환 작업을 수행할 때, 단일 머신에서 가장 빠른 DataFrame 성능을 원할 때, 또는 엄격한 타입 지정과 조합 가능한 표현식을 원할 때.
DuckDB를 사용할 때
데이터가 파일(CSV/Parquet)에 저장되어 있을 때, SQL 방식으로 사고할 때, 분석 쿼리(GROUP BY, 윈도우 함수, 조인)를 수행할 때, 또는 데이터셋이 RAM 용량보다 클 때.
2026년의 데이터 분석가 스택은 단일 도구가 아닙니다. 이는 하나의 워크플로우이며, 각 도구가 실제로 어디에 적합한지 이해하는 것이 능숙한 엔지니어와 좌절하는 엔지니어를 구분하는 진정한 기술입니다.
지금 터미널을 열고 `pip install polars duckdb`를 실행한 다음, 기존 방식을 버리고 나니 CSV 처리에 실제로 얼마나 시간이 걸리는지 확인해 보세요.
'EPL과 유튜브 데이터로 배우는 DuckDB' 카테고리의 다른 글
| DuckDB Tricks - Part 1 (0) | 2026.05.17 |
|---|---|
| DuckLake:레이크하우스 형식의 SQL (0) | 2026.05.16 |
| 모든 데이터 엔지니어가 더 이상 믿어서는 안 될 DuckDB 성능에 관한 7가지 오해 (0) | 2026.05.15 |
| Pandas 사용자의 DuckDB 마스터하기 -Part 1 (0) | 2026.05.15 |
| DuckDB의 오브젝트 스토리지 캐싱(Object-Store Caching) (0) | 2026.05.13 |
댓글