πŸ”‘πŸ”— PK / FK μ™„μ „ 정리 | κ°œλ…, 예제, μ‹€μŠ΅ ν›„κΈ°κΉŒμ§€!

JOPOΒ·2025λ…„ 4μ›” 5일
0

λ°μ΄ν„°λ² μ΄μŠ€

λͺ©λ‘ 보기
6/7
post-thumbnail

κ²Œμ‹œνŒ ν”„λ‘œμ νŠΈμ—μ„œ νšŒμ›κ³Ό κ²Œμ‹œκΈ€μ„ λ‚˜λˆ„μ–΄ μ„€κ³„ν•˜λ©° PK와 FKλ₯Ό 직접 μ‚¬μš©ν•΄λ΄€μ–΄μš”. μ‹€μŠ΅ μ€‘μ—λŠ” 'μ™œ 이런 μ œμ•½ 쑰건이 κΌ­ ν•„μš”ν•˜μ§€?'λΌλŠ” 고민도 ν–ˆμ§€λ§Œ, 데이터λ₯Ό μ—°κ²°ν•˜κ±°λ‚˜ 였λ₯˜λ₯Ό λ§‰λŠ” 데 μžˆμ–΄ 정말 μ€‘μš”ν•œ 역할을 ν•œλ‹€λŠ” κ±Έ ν™•μ‹€νžˆ λŠλ‚„ 수 μžˆμ—ˆμ–΄μš”. κ°œλ… 정리와 ν•¨κ»˜ μ‹€μŠ΅ κ²½ν—˜λ„ ν•¨κ»˜ λ‹΄μ•„λ΄€μŠ΅λ‹ˆλ‹€!!


πŸ“š λͺ©μ°¨


πŸ”‘ κΈ°λ³Έ ν‚€(PK)λž€?

κΈ°λ³Έ ν‚€(Primary Key)λŠ” ν…Œμ΄λΈ”μ—μ„œ 각 ν–‰(row)을 κ³ μœ ν•˜κ²Œ 식별할 수 μžˆλ„λ‘ 보μž₯ν•˜λŠ” μ—΄(컬럼)μ΄μ—μš”.
NULL 값이 λ“€μ–΄κ°ˆ 수 μ—†κ³ , 쀑볡도 ν—ˆμš©λ˜μ§€ μ•Šμ•„μš”. ν•œ ν…Œμ΄λΈ”μ— λ°˜λ“œμ‹œ ν•˜λ‚˜λ§Œ μ‘΄μž¬ν•  수 있죠.

CREATE TABLE Member (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    email VARCHAR(100)
);

🧭 λΉ„μœ ν•˜μžλ©΄, κΈ°λ³Έ ν‚€λŠ” 'μ£Όλ―Όλ“±λ‘λ²ˆν˜Έ'μ˜ˆμš”.
각각의 μ‚¬λžŒμ΄ ν•˜λ‚˜μ”©λ§Œ κ°€μ§€κ³  μžˆμ–΄μ•Ό ν•˜κ³ , μ ˆλŒ€ μ€‘λ³΅λ˜λ©΄ μ•ˆ 되죠!

PKκ°€ μžˆμ–΄μ•Ό 각 데이터λ₯Ό ꡬ뢄할 수 있고, ν…Œμ΄λΈ”μ—μ„œ μ •ν™•νžˆ μ›ν•˜λŠ” 데이터λ₯Ό 찾을 수 μžˆμ–΄μš”.
λ˜ν•œ μžλ™μœΌλ‘œ μΈλ±μŠ€κ°€ μƒμ„±λ˜κΈ° λ•Œλ¬Έμ— 검색 속도에도 이점이 μžˆμ–΄μš”.


πŸ”— μ™Έλž˜ ν‚€(FK)λž€?

