바이브 코딩 시대의 데이터베이스4-2 부모 / 자식 — FK 위치 정하기
테크타니 LEARN — 섹션 04 · DB 모델링

부모 / 자식 —
외래키를 어디에 둘까

섹션 3에서 외래키가 무엇인지는 이미 배웠습니다. 이번에는 만들어진 외래키를 찾는 데서 끝나지 않아요. 업무 규칙을 읽고 왜 외래키가 그쪽 테이블에 있어야 하는지를 직접 판단해 봅니다.

난이도보통소요9분준비물4-1 완료오늘shop 의 네 관계 전부

이번 섹션의 여정

4-1 관계의 구조

완료 ✓

4-2 부모 · 자식

지금 여기

4-3 관계의 종류

1:1 · 1:N · N:M

4-4 ~ 4-7

ERD · 정규화 · 실습

부모와 자식을 정하는 기준은 하나뿐입니다

부모는 다른 테이블이 참조하는 키를 가진 쪽입니다. 보통 기본키를 참조해요. 자식은 부모의 키를 자기 행에 외래키로 기록하는 쪽입니다.

정확히는

관계형 데이터베이스에서는 중복되지 않는 다른 키를 참조할 수도 있습니다. 다만 우리 shop 의 외래키 네 개는 모두 부모의 기본키를 가리킵니다.

이름 때문에 생기는 오해부터 지우고 가겠습니다.

부모 · 자식은 이런 뜻이 아닙니다
이런 뜻일까?아닙니다
부모가 더 중요하고 자식은 덜 중요하다× 중요도와 전혀 관계없다
부모가 오래된 데이터, 자식이 새 데이터다× 데이터의 나이와 무관하다
부모를 먼저 만드니까 부모다× 생성 순서는 기준이 아니라 결과다
테이블을 만들 때 부모를 먼저 만드는 건 — 참조할 테이블이 먼저 필요하다는 결과일 뿐입니다
⭐ 판단 기준어느 쪽의 키가 참조되고, 어느 쪽이 그 키를 외래키로 가지고 있는가.

업무 규칙에서 FK 위치가 나옵니다

“주문 한 건은 회원 한 명의 주문이다” 라는 규칙을 보겠습니다.

주문 한 건을 저장할 때 우리는 “이 주문은 어느 회원의 것인가” 를 기록해야 합니다. 그래서 주문 행이 회원의 번호를 갖습니다. 실제 구조는 orders.member_idmembers.member_id를 참조하죠 — members가 부모, orders가 자식입니다.

반대로 해보면 왜 그래야 하는지가 분명해집니다.

회원 행에 주문 번호를 넣는다면?

members 에 order_id 를 두면
  • 재주문할 때기존 order_id 를 바꾸거나 덮어써야 한다

  • order_id_1 · 2 · 3주문이 늘 때마다 컬럼을 늘려야 한다

  • 결국회원 한 명의 정보에 주문 여러 건을 억지로 밀어 넣게 된다

orders 에 member_id 를 두면 ✓
  • 주문이 추가되면주문 행을 하나 더 만들면 된다

  • 각 행에같은 회원 번호를 기록하기만 하면 된다

  • 구조는 그대로컬럼을 늘릴 일이 없다

외래키 위치는 관습으로 외우는 게 아닙니다 — 각 자식 행이 어느 부모에 속하는지 기록해야 한다는 업무 규칙에서 나옵니다.

관계를 읽는 두 개의 문장

새 관계를 설계할 때는 양쪽에서 문장을 만들어 보세요.

관계 문장 템플릿
① 한 부모는 자식을 최소 몇 개, 최대 몇 개까지 가질 수 있는가?
② 자식 하나는 부모를 반드시 가져야 하는가 · 선택적으로 가져도 되는가 · 최대 몇 개 가질 수 있는가?

회원과 주문에 적용하면 이렇게 됩니다.

회원 — 주문에 적용해 보기
방향질문
부모 → 자식회원 한 명은 주문을 몇 건까지 할 수 있는가?
자식 → 부모주문 한 건은 회원을 반드시 가져야 하는가, 몇 명의 주문인가?
이 질문에 답하면 어느 쪽에 외래키가 필요한지, 그 값이 필수인지가 보입니다
오늘은 '읽기'까지만

최소와 최대 개수를 1:1, 1:N, N:M 같은 표기로 정리하는 방법은 다음 4-3 강의에서 자세히 다룹니다. 오늘은 이 문장으로 관계를 읽는 데 집중하세요.

shop 의 네 관계를 차례로 읽습니다

① members — orders
항목내용
부모 / 자식members(부모) / orders(자식)
외래키orders.member_id → members.member_id
부모 쪽회원 한 명은 주문이 없을 수도, 여러 건일 수도 있다
자식 쪽주문 한 건은 회원 한 명을 반드시 가리킨다
실제 샘플의 17 ~ 20번 회원은 주문이 하나도 없습니다 — 정상입니다

orders.member_idNOT NULL이고 외래키이기 때문에, 비어 있거나 존재하지 않는 회원 번호를 가질 수 없습니다.

