2년전 나에게 - ERD 설계의 기본개념

박민기·2025년 7월 4일

2년전 나에게

목록 보기
2/6
post-thumbnail

A. 배경

이 글은 첫 프로젝트에서 ERD를 그려야 하는 과제를 받은 학생을 위한 글입니다. 저의 경우 첫 프로젝트를 시작할 때 데이터베이스에 대해 어느 정도 알고 있었기 때문에 ERD를 설계하는 데 큰 무리는 없었습니다. 하지만 데이터베이스 테이블 설계를 처음 하거나 개념을 잘 모르는 상태에서 시작한다면, 개발 과정에서 불필요한 절차가 추가될 수 있고, 너무 복잡하게 설계할 경우 개발 시간에 지장을 줄 수 있습니다. 그래서 처음 시작하는 초심자가 알고 있으면 좋을 점들을 소개하고, 저와 주변에서 봤던 사례를 통해 설계를 보다 쉽게 할 수 있도록 이 글을 작성하게 되었습니다.

B. 기본 개념

1. 데이터베이스

데이터베이스는 여러 가지 정보를 체계적으로 저장하고, 필요할 때 쉽게 꺼내 쓸 수 있게 해주는 정보 저장소입니다.

무신사 사이트를 예로 들면, 무신사는 상품들이 카테고리별로 분류되어 있어서 사용자가 아우터가 필요하면 해당 카테고리에 들어가 원하는 옷을 찾아보거나 구매할 수 있습니다.

여기서 ‘이름’, ‘가격’, ‘브랜드’ 처럼 위에 있는 게 바로 열(컬럼)이에요.
그리고 그 아래에 실제로 들어가는 ‘에어포스’, ‘100,000’, ‘나이키’ 같은 정보들이 행(로우)가 되는 거죠.
이때, 중복되지 않는 컬럼을 기본키 (Primay Key) 라고 생각하시면 밑의 내용을 이해하기 편할 것 같습니다.

이렇게 상품 하나하나가 행으로 쌓이면서, 전체가 하나의 ‘상품’ 이라는 표(테이블)가 됩니다.
그리고 이런 표들이 여러 개 모여서, 우리가 흔히 말하는 데이터베이스가 만들어지는 거예요.

데이터베이스라는 건 이런 표(테이블)들이 모여 있는, 일종의 ‘정보 저장소’ 입니다.

2. 정규화

이제 위와 같이 테이블들만 만들어서 데이터베이스를 구성한다고 좋은 설계를 했다고 하기는 어렵습니다. 더 좋은 설계와 개발과정에서 도움이 되기 위해서는 데이터가 불필요하게 여러 번 반복되거나, 엉뚱하게 사라지거나, 잘못 바뀌는 것 을 막기 위해 데이터를 잘 정리해서 저장하는 정규화하는 방식으로 설계를 해야합니다.

정규화에는 제1, 제2, 제3, BCNF, 제4, 제5 와같은 정규화 방식이 있지만 이번 글에서는 제1~제3 정규화 까지 소개해 드릴게요.

이 글을 읽으실 때, 정규화를 해야 하는 이유보다는 정규화를 하지 않을 때 발생하는 문제에 초점을 맞추면 정규화의 필요성을 더 쉽게 이해할 수 있습니다. 이런 방식으로 접근하면 데이터베이스 설계 시 명확한 의도를 가지고 설계할 수 있습니다.

3. 제1정규화

데이터베이스 테이블의 각 컬럼(열)에 반드시 하나의 값만 들어가도록 만드는 것입니다. 즉, 한 칸에 여러 개의 값(리스트, 배열 등)이 들어가면 안 되고, 반복되는 값이나 그룹이 있으면 각각의 값이 따로 저장되도록 테이블을 나누는 작업입니다.

위의 표는 제1정규화가 적용되지 않은 대표적인 사례입니다. 제1정규화에서는 컬럼에 하나의 값만 들어가야 하지만, ","를 통해 두 개의 값이 들어간 것을 볼 수 있습니다. 이런 구조에서는 데이터를 조회할 때 ","를 기준으로 파싱해야 하거나, 상품 목록을 추가할 때 이전 값에 문자열을 이어 붙이는 등의 불필요한 작업이 추가로 필요할 수 있습니다.

뿐만 아니라, 삭제할 때도 예를 들어 '아식스'를 삭제하고 싶다면, 해당 컬럼을 불러와서 '에어포스, 아식스'라는 문자열에서 '아식스'만 삭제하고 다시 업데이트해야 하는 불편함이 생깁니다.

이렇게 테이블을 설계하면,

  • 상품별로 데이터를 쉽게 추가, 수정, 삭제할 수 있습니다. 예를 들어, 특정 주문에서 '아식스'만 삭제하거나 추가할 때 한 행만 삭제/추가하면 되기 때문에 훨씬 간단합니다.
  • 상품별 검색이 쉬워집니다. '에어포스'를 주문한 모든 고객을 바로 조회할 수 있습니다.
  • 데이터 중복과 오류를 줄이고, 데이터 무결성을 지킬 수 있습니다.
  • 저장 공간도 효율적으로 사용할 수 있습니다.

