데이터베이스 용어 사전
관계 모델FK · Foreign Key · 참조 무결성 · CASCADE

외래키

다른 테이블의 키를 가리키는 속성. 존재하지 않는 행을 가리킬 수 없게 DB가 강제한다.

다른 테이블(또는 자기 자신)의 기본키·유니크 키를 가리키는 속성. 이걸로 참조 무결성이 지켜진다.

무엇을 막아 주나

CREATE TABLE orders (
  id        BIGINT PRIMARY KEY,
  member_id BIGINT NOT NULL REFERENCES member(id)
);

INSERT INTO orders (id, member_id) VALUES (1, 99999);
-- ERROR: insert or update on table "orders" violates foreign key constraint
--        Key (member_id)=(99999) is not present in table "member".

존재하지 않는 회원의 주문이 만들어질 수 없다. 애플리케이션 코드가 아무리 많아도 이 한 줄이 최종 방어선이다.

삭제·갱신 시 동작을 정한다

CREATE TABLE orders (
  member_id BIGINT REFERENCES member(id)
      ON DELETE CASCADE       -- 회원을 지우면 그 주문도 함께 지운다
      ON UPDATE CASCADE       -- 회원 id 가 바뀌면 따라 바꾼다
);
옵션부모를 지울 때
NO ACTION / RESTRICT거부한다 (기본값)
CASCADE자식도 함께 지운다
SET NULL자식의 참조를 NULL로 만든다
SET DEFAULT기본값으로 바꾼다

CASCADE는 신중해야 한다. 회원 하나를 지웠는데 주문·결제·배송이 연쇄로 사라질 수 있고, 그 연쇄가 어디까지 가는지 SQL만 봐서는 잘 안 보인다. 실무에서는 RESTRICT로 막고 소프트 삭제(deleted_at 칼럼)를 쓰는 경우가 많다.

성능에서 자주 데는 지점 — FK에 인덱스가 자동으로 안 생긴다

-- PostgreSQL: FK 를 만들어도 자식 쪽에는 인덱스가 생기지 않는다
CREATE INDEX idx_orders_member ON orders (member_id);   -- 직접 만들어야 한다

인덱스가 없으면 부모를 지울 때마다 자식 테이블을 풀 스캔해 참조를 확인한다. 그리고 그동안 자식 테이블에 락이 걸린다.

-- 인덱스 없는 FK 찾아내기 (PostgreSQL)
SELECT c.conrelid::regclass AS child, a.attname AS column
  FROM pg_constraint c
  JOIN unnest(c.conkey) k ON true
  JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = k
 WHERE c.contype = 'f'
   AND NOT EXISTS (SELECT 1 FROM pg_index i
                    WHERE i.indrelid = c.conrelid AND a.attnum = i.indkey[0]);

MySQL InnoDB는 FK 생성 시 인덱스를 자동으로 만들어 준다 — 두 엔진의 차이라 이식할 때 놓치기 쉽다.

FK를 아예 안 거는 선택

안 거는 쪽의 논리 대량 쓰기 성능 · 샤딩 · 마이그레이션 유연성

  • 거는 쪽의 논리 — 애플리케이션 버그가 데이터를 망가뜨리는 걸 DB 가 막는다

대규모 서비스에서 FK를 빼는 사례가 있지만, 그건 정합성 검증을 애플리케이션과 배치로 옮겨 오는 거래다. 검증 체계 없이 그냥 빼면 고아 행이 쌓인다.

-- 고아 행 점검 (FK 를 안 걸었다면 주기적으로 돌려야 한다)
SELECT o.* FROM orders o
  LEFT JOIN member m ON o.member_id = m.id
 WHERE m.id IS NULL;

면접 함정

  • "FK를 걸면 인덱스가 생긴다" → PostgreSQL은 안 생긴다. MySQL은 생긴다.
  • "FK가 있으면 애플리케이션 검증은 불필요" → 사용자에게 보여줄 오류 메시지는 애플리케이션 몫이다. FK는 최후의 방어선이지 UX가 아니다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 관계 모델 — 왜 테이블인가·키·무결성·집합대수