C.W.K.
Stream
Lesson 03 of 06 · published

Spreadsheet 가 무너지는 이유

~10 min · foundation, anti-pattern, history

Level 0구경꾼
0 XP0/47 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

Excel 은 대단한 소프트웨어야. 매일 수억 명이 쓰고, 일의 첫 80% (인터랙티브 탐색, 빠른 what-if, ad hoc 요약) 에선 여전히 맞는 도구. 근데 모든 데이터 엔지니어는 같은 쓴 교훈을 배워: spreadsheet 는 진지한, reproducible, automated 데이터 작업의 substrate 가 아니야. 상처가 보통 도착하는 순서대로:

일곱 가지 실패 모드

  • Reproducibility 없음. Spreadsheet 는 누가 저장 누른 그 순간의 입력 스냅샷이야. 다음 달 데이터로 같은 로직 다시 돌리려면 같은 클릭 체인을 같은 순서로 손으로 해야 하는데 — 같은 순서로 한다고 빌어야 해. Pandas 코드는 설계상 reproducible — git checkout + python pipeline.py = 같은 결과.
  • Scale. Excel row 한계는 1,048,576. 실제론 그보다 한참 전부터 느려. Pandas 는 노트북에서 수천만 행, Polars 와 DuckDB 는 수억, Spark / BigQuery 는 수십억. 데이터 커지면 옮기는 거 옵션 아니야.
  • 숨은 에러. A2:A100 에 row 하나 넣으면 D5A50 참조 수식이 조용히 깨져. 아무도 안 알려줘. 그냥 숫자가 틀려진 거야.
  • 수동 단계는 version control 안 돼. 드래그-fill, 복붙, 수동 필터 — git diff 에 안 나타나. "이 리포트 지난주랑 뭐 바뀐 거야?" 가 답할 수 없는 질문 돼.
  • 협업. 두 분석가가 같은 sheet 에 각자 편집한 거 머지하는 건 — 너그럽게 말해도 — 악몽. Pandas 파이프라인은 Python diff 로 머지돼.
  • 테스트 없음. Spreadsheet 의 로직을 단위 테스트할 합리적인 방법이 없어. 안전하게 리팩터링도 못 해 — regression 잡을 테스트 suite 가 없으니까.
  • 타입 혼동. Excel 은 타입을 auto-detect 하고 공격적이야. US 외 형식의 날짜는 텍스트가 되고, 긴 ID 는 과학 표기로 정밀도를 잃고, 유전자 이름은 날짜로 파싱돼 (이 마지막은 전설의 공포 이야기).

MARCH1 / SEPT4 / DEC1 참사

2016년 Genome Biology 의 한 연구에서, 샘플로 살펴본 유전체학 논문 중 ~20% 가 Excel 의 유전자 이름 자동 변환 오류 — MARCH1, SEPT4, DEC1 이 날짜로 — 때문에 에러를 포함하고 있었어. 너무 끈질긴 문제라서 2020년에 Human Gene Nomenclature Committee 가 실제로 유전자 이름을 Excel 이 안 먹을 심볼로 바꿨어. 다시 말해 — 인류는 spreadsheet 의 auto-detect 동작을 바꿀 수 없어서 생물학 어휘를 바꿨어. 두 번 읽어봐.

그어야 할 선

Spreadsheet 는 사람의 탐색, 일회성 요약 공유, 그리고 끝난 분석의 출력 목적지로 써 (임원은 여전히 깔끔한 XLSX 원해). 분석 자체의 substrate 로는 쓰지 마. Substrate 는 Python 코드, version control, 테스트, 스케줄, 관찰 가능성이야.

Code

Excel 꼭 읽어야 한다면 — 방어적으로·python
import pandas as pd

# 모든 컬럼 일단 string 으로 읽어서 Excel 의 타입 추측 차단
df = pd.read_excel(
    'sales_2026.xlsx',
    sheet_name='Q1',
    dtype=str,            # 다 텍스트로
    keep_default_na=False  # 빈 칸을 NaN 으로 자동 변환 안 함
)

# 의도적으로 cast — 에러 surface 명시
df['order_date']   = pd.to_datetime(df['order_date'], format='%Y-%m-%d', errors='raise')
df['amount_usd']   = pd.to_numeric(df['amount_usd'].str.replace(',', ''), errors='raise')
df['gene_symbol']  = df['gene_symbol'].astype('string')   # MARCH1 은 MARCH1 으로

# 이상한 거 있으면 지금 raise — 새벽 3시 prod 에서 말고
assert df['order_date'].notna().all(), '깨진 날짜 row 가 통과됨'

External links

Exercise

날짜 컬럼 있는 아무 Excel 파일이나. Excel 에서 CSV 로 저장. 텍스트 에디터로 CSV 열어. 셀에서 보이는 날짜 포맷이랑 disk 에 실제로 쓰인 거 비교해. Excel 의 표시 포맷이랑 underlying serialization 이 다른 경우가 자주 있어 — 그 disagreement 가 데이터 corruption 이 사는 곳이야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.