Database Modeling 📊
컨셉디자인 - Logical 디자인 -> Physical 디자인의 과정을 거친다.
- Concept Design 📝 - 업무적인 흐름에서 DB에 저장할 데이터를 선별하는 과정
- Logical Design 🧩 - 엔티티와 관계를 설정하는 과정 (R-DB의 형태로 데이터 정리)
- Physical Design 💾 - 물리적인 저장 구조를 설정하는 과정 (특정 DBMS의 테이블 형태로 정리)
시스템 🔄
시스템이란 유기적으로 역할자들이 결합된 집합체이다.
우리는 페이지를 만드는 사람이 아니라, 시스템을 만드는 사람이다. 시스템을 만들고, 그에 맞는 화면 설계를 하는 것이 우리의 역할이다.
시스템의 종류 🔄
- 업무 시스템 - 실제 비즈니스 프로세스를 처리
- 관리 시스템 - 데이터와 자원을 관리
시스템이 없으면 업무 처리가 비효율적이고 책임 소재가 불분명해진다.
시스템이 도입되면 업무 처리가 효율적이고 책임 소재가 명확해진다.
예시) 병원 시스템:
- 접수(접수내역) → 의사(진료내역) → 간호사&행정(수납&입원 내역)
내역과 같은 문서를 전산으로 바꾼 것이 바로 Database다. 업무시스템을 알아야 결국 관리 시스템을 만들 수 있는 것이다.
비용 처리 시스템을 만든다고 가정해보자.
팀장님께 비품 요청 -> 팀장님은 카드를 주시고 영수증을 받음 -> 구매내역을 정리해서 비용처리
소모품담당자, 구매자, 배급자 신청내역, 구매내역, 배급내역을 기록할 문서가 필요하다. 이러한 문서를 자동화 시키는것이 우리의 역할이다.
조회시스템
기존의 관리시스템(CRUD)에서의 조회는 관리자 입장에서의 조회시스템으로, 다른 역할자가 조회를 하기 위한 시스템이 따로 필요하다.
가장 대표적인 예) 서점. (일반 조회용 컴퓨터와 직원용 컴퓨터가 따로 존재한다.)
이처럼 우리가 만드는 모든 서비스나 앱에서 사용되는 db는 이런식으로 하나의 행위들이 전부 기록된다.
하지만, 요리와 같이 관리, 내역이 필요없는 것들은 업무에서 빠지게 될 것이고, 내가 관리나 내역이 필요하다고 생각하는 내역들을 DB에 넣는다.
메뉴조회, 식사, 요리 등이 내역이나 관리가 필요없어 보이지만, 조회는 좀 다르다. 조회를 통해 우리의 행위를 관찰해서 빅데이터에 들어간다.
DB에 넣는다는것은, 관리를 하는것이다. 조회를 위해 빅데이터를 사용한다. (추천을 하기 위해 우리의 행위를 뒷조사) 요새는 그래서 설문이 아니라 행위로 빅데이터를 조사하여 ai를 학습시키기도 한다.
아무튼 결국 관리가 필요없는것은 DB에 넣지 않으며, 이를 선별하는 것이 바로 Concept Design의 단계이다. (역할자와 행위를 정함)
Concept Design 🎨
Concept Design 단계에서는 역할자들과 행위 및 그들의 속성들을 정의한다.
예시) 레스토랑 시스템:
- 역할자: 웨이터, 요리사, 손님
- 행위: 주문, 결제, 서빙, 평가
이러한 행위들을 통해 데이터를 넣는다:
- 주문: 일자, 수량
- 결제: 일자, 금액, 방법
개념 | 설명 | 표현 |
---|---|---|
엔티티(Entity) | 저장할 데이터 객체 | 네모 모양 |
관계(Relation) | 엔티티 간의 관계 | 마름모 모양 |
엔티티/튜플/레코드 | 데이터베이스의 한 행(row) | - |
데이터 레코드(row) 하나를 튜플, 레코드, 엔티티 등 다양한 명칭으로 불린다.
그럼 이 마름모들을 어떻게 테이블로 만들 수 있을까? 이게 다음 단계인 Logical Design이다.
Logical Design 📐
Logical Design 단계에서는 관계를 정의하고 논리적 구조를 설계한다. 엄마 테이블을 같이 끼워넣을것인지, 독립 테이블로 만들 것인지, 이런식으로 관계 및 논리를 설계한다.
ERD를 완성햇다면, 똑같은걸 만들어서 영문이름으로 바꿔주는 작업을 마지막으로 수행하자.
관계의 유형 🔀
관계 유형 | 설명 | 예시 |
---|---|---|
1:1 관계 | 양쪽 엔티티가 서로 하나씩만 연결 | 사람과 주민등록번호 |
1:N 관계 | 한 엔티티가 여러 엔티티와 연결 | 한 명의 관리자가 여러 메뉴 관리 |
N:N 관계 | 양쪽 엔티티가 서로 여러 개와 연결 | 여러 회원이 여러 메뉴 주문 |
현실과 같이, 자식은 하나의 부모에서만 파생될 수 있어, 부모와 자식관계에서는 자식이 다(N), 부모가 일(1)의 관계를 가진다.
행위끼리의 1:1 관계에서는 서로를 포함하는 포함관계를 가지며, N:N의 관계를 가지는 엔티티는 독립적인 테이블로 만들어야 한다.
하나의 관리자가 여러개의 메뉴를 만들 수 있는가? 1 : N 하나의 메뉴를 여러명의 관리자가 등록하는가? X 👉 1 : 1
여러명의 회원이 하나의 메뉴를 주문할 수 잇는가? O 여러개의 메뉴를 한명의 회원이 주문할 수 잇는가? O 👉 주문은 N:N의 관계를 가진다.
한명의 회원이 여러개의 메뉴를 결제할 수 있는가? O 한개의 메뉴를 여러명의 회원이 결제할 수 있는가? O 👉 결제는 N:N의 관계를 가진다.
이처럼 다이어그램을 그려서 DBMS를 설계해보자! https://app.diagrams.net/
처음에 다이어그램을 그릴때 우리가 이해할 수 있는 한국어로 작성을 하고, 이후에 영어로 치환하는 프로세스로 진행하는 것이 좋을 것이다.
아이디를 통해 엔티티를 식별할 수 있게 해야 관리를 할 수 있다. PK(Primary Key)
키(Key) 🔑
키 유형 | 설명 | 예시 |
---|---|---|
주키/기본키(PK) | 엔티티를 유일하게 식별하는 키 (예측 불가능해야 함) | UUID |
후보키 | 엔티티를 식별할 수 있는 속성들 중 주키가 될 수 있는 후보 | 주민번호, 이메일, 전화번호 |
대체키 | 주키가 아닌 나머지 후보키 | - |
대리키 | 인위적으로 만든 식별자 (보통 주키로 사용) | 아이디, 일련번호 |
수퍼키/복합키 | 두 개 이상의 키를 합쳐서 만든 키 | 회원ID + 메뉴ID |
외래키(FK) | 다른 테이블의 기본키를 참조하는 키 | - |
주키는, 예측이 되면 안된다. (그래서 순번으로 아이디를 지정하는것이 좋지 않음.) 주키를 제외한 모든 속성이 후보키인게 아니라, 엔티티를 식별할 수 있는 속성들이 후보키에 들어가고, 후보키 중에 하나를 선정한 키가 주키가 되는 것이다. 또한, 주키 역시 엔티티이므로 개별적으로 생각하면 안된다.
N:N의 관계를 가지는 자식테이블은 독립적인 테이블로 만들어야함. 당연히 관계를 가지고 있는 엔티티에 대한 정보도 필요하기 때문에, 이때 참조를 통해 데이터를 가져온다.
복합키? 행위(마름모)에 대한건 고유키를 사용하면 아이디가 기하급수적으로 많아져 좋지 않다.
엑셀의 컬럼을 생각해보자 엑셀의 시트지에 한줄 (레코드, 행으로도 부름)을 넣으면, DB에서는 이를 엔티티라고 부름. 엑셀에는 엔티티를 여러개 넣는다. 그러한 엔티티들은 식별을 할 수 있어야한다. 그래야 특정행을 삭제하거나, 수정할 수 있는것이다.
참조의 키를 2개를 합쳐서 사용한 식별자가 복합키/수퍼키, 즉 따로 주키를 만들지 않고 기존의 부모 키를 2개 합쳐서 사용하는 것이다.
주문은 행위지만, 회원과 메뉴만으로는 식별을 하기 힘드므로 대리키가 필요하다. (다음날 똑같은 사람이 똑같은 메뉴를 시키면 식별이 안됨.)
식별관계가 아닌것은 점선으로 표시하자.
주문과 결제는 포함관계를 가진다. 행위끼리 1:1의 관계라면, 포함이 가능해진다.
Physical Design으로 넘어가기 전에, 정규화 작업이 필요하다.
정규화 🧹
정규화란? 데이터의 중복을 최소화하고 데이터 무결성을 보장하기 위해 데이터베이스 테이블을 구조화하는 과정
중복의 형태
1번 패턴을 보이는 중복 -> 정규화를 하면 -> 1정규화(1NF) 2번 패턴을 보이는 중복 -> 정규화를 하면 -> 2정규화(2NF) … n번 패턴을 보이는 중복 -> 정규화를 하면 -> n정규화(NNF)
NF는 Normal Form의 약자이다.
정규화 단계 | 설명 | 해결하는 문제 |
---|---|---|
1 정규화 (1NF) | 원자값이 아닌 도메인을 분해 | 하나의 속성에 여러 값이 들어가는 문제 |
2 정규화 (2NF) | 부분적 함수 종속 제거 | 복합키의 일부분으로만 식별되는 속성 문제 |
3 정규화 (3NF) | 이행적 함수 종속 제거 | 두번 이상의 참조로 식별되는 속성 문제 |
BCNF | 모든 결정자가 후보키여야 함 | 후보키가 아닌 속성이 결정자가 되는 문제 |
4 정규화 (4NF) | 다치 종속 제거 | 복수 값으로 인한 튜플 증식 문제 |
1 정규화 (1NF) 💡
- 원자값이 아닌 도메인을 분해하는 것
- 하나의 속성에 하나의 값만 와야 함
- 도메인: 속성에 들어갈 값의 유효 범위
- 원자값: 속성에 들어갈 값은 단일 값이어야 함
재료는 메뉴의 참조키를 받고 있어야한다.
항상 잘라내고 나면 일대다의 관계를 가지며, 자식은 부모의 참조키를 항상 가진다. (참조키는, 항상 참조할 대상이 먼저 탄생되어있어야하기 때문에, 자식이 부모를 참조하는것이 무조건이다. )
1정규화가 수행되지 않으면, 기존의 엔티티를 복제해서 비효율적으로 데이터를 늘리고, 크기는 식별자가 아닌데도 식별자같은 척을 하여 데이터가 더러워질 것이다.
만약 여러 데이터를 사용해야하는 상황이라면, DB에서는 반드시 1:1관계로 데이터 하나가 속성 하나에 할당되어야 하므로 자바스크립트나 다른 언어에서 이를 관리하고, DB에서는 정규화를 따라야한다.
👉 하나의 속성에 여러개의 값이 들어가는지를 검사
2 정규화 (2NF) 💡
- 부분적 함수 종속을 제거하는 것
- 함수 종속: 키로 식별되는 속성들
- 부분적 함수 종속: 식별관계를 가지는 테이블에서 복합키의 일부분으로만 식별되는 속성들
- 식별관계에서만 발생하는 문제
예를 들어, 추천이라는 데이터에서, 회원아이디와 메뉴아이디를 복합키로 가져왔는데, 속성에 일자, 이유, 연락처, 메뉴명이 존재한다고 가정하자. 연락처, 메뉴는 회원 아이디와 메뉴아이디를 통해 참조가 가능하므로, 이는 2정규화에 위반된다.
복합키가 존재하지 않는다면, 부분적 함수가 존재하지 않는 것이므로 위반을 찾을 필요가 없다.
키에 종속된다: 해당 키를 통해 이것을 찾을 수 있는 것
3 정규화 (3NF) 💡
- 이행적 함수 종속을 제거하는 것
- 이행적 함수적 종속성: 두번 이상의 참조를 통해서 식별되는 속성들
- 비식별관계에서 발생
- 외래키를 통한 간접 종속 관계를 분리
- x > y이고, y > z이면, x > z임을 알 수 있음.
- 간접된 속성들을 분리(a-b, b-c 👉 b-c가 되므로 분리하기)
외래키를 이행적 함수라고 부른다.
주문 엔티티에서, 아이디라는 주키를 가지고, 일자, 수량, 연락처, 매장명, 메뉴명이라는 속성들이 있고, 회원 아이디와 메뉴아이디를 외래키로 가진다고 가정해보자. 이때, 회원아이디는 연락처와 연결되어 있으므로 이를 바로 이행적 함수 관계라고 한다. 이러한 관계를 분리시키는 것이 3정규화이다.
외래키가 없다면 이행적 함수가 존재하지 않는것이므로 위반을 찾을 필요가 없다.
BCNF (Boyce-Codd Normal Form) 💡
- 모든 결정자가 후보키여야 함
- 결정자: 어떤 값을 기준으로 다른 값을 유일하게 정할 수 있는 속성 또는 속성 집합
- 종속시키는 모든 속성은 반드시 후보키여야 함
- 결정: 함수적 종속성과 관련된 개념으로, A의 값을 알면 B의 값을 유일하게 알 수 있다. (=A는 B를 결정한다.)
👉 무언가를 종속시키는 모든 속성은 반드시 후보키여야 한다. 종속이라는 것은 함수에서만 사용되는 말이다. 함수 = 키, 키가 아닌 것들은 모두 결정자이다. 메뉴명이 있을때, 메뉴명은 메뉴가격을 결정한다. 메뉴명은 키, 즉 함수가 아니지만, 결정자라고 한다.
3.5 정규화로도 불린다.
4 정규화 (4NF) 💡
- 다치 종속을 제거
- 한 속성이 복수의 값을 가질 때, 다른 속성과 곱 형태로 튜플이 증식하는 현상 방지
- 메뉴에서 크기 속성처럼, 한 속성으로 인해 곱으로 튜플이 증식함. 이때, 데이터 대신 키를 넣는다. 키는 중복되도 된다. 키는 수정이나 관리를 하지 않는 데이터기 때문에 이가 가능하다.
4정규화는 우리가 1:N같은 관계를 정의를 미리 하기 때문에, 위반할 일이 거의 없다.
테이블 설계 시 고려사항 📝
- NULL값이 많아지면 비용이 늘어나고 복잡한 로직이 추가될 수 있음
- 합칠 수 있는 테이블은 합치고, 고유 속성들은 별도 테이블로 분리하는 것이 좋음
예를 들어, 회원과 관리자가 있다고할때, 이를 회원이라는 테이블로 묶고, 종류라는 속성으로 구분을 한다고 할때, 관리자는 가입을 할때 자기가 관리자의 권한을 입증해야하니까 이런것은 추가적인 속성으로 테이블에 들어갈텐데, 일반회원같은경우에는 그러한 속성이 존재하지 않으니까 데이터가 비어있을 것이다.(NULL)
그러면, 합칠 수 있는것은 합치고, 고유속성들을 따로 테이블로 빼내자
회원 테이블 (기본 테이블)
---------
회원ID (PK)
이름
이메일
비밀번호
가입일
회원유형 (일반/관리자)
관리자 테이블 (확장 테이블)
---------
회원ID (PK, FK) ← 회원 테이블 참조
관리자증명문서
관리권한레벨
자식 테이블은 반드시 부모 테이블을 참조하므로 회원 아이디를 통해 접근을 하면 된다.
데이터베이스 시스템 🖥️
데이터베이스는 데이터들을 베이스화하여 한 곳에 모으고, 중복을 없애 결함을 줄인 시스템이다.
핵심 개념:
- 스키마(Schema): 저장 모델에 부합되는 데이터 구조
- 뷰(View): 사용자에게 보여지는 데이터 표현
- DBMS(데이터베이스 관리 시스템): 동시성, 성능, 보안 등을 관리
ex) 대학교 행정관리, 도서관 관리 시스템
복학을 했는데, 도서관에서 책을 빌리고자 할때 휴학생으로 등록되어 있어 책을 못 빌리는 상황. 옛날에는 데이터들이 동일 네트워크를 통해 실시간 업데이트가 안돼서 이처럼 불편한 일들이 많이 발생함.
그래서 데이터들을 베이스화 하기로 함 베이스화로 데이터들을 한 곳에 모이게 하고, 데이터를 쪼개면서 중복을 없애는 방법으로 결함을 줄임. 이렇게 자른 데이터를 정규화된 데이터라고 부른다.
데이터를 잘라낼 하나하나의 데이터를 저장 모델에 부합되는 구조(schema)라 하고, 잘라놨던 데이터의 원본(하나의 데이터)을 화면에 출력시킬 데이터를 뷰라고 한다.
베이스화로 인해 동시에 요청이나 응답이 발생하거나, 아무나 동일 네트워크라면 데이터에 접근할 수 있는 문제가 발생했다.
동시성, 성능, 보안을 관리할 관리자가 필요하여, DBMS (데이터베이스 관리 시스템)이 등장하게 되었다.
구조 DBMS 네트워크 DBMS 객체 지향 DBMS 관계형 DBMS
Oracle, MySQL등이 DBMS를 만들게 됐다.
SQL(Structured Query Language) ORM(Object Relational Mapping) - MongoDB의 Mongoose, TS/JS에서의 Prisma 등.. 데이터베이스와 객체지향 프로그래밍 언어 사이의 데이터를 변환해주는 기술이다. ORM을 통해 SQL 쿼리를 직접 작성하지 않고 프로그래밍 언어의 객체를 통해 데이터베이스를 조작할 수 있다.
용어 정리 📚
데이터베이스 용어 | 설명 |
---|---|
엔티티 타입 | 테이블(릴레이션) |
엔티티 인스턴스 | 튜플(행) |
엔티티 속성 | 컬럼(열) |
실선 관계 | 식별관계 (외래키를 가져와서 주키로 사용) |
점선 관계 | 비식별관계 (자신만의 주키가 따로 존재하고, 외래키가 속성으로 존재) |
카디널리티 | 행의 개수 |
차수(Degree) | 열의 개수 |