C.W.K.
Stream
Lesson 02 of 10 · published

파일이랑 스프레드시트는 왜 깨지냐

~14 min · foundations, comparison

Level 0스키마 새싹
0 XP0/86 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

금요일 회의 스토리

'진짜' 데이터를 Google Sheet 로 공유해본 모든 팀이 겪은 일이야: 월요일에 두 사람이 동시에 행 붙여넣어서 한쪽 데이터 사라짐. 화요일에 컬럼 이름 바뀌어서 downstream 스크립트 조용히 깨짐. 목요일에 누가 숫자 자리에 "N/A" 박아서 SUM 이 string 에러 뱉음. 금요일에 긴급 회의 — 시트 '정리'하자는 게 결론. 즉, 손으로 수백 행 수정.

스프레드시트랑 CSV 가 스케일에서 깨지는 건 멍청해서가 아니라, 프로덕션 데이터가 매초 필요로 하는 세 가지를 강제할 설계가 안 돼있어서야 — 동시성 제어 (두 writer 충돌 시 누가 이김), 데이터 정합성 (스키마 어기는 행 거절), 효율적 쿼리 (5천만 행에서 한 행 50ms 안에 찾기).

대신 데이터베이스가 하는 일

PostgreSQL 은 INSERT 시점에 잘못된 행 거절. 두 트랜잭션이 동시에 이길 수 없음. 인덱스가 linear scan 을 logarithmic lookup 으로 바꿔. 이 quest 의 나머지가 풀어줄 ACID 보장은 학술 얘기가 아냐 — 금요일 회의 vs '그냥 잘 돌아감' 의 차이지.

그래도 CSV 가 맞을 때

파일은 데이터 교환 (export, 공유, 보관) 이랑 config 에는 훌륭해. 한 프로세스 이상이 쓰거나, 행 단위로 진지한 질문 던질 필요 생기는 순간부터 안 좋아져. DB 로 가야 하는 신호가 정확히 이거 — "writer 가 둘 이상이거나, 쿼리가 trivial 이상."

Code

스키마가 입구에서 쓰레기 거절·sql
CREATE TABLE orders (
    id       INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    customer TEXT    NOT NULL,
    product  TEXT    NOT NULL,
    price    NUMERIC(10,2) NOT NULL CHECK (price > 0),
    placed_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- 셋 다 경계에서 거절. 하나도 안 들어옴.
INSERT INTO orders (customer, product, price) VALUES ('Alice', 'Widget', NULL);
-- ERROR: null value in column "price" violates not-null constraint

INSERT INTO orders (customer, product, price) VALUES ('Bob', 'Gadget', -5);
-- ERROR: new row for relation "orders" violates check constraint

INSERT INTO orders (customer, product, price) VALUES ('Carol', 'Bolt', 'free');
-- ERROR: invalid input syntax for type numeric: "free"
두 writer, 한 진실·sql
-- Session A                         | -- Session B (동시)
BEGIN;                               | BEGIN;
UPDATE products SET stock = stock-1  | UPDATE products SET stock = stock-1
  WHERE id = 7;                      |   WHERE id = 7;
COMMIT;                              | COMMIT;
-- PostgreSQL 이 직렬화해서 stock 이 정확히 두 번 감소.
-- 스프레드시트는 한쪽 write 를 조용히 잃어버려.

External links

Exercise

갖고 있는 CSV 하나 골라 (없으면 10 행짜리 만들어). 동등한 PostgreSQL CREATE TABLE 설계 — 모든 컬럼 타입, 필수 필드 NOT NULL, 최소 한 개 CHECK. \copy 로 로드하고 어느 행을 거절하는지 관찰.

Progress

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

댓글 0

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

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