DB 설계하기

영슈·2024년 7월 4일
1
post-thumbnail

이 글의 내용은 DB 설계하는 법 (feat. 데이터 모델링) 의 글을 참고해서 작성했다.
해당 내용을 기반으로 내가 다른 예시로 설계를 하고,설계 중 느낀점들에 대해서 남겼다.

DB 설계 과정

  • 하향식 방법 : 타사의 서비스를 참고해 벤치마킹
    - 빠른 엔티티 도출 : 기존 시스템을 참고 하기에 빠르게 엔티티&관계 정의 가능
    - 검증된 설계 : 이미 완성된 시스템을 참고하므로 설계 오류가 상대적으로 적음
    - 짧은 개발 시간 : 초기 설계 드는 시간을 줄여 빠른 프로토타입 제작 가능
  • 상향식 방법 : 프로젝트 요구사항을 분석해, 필요한 엔티티 도출&설계 ( 무에서 유 창조 )
    - 근거 명확 : 요구사항을 기반 엔티티 도출, 각 엔티티의 존재 이유가 명확
    - 유연성 : 설계 근거 명확, 요구사항 변경에 대해 유연한 대응 가능
    - 맞춤 설계 : 프로젝트 요구사항에 맞게 최적화된 설계

결국, 상향식 설계를 해야만 요구 사항의 발전 & 변경에 대처가 가능하다.

상향식 설계

  1. 기획안을 보며 모든 키워드를 뽑아내기
  2. 뽑아낸 키워드를 행위-데이터로 구분하기
    1. 행위는 행위 엔티티, 데이터는 실제 엔티티로 매핑 ( 모든 행위,데이터를 담을 필요 X - 서버의 ENUM )
  3. 설계한 엔티티에 관계 매핑
    ( 관계 역시도 속성, 엔티티 간 JOIN 하려면 속성 필요 )

예시 - 스타벅스

블로거 영운님은 맥도날드를 예시로 들었다.
나는 내가 공부도 할겸 스타벅스를 예시로 설계를 해볼것이다.

300

300

( 참고 그림 )

기능 명세

- 메뉴를 CRUD 할 수 있다. ( 메뉴는 또 음료 / 푸드 / 상품 그룹을 가진다. ) - 여기서 메뉴는 음료로만 가정한다.
	- 메뉴마다 이름 / 설명 / 가격 / ICED(HOT) ONLY / 제품 영양 정보를 가진다.
	- 메뉴마다 퍼스널 옵션이 존재한다. ( 각 메뉴마다 매우 다양하다. - 사실상 공통화 X )
	- 메뉴는 하나 이상의 메뉴 그룹에 매핑된다. ( 추천/NEW 에 포함될 수 있으며, 기본 티바나/피지오 등에 포함될 수 있다. )
- 매장을 CRUD 할 수 있다.
	- 매장은 주소, 운영 시간, 오시는길, 등을 가진다.
	- 몇명 매장은 특별 상품을 가진다.
- 장바구니에 1개 이상의 메뉴를 담을 수 있고 매장을 선택한다.
	- 메뉴들은 선택한 퍼스널 옵션 / 사이즈 등을 가진다.
	- 선택한 매장과 메뉴 수령 방법을 가진다.

기획안을 통해 모든 키워드를 뽑아보자. ( 불필요한 정보성 칼럼들은 생략 )

메뉴는 음료 / 푸드 / 상품 그룹을 가지나, 얘네를 하나의 테이블로 관리할 것 같지는 않다.
( 공통점 : 설명,가격이 끝, 차이점 : ICED ONLY 선택, 알레르기, 등등 대부분이 다름 )

  • ICED 와 HOT 은 두개를 다른것으로 구분한다 ( 영문명, 설명,그림 등이 달라지므로 다른것으로 판단 )

  • 메뉴
    - 이름
    - 설명
    - 가격
    - 가능한 사이즈
    - 온도 ( ICED, HOT )
    - 퍼스널 정보
    - 알레르기 유발 요인
    - 제품 영양 정보 ( 칼로리, 탄수화물, 당류 등등 )

  • 퍼스널 정보
    - 시럽 ( 그룹 )
    - 바닐라
    - 헤이즐넛
    - 카라멜
    - 우유
    - 일반
    - 저지방
    - 무지방
    - 두유
    - 오트
    - 얼음
    - 휘핑 크림
    - 드리즐 ...

  • 매장
    - 매장 주소
    - 전화번호
    - 가능 서비스들
    - 배달
    - 개인컵
    - 야간
    - 운영 시간
    - 오시는 길

  • 장바구니
    - 주문 메뉴들
    - 매장 정보
    - 픽업 방법

우선, 실체 엔티티 와 행위 엔티티를 분리해보겠다.

엔티티 분리

  • 실체 엔티티 : 실제로 보이는 것을 나타내는 엔티티 ( 만질 수 있다...? )
    - 물리적으로 존재해야 하며, 명확히 식별 가능하다
    - 실제 정보를 관리한다
  • 행위 엔티티 : 실체 엔티티와 상호작용 하는 엔티티, 실체 엔티티와 관계 통해 특정 작업 수행

실체 엔티티는 결국 모델의 뼈대이기에, 모델의 근간이 튼튼해진다.