μ™Έλž˜ ν‚€(Foreign Key)λŠ” λ‹€λ₯Έ ν…Œμ΄λΈ”μ˜ κΈ°λ³Έ ν‚€λ₯Ό μ°Έμ‘°ν•˜λŠ” μ—΄μ΄μ—μš”.
두 ν…Œμ΄λΈ” κ°„μ˜ 관계λ₯Ό λ§Ίμ–΄μ£ΌλŠ” μ—°κ²° 고리 역할을 ν•˜μ£ .

CREATE TABLE Post (
    id INT PRIMARY KEY,
    title VARCHAR(100),
    content TEXT,
    member_id INT,
    FOREIGN KEY (member_id) REFERENCES Member(id)
);

πŸͺ’ λΉ„μœ ν•˜μžλ©΄, μ™Έλž˜ ν‚€λŠ” 'λ‹€λ₯Έ ν…Œμ΄λΈ”μ˜ μ‘΄μž¬μ™€ μ—°κ²°λ˜λŠ” 닀리'μ˜ˆμš”.
κ²Œμ‹œκΈ€ ν…Œμ΄λΈ”μ—μ„œ member_idκ°€ Member ν…Œμ΄λΈ”μ˜ idλ₯Ό κ°€λ¦¬ν‚€λŠ” 식이죠.

μ΄λ ‡κ²Œ FKλ₯Ό μ§€μ •ν•˜λ©΄, μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” νšŒμ› IDλ‘œλŠ” κ²Œμ‹œκΈ€μ„ 등둝할 수 μ—†κ²Œ λ˜μ–΄
λ°μ΄ν„°μ˜ μ •ν•©μ„±(무결성)κ³Ό 논리적 연결이 보μž₯λ©λ‹ˆλ‹€.


πŸ” PK, FKκ°€ μ€‘μš”ν•œ 이유

  • λ°μ΄ν„°μ˜ μ •ν•©μ„±(무결성) 보μž₯
    β†’ PKλŠ” μ€‘λ³΅λœ κ°’ 없이 각각의 데이터λ₯Ό μ •ν™•νžˆ κ΅¬λΆ„ν•˜κ²Œ ν•΄μ€˜μš”.
    β†’ FKλŠ” μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 데이터λ₯Ό μ°Έμ‘°ν•˜μ§€ λͺ»ν•˜κ²Œ λ§‰μ•„μ€˜μš”.

  • ν…Œμ΄λΈ” κ°„μ˜ 관계 μ •μ˜
    β†’ νšŒμ›κ³Ό κ²Œμ‹œκΈ€μ²˜λŸΌ, 1:N 관계λ₯Ό λͺ…ν™•νžˆ ν‘œν˜„ν•  수 μžˆμ–΄μš”.

  • ORM(JPA)과의 연계성
    β†’ Java 같은 객체지ν–₯ μ–Έμ–΄μ—μ„œ μ—°κ΄€ 관계λ₯Ό 맺으렀면 DB에도 FKκ°€ μ„€μ •λ˜μ–΄ μžˆμ–΄μ•Ό ν•΄μš”.

πŸ“Œ PK/FK 없이 데이터λ₯Ό μ €μž₯ν•˜λ©΄ ꡬ쑰가 ννŠΈλŸ¬μ§€κ³ ,
λ‚˜μ€‘μ— μˆ˜μ •, μ‚­μ œ, κ²€μƒ‰μ—μ„œ 큰 였λ₯˜κ°€ λ°œμƒν•  수 μžˆμ–΄μš”.


πŸ’» SQL μ˜ˆμ‹œ

-- νšŒμ› ν…Œμ΄λΈ” 생성
-- 각 νšŒμ›μ€ κ³ μœ ν•œ id(PK)λ₯Ό κ°€μ§€λ©°, name은 λ°˜λ“œμ‹œ μž…λ ₯되고(email도 쀑볡 λΆˆκ°€)
CREATE TABLE Member (
    id INT PRIMARY KEY, -- κΈ°λ³Έ ν‚€: 쀑볡 λΆˆκ°€ + NULL λΆˆκ°€
    name VARCHAR(50) NOT NULL, -- 이름은 λ°˜λ“œμ‹œ μž…λ ₯λ˜μ–΄μ•Ό 함
    email VARCHAR(100) UNIQUE NOT NULL -- 이메일은 μ€‘λ³΅λ˜λ©΄ μ•ˆ 됨
);

