키 (Key)
기본키(PK)와 외래키(FK), UNIQUE 제약과의 차이를 프로젝트 예시로 먼저 보고, 이어서 식별자를 이론적으로 어떻게 분류하는지 정리했습니다.
기본키(Primary Key, PK)
한 테이블 안에서 각 행을 유일하게 식별하는 값입니다. NULL이 될 수 없고, 중복될 수 없습니다. 이 프로젝트에서는 4개 테이블 모두 INTEGER PRIMARY KEY AUTOINCREMENT를 써서, 행을 추가할 때마다 SQLite가 1씩 증가하는 ID를 자동으로 채워줍니다.
외래키(Foreign Key, FK)
다른 테이블의 PK 값을 그대로 저장해서 두 테이블을 연결하는 컬럼입니다. FK가 걸려 있으면 DB 엔진이 "이 값이 부모 테이블에 실제로 존재하는가"를 강제로 검사합니다. 존재하지 않는 값을 넣으려고 하면 FOREIGN KEY constraint failed 에러로 막히는데, 이건 03_queries.sql의 무결성 검증 부분에서 직접 확인했던 바로 그 내용입니다.
PK와 FK 비교
| 구분 | PK (기본키) | FK (외래키) |
|---|---|---|
| 역할 | 자기 테이블에서 각 행을 유일하게 식별 | 다른 테이블의 PK를 가리킴 |
| 중복 | 불가능 | 가능 (여러 자식 행이 같은 부모를 가리킬 수 있음) |
| NULL 허용 | 불가능 | 컬럼 설계에 따라 다름 (이 프로젝트는 전부 NOT NULL) |
| 테이블당 개수 | 보통 1개 | 여러 개 가능 (likes, comments는 FK가 2개씩) |
UNIQUE와 PRIMARY KEY의 차이
둘 다 "중복을 막는다"는 점은 같지만, PK는 테이블마다 사실상 하나(그 테이블의 정체성)이고 NULL을 허용하지 않는 반면, UNIQUE는 한 테이블에 여러 개 걸 수 있습니다. 이 프로젝트에서는 users.username, users.email에 각각 UNIQUE를 걸어서 "식별자로 쓰진 않지만 중복은 안 되는 값"을 표현했고, likes(user_id, reel_id)에는 두 컬럼을 묶은 복합 UNIQUE를 걸어서 "이 조합은 한 번만 존재해야 한다"를 표현했습니다.
식별자의 종류: 주식별자, 보조식별자, 인조식별자
식별자는 테이블의 한 행(인스턴스)을 유일하게 구분해주는 속성(또는 속성 묶음)입니다. 좋은 식별자는 아래 4가지를 만족해야 합니다.
- 유일성: 중복되면 안 됨
- 최소성: 꼭 필요한 속성만으로 구성 (쓸데없이 많이 묶지 않기)
- 불변성: 한번 정해지면 값이 안 바뀜
- 존재성: NULL(빈 값)이면 안 됨
공백 문자열은 NULL과 다르다
존재성은 "NULL이면 안 된다"는 뜻입니다. 공백 문자열(' ')을 허용할지는 존재성과는 별개로, 업무 규칙에 따라 따로 정합니다.
이 식별자를 몇 가지 기준으로 나눠볼 수 있습니다.
대표로 뽑혔는가
- 주식별자(PK): 테이블당 딱 하나, 행을 대표해서 식별하는 속성. NULL 불가.
- 보조식별자: 유일성은 있지만 대표로 뽑히지 못한 속성. 예: 사원번호가 PK일 때 주민등록번호는 보조식별자.
업무에서 자연스럽게 나왔는가, 인위적으로 만들었는가
- 본질식별자: 업무 과정에서 자연스럽게 생긴 속성 그대로 (예: 주문일자 + 상품코드)
- 인조식별자(Surrogate Key): 본질식별자가 너무 복잡하거나 여러 속성으로 얽혀 있을 때, 관리 편의를 위해 인위적으로 새로 만든 식별자. 보통 자동 증가 번호나 UUID를 씁니다 (예: 주문일자+상품코드 대신 새로 만든 "주문번호").
속성 하나인가, 여러 개를 묶었는가
- 단일 식별자: 속성 1개로 유일성 확보
- 복합 식별자: 여러 속성을 합쳐야 유일성이 나옴 (예: 학번+과목코드)
스스로 만들어졌는가, 남한테 물려받았는가
- 내부식별자: 자기 테이블 안에서 자체적으로 생성
- 외부식별자: 다른 테이블과의 관계를 통해 물려받은 식별자, 즉 FK
한눈에 비교
| 분류 기준 | 무엇을 보나 | 식별자 종류 |
|---|---|---|
| 대표성 | PK로 뽑혔는가 | 주식별자 vs 보조식별자 |
| 생성 방식 | 업무에서 자연스럽게 생겼나, 인위적으로 번호를 붙였나 | 본질식별자 vs 인조식별자 |
| 속성 수 | 컬럼이 1개인가, 2개 이상인가 | 단일식별자 vs 복합식별자 |
| 상속 여부 | 스스로 만들었나, 부모에게 물려받았나(FK) | 내부식별자 vs 외부식별자 |
보조식별자도 여러 속성을 묶어서 만들 수 있습니다. 학번이 주식별자인 학생 테이블에서 "학년 + 반 + 번호"를 묶으면 한 학생을 찾을 수 있는데, 이런 걸 복합 보조식별자라고 합니다.
연습 문제: 식별자 분류
직접 풀어 본 식별자 분류 문제 (이미지)

정리
| 개념 | 핵심 |
|---|---|
| PK | 행을 유일하게 식별, NULL·중복 불가, 테이블당 보통 1개 (예: INTEGER PRIMARY KEY AUTOINCREMENT) |
| FK | 다른 테이블의 PK를 저장해 연결, 중복 가능, 테이블당 여러 개 가능, 없는 값은 FOREIGN KEY constraint failed |
| UNIQUE | 중복만 막음, 한 테이블에 여러 개 가능, 복합 UNIQUE로 조합 중복도 방지 |
| 좋은 식별자 | 유일성 · 최소성 · 불변성 · 존재성 |
| 식별자 분류 | 주/보조, 본질/인조(Surrogate Key), 단일/복합, 내부/외부(FK) |
출처: Codyssey-B1/B6-1
참고: 개인 Notion 학습 노트
