YourERD

ERD 예제 갤러리

세 가지 익숙한 도메인을 통해, 테이블을 단순히 나열하는 것과 관계가 보호해야 할 규칙을 모델링하는 것의 차이를 살펴봅니다. 예제는 출발점입니다. 아래의 판단 기준을 읽고 자신의 요구사항에 맞게 바꿔 보세요.

5개 엔티티주문 이력다대다 해소

1. 쇼핑몰 주문 ERD

사용자는 주문을 만들고, 주문에는 여러 상품이 담기며, 결제는 주문의 상태 변화와 분리해 기록합니다. 이 예제의 핵심은 현재 상품 정보과거 주문 사실을 같은 것으로 취급하지 않는 데 있습니다.

user1 ── Norder1 ── Npayment · order1 ── Norder_productN ── 1product

이 관계가 말하는 것

  • order.user_id는 주문자가 누구인지 가리키는 비식별 외래키입니다. 주문 번호 자체는 사용자 번호와 별개로 식별됩니다.
  • order_product는 주문과 상품의 다대다 관계를 한 행씩 풀어낸 연결 테이블입니다. 수량은 이 관계에 속하는 사실입니다.
  • 샘플의 payment.order_id는 기본키이면서 외래키입니다. 주문을 구성하는 결제 기록이라는 의도를 드러냅니다.

구현 전에 정할 질문

  • 결제 실패·재시도·부분 환불을 각각 한 결제 행의 상태로 둘지, 결제 시도와 환불을 별도 이력으로 둘지 정합니다.
  • 상품명과 판매 단가가 바뀌어도 영수증이 변하면 안 됩니다. 실제 주문상품에는 당시 이름과 단가를 스냅샷으로 추가할지 검토합니다.
  • 배송이 여러 번으로 나뉠 수 있으면 shipmentshipment_item을 주문상품에 연결합니다.

관계선은 “어떤 화면에서 함께 보이는가”가 아니라 “한 사실을 삭제하거나 수정했을 때 다른 사실이 무엇을 보장해야 하는가”를 기준으로 판단합니다. 예를 들어 주문 이력이 있는 상품은 삭제 대신 판매중지 상태로 두는 규칙이 필요할 수 있습니다.

쇼핑몰 샘플을 편집기에서 열기

5개 엔티티작성자와 댓글태그 연결

2. 블로그 ERD

블로그는 작성자, 게시글, 댓글처럼 생명주기가 다른 정보를 나누는 연습에 좋습니다. 게시글에 태그를 직접 쉼표로 적지 않고 연결 테이블을 두는 이유도 한 번에 확인할 수 있습니다.

User1 ── NPost1 ── NComment · Post1 ── NPostTagN ── 1Tag

이 관계가 말하는 것

  • Post.user_id로 한 사용자가 여러 글을 쓸 수 있음을 표현합니다. 게시글의 제목·본문·게시일은 작성자 정보와 분리됩니다.
  • 댓글은 어느 글에 달렸는지와 누가 작성했는지를 모두 참조합니다. 그래서 글을 지우거나 사용자를 탈퇴시킬 때의 보존 규칙을 먼저 정해야 합니다.
  • PostTag는 한 글의 여러 태그와 한 태그의 여러 글을 연결합니다. 같은 태그가 한 글에 중복되지 않도록 실제 DB에서는 (post_id, tag_id) 유니크 제약을 고려합니다.

다음 요구사항이 오면

  • 답글이 필요하면 Comment.parent_comment_id를 선택적 자기 참조로 둡니다. 깊이 제한과 삭제된 부모 댓글의 표시 방식도 함께 정합니다.
  • 공개 전 검수가 필요하면 published_at만으로 충분한지, status와 상태 전이 기록이 필요한지 결정합니다.
  • 사용자 탈퇴 뒤에도 게시글·댓글을 남겨야 한다면 물리 삭제 대신 익명화 또는 비활성화 방식을 검토합니다.

연결 테이블은 관계가 자체 속성을 가질 때 특히 유용합니다. 나중에 태그를 붙인 시각·담당자·정렬 순서가 필요해져도 PostTag에 자연스럽게 추가할 수 있습니다.

블로그 샘플을 편집기에서 열기

2개 엔티티부서 배정자기 참조

3. 인사관리 ERD

인사관리 예제는 같은 테이블이 자기 자신을 참조할 수 있다는 점을 보여 줍니다. 직원은 한 부서에 배정되고, 선택적으로 다른 직원을 관리자(상위 직원)로 가리킬 수 있습니다.

department1 ── Nemployee · employee0..1 ── Nemployee(manager)

이 관계가 말하는 것

  • employee.dept_id는 부서 하나에 여러 직원이 속할 수 있음을 표현합니다. 부서가 먼저 만들어져도 직원이 아직 없을 수 있습니다.
  • employee.parent_emp_id는 같은 employeeemp_id를 가리키는 선택적 외래키입니다. 최고 책임자는 관리자가 없으므로 NULL일 수 있습니다.
  • 직급은 조직도상의 위치와 다릅니다. position은 직급·직책 정책에 따라 별도 코드 테이블로 분리할지를 판단합니다.

운영 규칙으로 보완할 점

  • 한 직원이 자기 자신을 관리자로 지정하거나, A와 B가 서로를 관리자로 만드는 순환을 애플리케이션 또는 DB 제약으로 막습니다.
  • 부서 이동 이력이 중요하면 현재 dept_id만 갱신하지 말고 employee_department_history를 추가합니다.
  • 겸직, 매트릭스 조직처럼 관리자가 여럿일 수 있다면 단일 자기 참조 대신 별도 직원-관리자 관계 테이블을 사용합니다.

자기 참조는 구조를 간결하게 만들지만, 순환·삭제·재귀 조회의 규칙을 함께 설계해야 합니다. “관리자가 없는 직원이 가능한가?” 같은 업무 문장을 먼저 적고 NULL 허용 여부를 정하는 편이 안전합니다.

인사관리 샘플을 편집기에서 열기

샘플을 내 서비스에 맞게 바꾸는 순서

샘플의 테이블 이름을 먼저 복사하기보다, 아래 질문에 답하면서 관계를 수정해 보세요. 이 과정이 있으면 화면 요구사항이 바뀌어도 왜 컬럼과 제약이 필요한지 설명할 수 있습니다.

  1. 한 행이 기록하는 사실을 한 문장으로 씁니다

    예를 들어 주문상품 행은 “특정 주문에 특정 상품을 몇 개, 얼마에 판매했다”는 사실입니다. 이 문장에 없는 값이 섞여 있으면 다른 엔티티나 이력으로 분리해야 할 가능성이 큽니다.

  2. 삭제·변경 뒤에도 남아야 하는 값을 표시합니다

    사용자 이름, 상품명, 소속 부서는 바뀔 수 있습니다. 과거 화면이나 보고서가 당시 값을 보여야 한다면 참조만 둘지, 스냅샷·상태 이력을 함께 둘지 결정합니다.

  3. 데이터베이스가 막아야 할 중복과 누락을 고릅니다

    한 게시글에 같은 태그를 두 번 붙일 수 없는지, 결제 기록 없이 주문이 가능한지처럼 업무 규칙을 유니크·외래키·NOT NULL 제약과 애플리케이션 검증으로 나눠 표현합니다.

예제는 복사본이 아니라 질문 목록입니다

실제 서비스의 이름, 상태 변화, 삭제 규칙, 이력 보존 방식에 맞춰 엔티티와 관계를 바꾸세요. 더 깊은 판단 기준은 데이터 모델링 아티클에서 이어서 볼 수 있습니다.