-- κ²Œμ‹œκΈ€ ν…Œμ΄λΈ” 생성
-- κ²Œμ‹œκΈ€λ§ˆλ‹€ κ³ μœ ν•œ idλ₯Ό κ°–κ³ , λˆ„κ°€ μΌλŠ”μ§€λ₯Ό member_id(FK)λ₯Ό 톡해 μ—°κ²°
CREATE TABLE Post (
    id INT PRIMARY KEY, -- κ²Œμ‹œκΈ€ 고유 μ‹λ³„μž
    title VARCHAR(100) NOT NULL, -- 제λͺ© ν•„μˆ˜
    content TEXT, -- λ‚΄μš©μ€ μ˜΅μ…˜
    member_id INT NOT NULL, -- μž‘μ„±μž 정보 (Member의 id μ°Έμ‘°)
    FOREIGN KEY (member_id) REFERENCES Member(id) -- FK μ„€μ •: μ‘΄μž¬ν•˜λŠ” νšŒμ›λ§Œ κ°€λŠ₯
);

-- κ²Œμ‹œκΈ€ 등둝 μ˜ˆμ‹œ (정상)
-- λ¨Όμ € νšŒμ› 정보λ₯Ό μž…λ ₯ν•˜κ³ , ν•΄λ‹Ή νšŒμ›μ˜ id(1)둜 κ²Œμ‹œκΈ€μ„ 등둝
INSERT INTO Member (id, name, email) VALUES (1, '홍길동', 'hong@example.com');
INSERT INTO Post (id, title, content, member_id) VALUES (1, 'μ•ˆλ…•ν•˜μ„Έμš”', '첫 κΈ€μ΄μ—μš”', 1);

-- κ²Œμ‹œκΈ€ 등둝 μ˜ˆμ‹œ (μ‹€νŒ¨)
-- μ—†λŠ” νšŒμ› 번호(99)둜 κ²Œμ‹œκΈ€μ„ λ“±λ‘ν•˜λ©΄ μ™Έλž˜ ν‚€ μ œμ•½ 쑰건 μœ„λ°˜μœΌλ‘œ 였λ₯˜ λ°œμƒ
INSERT INTO Post (id, title, content, member_id) VALUES (2, 'μ—λŸ¬ λ°œμƒ', '이건 μ‹€νŒ¨ν•  κ±°μ˜ˆμš”', 99);

βœ… μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” νšŒμ› IDλ₯Ό μ°Έμ‘°ν•˜λ €κ³  ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•΄μš”. FKκ°€ λ§‰μ•„μ£ΌλŠ” 덕뢄이죠!
πŸ“Œ μ΄λ ‡κ²Œ PK와 FKκ°€ ν•¨κ»˜ μžˆμ–΄μ•Ό 데이터 κ°„μ˜ μ—°κ²° 관계λ₯Ό μ •ν™•νžˆ μœ μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


⚠️ μ‚¬μš© μ‹œ μ£Όμ˜ν•  점

  • PKλŠ” 무쑰건 μœ μΌν•˜κ³  NULL이면 μ•ˆ 됨
    β†’ μ‹€μˆ˜λ‘œ μ€‘λ³΅λ˜κ±°λ‚˜ NULL이 λ“€μ–΄κ°€λ©΄ μ—λŸ¬ λ°œμƒ
  • FKλŠ” μ°Έμ‘° λŒ€μƒ ν…Œμ΄λΈ”μ˜ 값이 μ‘΄μž¬ν•΄μ•Ό 함
    β†’ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” PKλ₯Ό μ°Έμ‘°ν•˜λ©΄ foreign key constraint μ—λŸ¬κ°€ λ°œμƒν•΄μš”.
  • μ‚­μ œ/μˆ˜μ • μ‹œ μ°Έμ‘° 관계 쑰심!
    β†’ λΆ€λͺ¨ ν…Œμ΄λΈ” 데이터λ₯Ό μ‚­μ œν•˜λ € ν•  λ•Œ, FK둜 μ—°κ²°λœ μžμ‹ ν…Œμ΄λΈ”μ— 데이터가 있으면 μ‚­μ œ λΆˆκ°€
    β†’ 이럴 땐 ON DELETE CASCADE μ˜΅μ…˜μ„ κ³ λ €ν•  수 μžˆμ–΄μš”.