여기서, 내가 생각하기에 실체 엔티티는
매장, 메뉴, 옵션, 메뉴 그룹 이라고 생각한다.

  • 커피를 CRUD 하기 위해선 메뉴
  • 커피들 카테고리를 가지는 메뉴 그룹
  • 퍼스널 정보에 포함된 옵션
  • 커피를 시키기 위한 매장

( 느끼는 점으론 정적인 값들이라고 생각하고 실체 엔티티를 접근해도 괜찮은 것 같다. )

이때 되게 생각을 많이 했는데 퍼스널 정보라는 테이블 자체가 필요하지 않다.
옵션을 통해서 그룹화가 가능하다!

350

그러면 이제 요구사항과 엔티티들을 통해 다대다 관계를 생각해보자

  • 하나의 메뉴는 여러 메뉴 그룹에 속할 수 있다. 하나의 메뉴 그룹은 여러 메뉴를 속할 수 있다.
  • 하나의 특별 메뉴는 여러 매장에 속할 수 있다. 하나의 매장은 여러 특별 메뉴를 속할 수 있다.
  • 하나의 옵션은 여러 메뉴에 속할 수 있다. 하나의 메뉴는 여러 옵션을 가질 수 있다.

퍼스널 옵션들을 빼고 다대다는 단순히 테이블만 더 만들면 된다.

400

그후, 관계를 설정하면?

400

기본적인 설계 및 프론트에 보여주기 위한 엔티티 설계는 마무리가 되었다.

하단에는 이번에 설계하며 생각한 부분들에 대해 작성하며 마무리 하려고 한다.


DB에 저장해야 하는 데이터인지 식별하기

추가적으로, DB 가 가져야 하는 데이터인지 가질 필요 없는 데이터인지를 잘 구별 해내야 한다.

스타벅스에서 퍼스널 옵션을 선택할때는 각각 옵션마다 선택지가 다양하다.

예를 들어
1. 시럽에서는 바닐라 시럽,헤이즐넛 시럽, 카라멜 시럽 등이 있는데 횟수를 선택할 수 있다.
2. 휘핑 크림은 작게 / 보통 / 많이를 선택할 수 있다.
3. 드리즐은 카라멜 드리즐, 초콜렛 드리즐이 있는데 적게/보통/많이를 선택할 수 있다.

이때 적게 / 보통 / 많이를 굳이 DB에 저장할 필요가 있을까?

class Enum Amount {
	LESS("적게"),
	NORMAL("보통"),
	MORE("많이");
}

Drizzle 에 대한 정보를 받으면 해당 값 + Enum 을 포함시켜줘서 프론트로 반환하면 칼럼이 없어도 칼럼이 있는것처럼 기대할 수 있다.

@Entity
class Drizzle{
	@Id
	private Long id;
	private String name;
	private BigDecimal price;
}

public DrizzleRespone toResponse(Drizzle drizzle){
	return new DrizzleResponse(
		drizzle.getId(),
		drizzle.getName(),
		drizzle.getPrice(),
		Set.of(Amount.LESS,Amount.NORMAL)
	);
}

물론, 특정 커피는 적게&보통만 가능하고, 어떤 커피는 많이만 가능하는 등의 빈도가 자주 보인다면 테이블이 가지는 것도 고려할 수 있다.
-> 그룹화와 유연한 확장에 대해 생각을 해야 한다.

그리고 Depth가 깊어지면 해당 내용에서의 일환으로도

옵션을 저장할 필요가 있을까? 에 대해서도 판단할 수 있다.
-> 사실 조회 자체도 필요없을수도, 저장될 필요가 없을수도 있다.

저장될 필요가 없다고 판단 하면 로그성 데이터로 이동후 로그성 데이터로만 사용되게 의도할 수 있다.


Application 내 Enum, DB 내 Data 의 차이점

정보를 DB에 저장할 수도, 애플리케이션이 가질 수도 있다.
이 부분은 현 인프랩 CTO 향로님이 배민에서 작성하신 Java Enum 활용기 에서도 잘 설명되어 있다.

내용을 인용하자면

특히나 카테고리의 경우 6개월에 1~2개가 추가될까말까한 영역인데 굳이 테이블로 관리하는 것은 장점보다 단점이 더 많다고 생각하였습니다.
Enum을 사용하는데 있어 가장 큰 허들은 "변경이 어렵다"란 의견입니다.
정말 코드를 추가하거나 변경해야 하는 일이 빈번하다면, 매번 Enum 코드를 변경하고 배포하는것보다 관리자 페이지에서
관리자가 직접 변경하는 것이 훨씬 편리할 수 있다고 생각합니다.
적정선에서 Enum으로 관리할 부분과 테이블로 관리할 부분을 잘 나누어야 된다고 생각합니다.)

Enum의 장점으로는 쿼리문을 날릴 필요 없는 점 + 메모리 내 상주 + 데이터 값과 로직을 같은곳에 붙힐 수 있는게 장점이다. ( 가장 큰 장점은 날리는 CRUD API 구현 할 필요가 없다는 점도 큰 장점 )

Enum의 변경으로 애플리케이션이 하루에도 2~3번씩 재시동&배포 해야하거나 ( 즉, 데이터 변동성을 잘 파악 )
너무 많은 데이터거나, 너무 용량이 큰 데이터가 아니라면 Enum으로 관리를 하는게 맞다고 판단했다.


원래 해당 내용은
퍼스널 옵션들에 대한 장바구니와 결제 내역 저장들에 대해서도 남기려고 했으나
내용이 길어져서 다음편에서 다룬다.

0개의 댓글