② categories — products
항목내용
부모 / 자식categories(부모) / products(자식)
외래키products.category_id → categories.category_id
부모 쪽카테고리 하나에는 상품이 없을 수도, 여러 개일 수도 있다
자식 쪽상품 한 개는 카테고리 한 개를 반드시 가리킨다
현재 샘플은 다섯 카테고리 모두 상품이 있지만 — 구조 자체가 그것을 요구하지는 않습니다
③ orders — order_items
항목내용
부모 / 자식orders(부모) / order_items(자식)
외래키order_items.order_id → orders.order_id
부모 쪽주문 한 건에는 주문상세가 여러 개 들어갈 수 있다
자식 쪽주문상세 한 행은 반드시 주문 한 건에 속한다
외래키가 모든 업무 규칙을 보장하지는 않습니다

현재 외래키만으로는 주문상세가 하나도 없는 주문을 막지 못합니다. 업무에서 “완료된 주문에는 상품이 최소 한 개 있어야 한다” 는 규칙이 필요하다면, 외래키 외의 처리도 함께 설계해야 해요.

④ products — order_items
항목내용
부모 / 자식products(부모) / order_items(자식)
외래키order_items.product_id → products.product_id
부모 쪽상품 한 개는 아직 한 번도 주문되지 않을 수도, 여러 주문상세에 쓰일 수도 있다
자식 쪽주문상세 한 행은 상품 한 개를 반드시 가리킨다
order_items 는 orders 와 products — 두 부모 테이블을 참조합니다

한 행 안의 order_idorders를 가리키고, product_idproducts를 가리킵니다.

부모·자식은 관계마다 달라지는 역할입니다

전체 구조에서 orders를 다시 보겠습니다.

orders 는 부모일까 자식일까
어느 관계에서orders 의 역할이유
members 와의 관계자식회원의 키를 member_id 라는 FK 로 가지고 있다
order_items 와의 관계부모자신의 order_id 가 주문상세에서 참조된다
같은 테이블인데 관계에 따라 역할이 바뀝니다
⭐ 이것만은 꼭

“orders 는 부모 테이블이다” 처럼 단독으로 외우면 안 됩니다. 항상 “어느 테이블과의 관계에서” 부모인지 자식인지 말해야 합니다.

부모와 자식은 테이블에 영구히 붙는 신분이 아니라 — 관계 하나에서 맡는 역할입니다.

부모·자식을 찾은 뒤 남는 두 질문

반드시 물어봐야 할 설계 질문
① 자식이 부모 없이 존재해도 되는가?
② 부모를 삭제할 때 이미 연결된 자식을 어떻게 처리할 것인가?

현재 shop DB의 외래키 네 개는 모두 NOT NULL이라서 자식 행마다 부모가 반드시 필요합니다. 하지만 모든 서비스가 이렇게 설계되는 것은 아닙니다. 연결을 선택 사항으로 둘지, 부모 삭제를 막을지, 다른 방식으로 처리할지는 업무 규칙에 따라 결정해야 해요.

지금은 정답을 외우지 말고 — 반드시 물어봐야 할 설계 질문으로 기억해 두세요.

마스터·트랜잭션은 다른 분류축입니다

실무에서는 부모·자식과 함께 마스터 테이블, 트랜잭션 테이블이라는 말도 자주 듣습니다. 이 둘은 서로 다른 기준이에요.

두 분류축은 따로 봅니다
분류축판단 질문shop 예시
부모 / 자식누가 참조되고 누가 FK 를 가지는가? (관계에서의 역할)orders 는 members 의 자식이자 order_items 의 부모
마스터 / 트랜잭션어떤 성격의 업무 데이터를 담는가? (비즈니스 분류)members · categories · products = 마스터 / orders · order_items = 트랜잭션

회원, 카테고리, 상품처럼 업무의 기준이 되는 정보를 관리하는 테이블은 마스터 성격, 주문처럼 발생한 사건과 그 상세를 기록하는 테이블은 트랜잭션 성격으로 볼 수 있습니다.

'외래키가 없으면 마스터'는 틀린 판단입니다

products마스터 성격이지만 category_id 외래키를 가진 자식입니다. orders트랜잭션 성격이면서 members 의 자식이자 order_items 의 부모예요. 두 축은 서로 독립입니다.

한 줄로마스터·트랜잭션은 데이터의 성격이고, 부모·자식은 관계에서의 역할입니다.

한눈에 정리

관계부모자식외래키
회원 — 주문membersordersorders.member_idmembers.member_id
카테고리 — 상품categoriesproductsproducts.category_idcategories.category_id
주문 — 주문상세ordersorder_itemsorder_items.order_idorders.order_id
상품 — 주문상세productsorder_itemsorder_items.product_idproducts.product_id

부모는 참조되는 키를 가진 쪽이고, 자식은 그 키를 외래키로 기록하는 쪽입니다. 그 역할은 중요도나 생성 순서가 아니라 관계마다 정해집니다.

이제 연결의 방향은 알았습니다. 그런데 한 회원은 주문을 몇 건까지 할 수 있을까요? 주문 한 건은 회원 몇 명의 것일까요? 다음 강의에서 그 개수를 표기로 정리합니다.

NEXT LESSON4-3 관계의 종류 — 1:1, 1:N, N:M

두 방향으로 문장을 만들어 관계의 종류를 가려내고 — N:M 을 연결 테이블로 저장하는 이유를 봅니다.

GO ▸ 4-3 시작하기