4. 제2정규화

제2정규화는 데이터베이스 정규화 과정 중 두 번째 단계로, 제1정규화를 만족한 테이블에서 "부분 함수 종속"을 제거하는 작업입니다.

이렇게만 말하면 “부분 함수 종속이 뭐야?” 라는 의문이 생길 수 있어요.

아래와 같은 주문 테이블에서 다시 설명하겠습니다.

여기서 주문번호는 한 번의 주문을 의미하고, 한 주문에는 여러 상품이 들어갈 수 있습니다.

  • 한 주문(주문번호)은 여러 상품(상품코드)을 가질 수 있으니 일대다(1:N) 관계입니다.
  • 반대로, 한 상품(상품코드)은 여러 주문에 포함될 수 있으니 다대일(N:1) 관계도 숨어 있습니다.

부분 함수 종속이란?

이 테이블에서 기본키는 (주문번호, 상품코드)입니다. 왜냐하면 이 두 개를 묶어야만 각 행이 유일하게 구분되기 때문입니다.

  • 상품명과 브랜드는 상품코드만 알면 항상 정해집니다.
  • 예를 들어, 상품코드가 A001이면 상품명은 항상 '에어포스1', 브랜드는 항상 '나이키'입니다.
    즉, 주문번호와 상품코드(두 개의 정보)로 행을 구분하지만,
    상품명과 브랜드는 상품코드(한 개의 정보)만으로 결정됩니다.
    이렇게 기본키 전체가 아니라 일부(상품코드)만으로 다른 값이 정해지는 것을 “부분 함수 종속”이라고 합니다.

부분 함수 종속이 있으면 생기는 문제

  1. 데이터 중복과 관리의 어려움
    예를 들어, '나이키' 브랜드 이름이 '나이키스포츠'로 바뀌면,
    상품코드가 A001인 모든 행의 브랜드를 일일이 수정해야 합니다.
    만약 이런 행이 수십만 개라면? 수정이 너무 번거롭고, 일부만 바꾸면 데이터가 서로 달라질 수 있습니다.

  2. 불필요한 데이터 중복
    같은 상품(예: A001 에어포스1 나이키)이 여러 주문에 포함될 때마다 똑같은 상품명과 브랜드가 반복 저장됩니다.
    이로 인해 데이터베이스 용량이 커지고, 관리가 어려워집니다.

2정규화로 해결하기

이 문제를 해결하기 위해 2정규화를 적용합니다.
상품코드만 알면 알 수 있는 정보(상품명, 브랜드)를 별도의 상품 테이블로 분리하는 거죠.

이렇게 하면,

  • 주문 테이블은 한 주문에 어떤 상품이 들어있는지만 관리합니다. (주문과 상품의 다대다 관계를 연결)
  • 상품 테이블은 상품코드별로 상품명과 브랜드를 한 번만 저장합니다. (상품과 브랜드의 다대일 관계)

5. 제3정규화

제3정규화 는 데이터베이스 정규화의 세 번째 단계로,
2정규화까지 마친 테이블에서 '직접적인 관계가 없는 정보끼리의 간접적인 의존성' 을 없애는 과정입니다.

3정규화가 필요한 이유

2정규화를 거치면 중복이 줄고, 부분 함수 종속이 사라집니다.
하지만 여전히 직접적으로 연결되지 않은 정보끼리, 다른 정보를 통해 연결(의존)되는 문제가 남아 있을 수 있습니다.
이런 관계를 전이적(간접적) 종속이라고 부릅니다.

부분함수 종속이랑 별 다를게 없는거 아니라고 생각할 수 있을 거 같아 아래의 표로 다시 설명드리자면

여기서 상품코드만 알면 상품명과 브랜드를 알 수 있습니다.
그런데 브랜드주소는 상품코드가 아니라, 브랜드만 알면 항상 정해집니다.

이때 브랜드는 기본키가 아닌 컬럼 입니다. 이게 전이적(간접적) 종속이고,
상품코드 → 브랜드 → 브랜드주소 이런 관계가 형성 됩니다.
반면, 부분 종속 함수는 기본키 중 일부만 사용해서 값이 정해지는 것을 의미합니다.

전이적(간접적) 종속이 있으면 생기는 문제

  • 브랜드주소가 '나이키' 브랜드에 속한 상품마다 반복 저장됩니다.
  • 만약 나이키 본사가 이사하면, 나이키 브랜드가 들어간 모든 상품의 브랜드주소를 수정해야 합니다.
  • 실수로 일부만 수정하면, 브랜드주소가 서로 다르게 남아 데이터가 꼬일 수 있습니다.

