본문 바로가기
개념 공부/DBMS

[Beyond SW / 7일차 복습 - 1] 데이터모델링

by clean01 2024. 5. 22.

데이터모델링

데이터 모델링이란 구축할 DB 구조를 약속된 표기법에 의해 표현하고 설계해 나가는 과정을 의미합니다.

데이터모델링의 단계

  1. 개념적 데이터 모델링
  2. 논리적 데이터 모델링
  3. 물리적 데이터 모델링

개념적 데이터 모델링

  • 다이어그램을 통해 데이터베이스 구조를 시각화
  • 이 단계는 추상화된 DB 구조를 그리는 것이므로 생략이 가능합니다.
    • 사각형: 엔터티
    • 원: 속성
    • 마름모: 관계

논리적 데이터 모델링

  • 구체적으로 데이터베이스를 설계합니다.
  • 각 데이터의 타입, 관계, key 등을 지정합니다.
  • erd cloud, draw.io, mysql 워크벤치 등의 툴을 써서 ERD를 그릴 수 있습니다.
    • 엔터티: (엄밀히 말하면 다르지만,) DB의 한 테이블을 엔터티라고 생각하면 됩니다.
    • ERD: 엔터티 간의 관계를 표현하는 다이어그램입니다.
  • DB 설계에서 가장 중요한 단계라고 할 수 있습니다.
  • 연관이 있는 테이블은 선으로 연결할 수 있는데, 엔터티 간의 관계에 따라서 다음 사진과 같이 표시할 수 있습니다.

간단히 정리해보자면

  • 몇 대 몇인가
    • 작대기: 1개 있어야함
    • 삼발이: 여러개
  • 필수 값인가
    • 작대기: 필수
    • 동그라미: 필수 아님

아래서 보게 될 테이블 간의 참조 관계 종류를 잘 고려하여 선으로 연결해주어야 합니다.

관련 용어 정리:

  • reverse engineering: 기존 스키마(DDL 쿼리문)에서 ERD 추출 (워크벤치, 데이터그립 등의 툴에서 제공)
  • forward engineering: ERD에서 스키마(DDL 쿼리문) 추출 (워크벤치, erd cloud 등의 툴에서 제공)

물리적 데이터 모델링

  • 최종적으로 데이터베이스에 실제 테이블을 만드는 SQL 작업입니다.
  • ERD에 표현되지 않는 부분들(예를 들면 인덱스)을 고려하여 테이블을 생성합니다.

테이블 간의 참조 관계

1:1 관계

  • 한 테이블의 레코드(record, row)가 다른 테이블의 레코드 하나와만 연관 관계를 갖습니다.
  • 1:1 관계를 보장하기 위해서는 fk를 unique 설정해줍니다.
  • 1:1 관계 분리 필요성:
    • 서비스의 특성을 기준으로 도메인의 명확한 분리를 통해 특정 서비스 변경 사항 발생 시 영향도를 최소화하고 유지 보수성 향상을 위해 1:1 테이블 관계로 분리하는 것이 필요할 때가 있습니다.
      • ex) 회원과 회원의 주소 테이블: 회원이 한 개의 주소만 가질 수 있는 서비스가 있다면, 회원과 회원의 주소 테이블이 1:1 관계에 있습니다. 회원 테이블의 회원의 주소 정보까지 다 포함시켜도 되지만, 주소 체계가 복잡해서 country, city 등등 여러 컬럼으로 나눠야 하는 경우, 회원 테이블에 모두 포함시키면 회원 테이블의 컬럼이 너무 많아질 수 있으므로 주소 테이블을 분리하는 것이 좋습니다.

1:n 관계

A 테이블의 입장에서 생각했을 때, A 테이블의 한 레코드가 B 테이블의 여러 레코드와 관계가 있습니다.

ex) 게시판 서비스에서 author 테이블 입장에서 post 테이블과의 관계

n:1 관계

A 테이블 입장에서 생각했을 때, A 테이블의 여러 레코드가 B 테이블의 한 레코드와 관계가 있습니다.

ex) 게시판 서비스에서 post 테이블 입장에서 author 테이블과의 관계

n:m 관계

A 테이블의 한 레코드가 B 테이블의 여러 레코드와 관계가 있고, B 테이블의 한 레코드가 A 테이블의 여러 레코드와 관계가 있습니다.

ex) 백준 플랫폼에서 한 문제에는 여러 검수자가 있을 수 있고, 반대로 한 유저가 여러 문제를 검수할 수 있습니다.

-> n:m 관계는 나중에 살펴볼 제 1 정규화 규칙에 어긋납니다. 따라서 연결 테이블(junction table)을 만들어서 1:n 관계로 풀어주어야 합니다.