⚠️ ν…Œμ΄λΈ” κ°„ 연관관계λ₯Ό λ§Ίμ„μˆ˜λ‘ ꡬ쑰가 λ³΅μž‘ν•΄μ§€κΈ° λ•Œλ¬Έμ—, 섀계 μ΄ˆκΈ°μ— λͺ…ν™•ν•œ 관계 μ •μ˜κ°€ μ€‘μš”ν•©λ‹ˆλ‹€!


πŸ“ μš”μ•½

ν•­λͺ©μ„€λͺ…
PK각 행을 κ³ μœ ν•˜κ²Œ μ‹λ³„ν•˜λŠ” μ—΄. 쀑볡 λΆˆκ°€, NULL λΆˆκ°€
FKλ‹€λ₯Έ ν…Œμ΄λΈ”μ˜ PKλ₯Ό μ°Έμ‘°. 데이터 κ°„ 관계 μ—°κ²°
ν•„μš”μ„±λ¬΄κ²°μ„± 보μž₯, κ΄€κ³„ν˜• ꡬ쑰 ν‘œν˜„, ORM 맀핑에 ν•„μˆ˜
주의점FK μ°Έμ‘° λŒ€μƒμ€ λ°˜λ“œμ‹œ μ‘΄μž¬ν•΄μ•Ό ν•˜λ©°, PKλŠ” ν…Œμ΄λΈ”λ‹Ή ν•˜λ‚˜λ§Œ μ„€μ • κ°€λŠ₯

🧩 μ •λ¦¬ν•˜μžλ©΄, PKλŠ” β€˜λˆ„κ΅°μ§€ 식별’, FKλŠ” β€˜λˆ„κ΅¬μ™€ μ—°κ²°β€™μ΄μ—μš”!


πŸ“– λŠλ‚€μ 

μ²˜μŒμ—” FK 없이도 λ°μ΄ν„°λ§Œ λ„£μœΌλ©΄ λ˜λŠ” κ±° μ•„λ‹Œκ°€ μ‹Άμ—ˆλŠ”λ°, 막상 μ—†λŠ” νšŒμ› 번호둜 글을 μ“°κ²Œ λ˜λŠ” 상황을 λ³΄λ‹ˆκΉŒ, 'μ•„, 이걸 μ•ˆ μ“°λ©΄ 이런 λ¬Έμ œκ°€ μƒκΈ°λŠ”κ΅¬λ‚˜!' ν•˜κ³  λ°”λ‘œ 싀감할 수 μžˆμ—ˆμ–΄μš”.

직접 μ‹€μŠ΅ν•˜λ©΄μ„œ 였λ₯˜λ„ λ‚˜λ³΄κ³ , μ™œ 이런 μ œμ•½ 쑰건이 ν•„μš”ν•œμ§€ 고민도 ν•΄λ³΄λ‹ˆκΉŒ
PK와 FKκ°€ λ‹¨μˆœν•œ κ·œμΉ™μ΄ μ•„λ‹ˆλΌ 데이터 흐름을 μ§€μΌœμ£ΌλŠ” μ€‘μš”ν•œ μž₯μΉ˜λΌλŠ” κ±Έ μ•Œκ²Œ λμ–΄μš”.

0개의 λŒ“κΈ€