본문 바로가기
C.W.K.
Stream
Lesson 10 of 10 · published

오래 버티는 스키마 설계 습관

~15 min · schema, design

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

코드보다 먼저 청사진을 그려

화면이나 ORM 모델부터 만들기 전에 어떤 대상이 있고 서로 어떤 관계를 맺으며 무엇이 절대 깨지면 안 되는지 적어봐. 스키마는 현재 화면의 모양이 아니라 데이터의 수명을 따라가야 해. 먼저 각 대상을 정규화해 별도 테이블로 두고 외래 키로 연결해. 계산된 합계나 중복 이름 같은 비정규화는 측정된 병목이 생겼을 때만 도입해.

스키마를 정직하게 만드는 6가지 습관

  1. 테이블은 복수형처럼 한 가지 이름 규칙을 고르고 users, order_items처럼 뜻을 드러내.
  2. 모든 영속 테이블에 안정적인 기본 키를 두고, 생성 시각인 created_at도 빠뜨리지 마.
  3. 자료형과 NOT NULL, CHECK, 외래 키로 업무 규칙을 데이터베이스가 지키게 해.
  4. created_at 같은 시각은 TIMESTAMPTZ NOT NULL DEFAULT now()처럼 일관되게 저장해.
  5. 아무 테이블에나 table_id 같은 모호한 이름을 쓰지 말고 관계를 이름에 드러내.
  6. 삭제 이력이 필요하면 deleted_at TIMESTAMPTZ 같은 명시적 정책을 정하고 모든 질의가 따르게 해.

updated_at은 데이터베이스가 갱신하게 해

앱의 모든 쓰기 경로가 updated_at을 기억하길 기대하면 빠뜨리는 순간이 와. 트리거를 이용해 UPDATE 때 자동으로 올리면 하나의 규칙으로 통일할 수 있어. 다만 트리거가 숨은 동작이 되지 않도록 마이그레이션과 문서에서 분명히 밝혀.

Code

공통 열을 빠뜨리지 않는 템플릿·sql
CREATE TABLE things (
    id         INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    -- ... 비즈니스 컬럼들 ...
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
updated_at을 자동으로 갱신하는 트리거·sql
CREATE OR REPLACE FUNCTION set_updated_at()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$;

CREATE TRIGGER things_updated_at
BEFORE UPDATE ON things
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
소프트 삭제 패턴·sql
ALTER TABLE things ADD COLUMN deleted_at TIMESTAMPTZ;
CREATE INDEX things_active_idx ON things (id) WHERE deleted_at IS NULL;

-- 앱 컨벤션: view / 재사용 WHERE 에서 삭제 행 필터.
CREATE VIEW active_things AS
  SELECT * FROM things WHERE deleted_at IS NULL;

External links

Exercise

칸반 보드 앱의 전체 스키마를 설계해. 보드는 목록을, 목록은 카드를, 카드는 다대다 관계로 라벨을 가져. 보드에는 역할이 있는 여러 사용자가 참여해. 자료형, 제약, 색인, 외래 키, 표준 시각 열과 갱신 트리거까지 포함해.

Progress

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

댓글 0

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

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