물론 n:m인 상태로 테이블을 만들어도 되기는 하지만, 한 컬럼에 여러 값들이 들어가기 때문에 조회, 수정, 삭제가 불편해집니다.


그 외 논리적/물리적 모델링을 할 때 고려해볼 것들

mandatory or optional

  • 필수 값이라면 not null 조건을 걸어줍니다.

1:1 관계

  • 1:1 관계를 보장해주고 싶다면 fk에 unique 조건을 걸어줍니다.
    • ex) 하나의 글은 반드시 하나의 유저가 써야하는 게시판이 있다고 생각해봅시다. author, post, author_post(연결 테이블) 이렇게 3개의 테이블이 있을 때, author_post의 post_id(Post 테이블의 id를 참조하는 fk)를 unique로 걸어준다면, Post와 author_post가 1:1 관계가 되는 것이 보장됩니다.

회원 테이블에서 id(int or bigint) 대신에 email(unique)를 pk로 사용해도 될까?

회원 테이블에 있는 email column에 unique, not null 조건이 걸려있다면, 기존 id 대신 pk로 사용해도 될 것 같은데 이것은 좋은 설계일까요?

  • 장점:
    • id가 차지하는 만큼의 용량을 아낄 수 있습니다. (회원 테이블에서 id 컬럼을 날려도 되니까)
  • 단점:
    • email이 변경된다면 fk가 걸려있는 다른 테이블의 로우가 모두 cascade로 변경됩니다. fk는 기본적으로 인덱스가 걸리므로 여러 테이블에서 emaild(fk)에 대한 인덱스도 모두 변경될 것 같습니다.
    • email을 fk로 참조하는 테이블이 많아질 수록 차지하는 용량이 커집니다. id는 int로 했을 때 4바이트, bigint로 했을 때 8바이트를 차지하지만, email은 최소 10자리 정도의 문자열로 구성되어 있을 것이고 길어질 경우 20자리 정도 된다고 생각하면 10바이트 ~ 20바이트를 차지하게 됩니다. 이 email을 pk로 써서 여러 테이블에서 fk로 참조하게 되면, id를 int, bigint 타입으로 설정하는 것보다 공간 낭비가 많이 발생할 것입니다.

-> 결론: id는 웬만하면 auto_increment 되는 int 또는 bigint를 쓰는 것이 좋을 것 같습니다.

uuid를 pk로 사용해도 될까?

  • 장점:
    • 분산 DB에서는 pk로 uuid를 쓰는 것이 유용합니다. (여러 DB에 흩어진 데이터를 다시 한 DB로 합칠 때 충돌이 발생할 가능성이 매우 적음)
  • 단점:
    • int(4바이트), bigint(8바이트) 타입의 pk보다 용량을 많이 차지합니다. (uuid는 36바이트)

-> 결론: 분산 DB 환경이 아니라면 id로 uuid를 쓰는 것은 추천하지 않습니다.

복합키의 사용

복합키란 2컬럼 이상에 PK 조건을 지정하는 것을 의미합니다.

ex) 복합키를 거는 테이블 생성 쿼리 예시

create table author_post(
  author_id int,
  post_id int,
  created_time datetime default current_timestamp,
  primary key(author_id, post_id), -- 복합키 설정. 둘에 같이 인덱스가 걸림
  foreign key(post_id) references post(id),
  foreign key(author_id) references author(id)
);

pk에는 자동으로 인덱스가 걸리는데, 복합키를 쓰면 두 컬럼에 동시에 인덱스가 걸립니다.
위 쿼리를 예시도 들었을 때, author_id, post_id에 동시에 인덱스가 걸리는 것이기 때문에, where author_id=1 이런 식으로 찾아올 때에는 인덱스가 걸리지 않습니다. where author_id=1 and post_id=3 이렇게 where 절을 써주어야 select 시에 인덱스를 활용할 수 있습니다.

  • 장점:
    • 불필요한 id 값을 추가할 필요가 없습니다.
    • author_id, post_id 등 명확한 식별자를 통해 조회 시에 쿼리의 명확성이 향상됩니다. (Id 값은 보통 의미가 없는 숫자이기에 id로 조회하는 것보다 복합키로 조회하는 것이 쿼리의 의미를 이해하기 더 쉬울 수 있음)
  • 단점:
    • 프로그램의 복잡성이 증대됩니다.

-> 결론: 복합키는 쓰지 않고 별도의 pk(id)를 두는 것이 좋을 것 같습니다.

 

 

 

 

데이터모델링 외에도 오늘 정규화와 mariadb 덤프 실습을 진행했지만, sqld 시험이 얼마 남지 않은 관계로..,,,
그 내용들은 나중에 정리해보도록 하겠습니다. :)


Reference

  • Beyond SW 7기 수업과 수업 자료