3정규화로 해결하기

3정규화는 이렇게 간접적으로 연결된 정보를 분리해서,
각각의 정보가 "직접적으로"만 연결되도록 테이블을 나누는 과정입니다.

위와 같이 하게 되면 테이블의 각각의 정보들이 직접적으로만 연결이 이루어질 수 있습니다.

  • 이제 브랜드주소가 바뀌어도 브랜드 테이블 한 곳만 수정하면 됩니다.
  • 상품 테이블에는 브랜드만 저장되니, 중복이 사라지고 관리가 쉬워집니다.

C. ERD 설계 순서

1. 요구사항 파악 및 테이블 도출

무엇을 저장할지, 어떤 기능이 필요한지 정리

  • 이전 단계에서 디자인(와이어프레임)을 통해 시각화한 요구사항을 보며, 어떤 데이터가 필요한지 적어봅니다.
  • 이해가 안 되면 “어떤 데이터를 저장해야 이 서비스가 동작할까?”를 계속 고민해보세요.

팁:

  • 명사(사람, 상품, 주문 등)를 중심으로 생각하면 테이블이 쉽게 보일 거에요.

2. 테이블별 정의

각 테이블에 어떤 정보가 들어갈지 나열

  • 예를 들어 “회원” 테이블에는 이름, 이메일, 비밀번호, 가입일 등이 들어갑니다.
  • “주문” 테이블에는 주문번호, 주문일시, 회원ID, 배송주소 등이 들어갑니다.
  • 각 테이블의 기본키(Primary Key)도 정합니다
  • 저는 덤벙거리는 성격이여서 정보를 빼먹지 않기 위해서 디자인(와이어프레임)을 여러번 보면서 뭐가 필요할까? 고민하는 과정을 여러번 반복합니다.

팁:

  • 처음에는 생각나는 대로 최대한 많이 적어도 괜찮습니다. 나중에 정규화 과정에서 정리하면 됩니다.

3. 테이블 정규화

정규화를 잘하려면, 각 데이터를 “이 정보가 어디에 속해야 가장 자연스러운가?”, “이 정보는 무엇에 의존해서 결정되는가?” 라는 질문을 반복적으로 던지며 테이블을 나누는 것이 중요합니다.

팁 :

1. 정보의 소속과 관계를 문장으로 풀어보세요.

  • “상품은 브랜드를 가진다.”
  • “주문은 여러 상품을 가진다.”
  • “상품은 한 브랜드에 속한다.”
  • “회원은 여러 주문을 할 수 있다.”

    이런 식으로 관계를 중얼중얼 거리면, 어떤 데이터가 어느 테이블에 있어야 할지, 테이블 간의 연결이 어떻게 되어야 할지 쉽게 떠올리는데 많이 도움되는 것 같아요.(저는 손가락으로 테이블을 이동하면서 중얼거려요.)

2. 중복과 불필요한 의존성을 찾아 분리하세요.

  • 한 테이블에서 같은 정보가 반복된다면, 그 정보는 별도의 테이블로 분리해 더 효율적인 설계를 할 수 있을거에요.
  • 어떤 값이 기본키 전체가 아닌 일부에만 의존한다면, 그 속성은 따로 떼어내야 합니다.
  • 한 정보가 다른 정보에 간접적으로 의존한다면(예: 상품이 브랜드주소를 직접 갖고 있다면), 중간 단계를 분리해 각각 직접적으로만 연결되도록 만드세요.

정규화 과정에서 테이블 간 관계도 자연스럽게 명확해집니다.

“~는 ~를 가진다”, “~에 속한다”처럼 관계를 문장으로 만들어보면, 어떤 테이블이 어떤 테이블과 연결되어야 하는지 쉽게 파악할 수 있습니다. (중얼거리기가 저만의 팁인거 같아요.)

D. 마무리

첫 프로젝트를 하는 분들을 대상으로 했기 때문에 단계를 조금 간소화하여 적었지만, 프로젝트를 진행하면서 시간적 여유가 있다면 ERD 설계의 순서를 이론적으로 한 번 더 찾아보시는 것을 추천드립니다.
제가 생각하는 ERD 설계의 핵심은 어떤 정보를 저장할지와 서로 어떻게 분리해야 효율적일지를 가장 많이 고민하는 것 같습니다. 차근차근 도식화해 보세요!
정규화를 무조건 한다고 해서 항상 좋은 것은 아닙니다. 많은 경험을 쌓고 개발에서 불편함을 겪다 보면, 정규화를 하지 않는 것이 더 좋은 경우도 있을 거예요.

다음 글은 "API와 명세서" 라는 글로 뵙겠습니다.

profile
밍기적거리지 않기

3개의 댓글

comment-user-thumbnail
2025년 7월 7일

시리즈로 이렇게 모두 알려주시면 정말 큰 도움이 될 거 같아요..!

1개의 답글