https://inf.run/pxDWY
[본 게시물은 파트너스 활동의 일환으로 소정의 수수료를 받을 수 있습니다.]
[규칙 1] 한 칸에는 한 가지 정보만 들어가도록 만들어라 - 1
✅ 한 칸에는 한 가지 정보만 들어가도록 만들어라.
데이터베이스 테이블을 설계할 때 ‘한 칸에는 한 가지 정보만 들어가야 한다.’라는 규칙을 지켜야 한다.
위의 규칙을 안 지킨 사례
[사례 1]
users (사용자)
id(PK) | 이름 | 이메일 |
1 | 박재성 | js123@naver.com, js00@naver.com |
2 | 김시안 | king123@naver.com, queen123@naver.com |
=> 한 칸에는 한 가지 정보만 들어가야 하는데 2가지 정보가 들어가 있다.
[사례 2]
stores (가게)
id (PK) | 가게명 | 판매 상품 |
1 | JSCODE 카페 | JS아메리카노, JS카페라떼 |
2 | 재성이네 국밥 | 재성이네 돼지국밥, 재성이네 육개장, 재성이네 수육 |
위 사례를 살펴보면 한 칸에 2가지 이상의 정보가 들어가있는 걸 확인할 수 있다.
“왜 한 칸에 2가지 이상 정보가 들어가면 안 되는걸까?”
판매 상품 조회해서 사용할 때마다 -> 중간에 있는 콤마(,)를 제거하고 배열에 집어넣는 로직을 넣어야 함
판매 상품 삽입, 삭제 시 -> 항상 콤마(,)를 신경써서 작업해야 함
한 칸에 데이터를 여러 개 집어넣다보면 -> 실수로 데이터를 중복해서 삽입 가능성 발생
따라서 한 칸에는 한 가지의 정보만 넣으려고 하는 것
✅ 한 칸에 2개 이상의 정보가 들어가있을 땐?
한 칸에 2가지 이상의 정보가 들어가있을 때는 테이블을 분리하면 된다.
테이블을 분리함으로써 한 칸에 한 가지 정보만 들어가도록 해야 한다.
[사례 1 - 테이블 분리]
users (사용자)
id (PK) | 이름 |
1 | 박재성 |
2 | 김시안 |
emails (이메일)
id (PK) | 이메일 |
1 | js123@naver.com |
2 | js00@naver.com |
3 | king123@naver.com |
4 | queen123@naver.com |
테이블을 분리하는 것까진 좋은데 위와 같이 테이블을 분리하면, 특정 사용자의 이메일 주소를 알 수 있는 방법이 없다.
특정 사용자의 이메일 주소가 어떤 건지 알 수 있게 테이블을 보완해보자.
[사례 1 - 잘못된 분리]
users (사용자)
id (PK) | 이름 | 사용자 id (FK) |
1 | 박재성 | 1, 2 |
2 | 김시안 | 3, 4 |
emails (이메일)
id (PK) | 이메일 |
1 | js123@naver.com |
2 | js00@naver.com |
3 | king123@naver.com |
4 | queen123@naver.com |
위와 같이 데이터를 저장하니 특정 사용자의 이메일 주소를 알 수는 있게 됐다.
하지만 한 칸에 2가지 이상의 정보가 다시 들어가게 됐다.
이럴 때는 FK를 다른 테이블로 옮겨보자.
즉, FK의 위치를 users 테이블에서 emails 테이블로 옮겨보자.
[사례 1 - 최종]
users (사용자)
id (PK) | 이름 |
1 | 박재성 |
2 | 김시안 |
emails (이메일)
id (PK) | 이메일 | 사용자 id (FK) |
1 | js123@naver.com | 1 |
2 | js00@naver.com | 1 |
3 | king123@naver.com | 2 |
4 | queen123@naver.com | 2 |
위와 같이 데이터를 저장하니 특정 사용자의 이메일 주소도 알 수 있고, 한 칸에 한 가지의 정보만 들어가게 만들었다.
위와 같이 테이블을 분리해야 한다.
다시 한 번 정리해보자.
한 칸에 두 가지 이상의 정보가 들어가있을 땐, 테이블을 분리해서 FK를 활용해 한 칸에 한 가지의 정보만 들어가게 만들어야 한다.
두 번째 사례
[사례 2]
stores (가게)
id (PK) | 가게명 | 판매 상품 |
1 | JSCODE 카페 | JS아메리카노, JS카페라떼 |
2 | 재성이네 국밥 | 재성이네 돼지국밥, 재성이네 육개장, 재성이네 수육 |
[사례 2 - 잘못된 분리]
stores (가게)
id (PK) | 가게명 | 판매 상품 id (FK) |
1 | JSCODE 카페 | 1, 2 |
2 | 재성이네 국밥 | 3, 4, 5 |
products (판매 상품)
id (PK) | 상품명 |
1 | JS아메리카노 |
2 | JS카페라떼 |
3 | 재성이네 돼지국밥 |
4 | 재성이네 육개장 |
5 | 재성이네 수육 |
[사례 2 - 최종]
stores (가게)
id (PK) | 가게명 |
1 | JSCODE 카페 |
2 | 재성이네 국밥 |
products (판매 상품)
id (PK) | 상품명 | 가게 id (FK) |
1 | JS아메리카노 | 1 |
2 | JS카페라떼 | 1 |
3 | 재성이네 돼지국밥 | 2 |
4 | 재성이네 육개장 | 2 |
5 | 재성이네 수육 | 2 |
🧑🏻 이 과정을 보고 데이터베이스 이론에서는 제1정규형이라고 부른다.
이런 학구적인 용어는 DB 설계를 할 수 있게 됐을 때 배워도 늦지 않다.
중요한 건 DB 설계를 하는 능력이다. 정확한 용어를 외우고 익히는 건 나중에 해라.
[규칙 1] 한 칸에는 한 가지 정보만 들어가도록 만들어라 - 2
✅ 심화) ‘한 가지 정보’라는 게 관점에 따라 달라질 수 있다.
users (사용자)
id | 이름 |
1 | 박재성 |
2 | 김시온 |
users (사용자)
id | 성 | 이름 |
1 | 박 | 재성 |
2 | 김 | 시온 |
박재성이라는 전체 이름이 하나의 정보?
박, 재성 각각 하나의 정보?
둘 다 올바른 관점
말 그대로 ‘한 가지 정보’라는 건 절대적 X
자신의 서비스에 맞게 판단해야 함
그럼 어떻게 판단해야 할까?
→ 서비스에서 데이터의 사용 방식에 따라 결정해야 한다!
예를 들어, 서비스에서 성과 이름을 따로따로 조회해야 하는 경우가 많다면 2번째 테이블의 형태로 구성하는 게 좋다.
반대로 서비스에서 성과 이름을 따로따로 조회할 일이 없고 통째로 쓰는 경우만 있다면 1번째 테이블의 형태로 구성하는 게 좋다.
이와 비슷한 예시를 하나 더 알아보자.
stores (가게)
id | 전화번호 |
1 | 0321112345 |
2 | 0521234567 |
stores (가게)
id | 전화번호1 | 전화번호2 | 전화번호3 |
1 | 032 | 111 | 2345 |
2 | 052 | 123 | 4567 |
전화번호가 하나의 정보? 3가지의 정보?
둘 다 맞는 말이다.
어떻게 테이블을 설계해야 하는 지는 서비스에 맞게 판단하면 됨
만약 전화번호의 3가지 정보를 분리해서 따로따로 사용해야 하는 경우가 있다면 두 번째처럼 설계를 해야 함
✅ 요약
- 한 칸에는 한 가지 정보만 들어가야 한다.
- 한 칸에 두 가지 이상의 정보가 들어가있을 땐, 테이블을 분리해서 FK를 활용하면 된다.
- 특정 테이블에 FK를 도입했을 때 규칙 1이 안 지켜진다면, 다른 테이블로 FK를 옮겨보자.
- ‘한 가지 정보’의 기준은 절대적이지 않다. 따라서 서비스에 맞게 판단해야 한다.
[규칙 2] 어떤 테이블에 FK를 넣어도 ‘규칙 1’을 못 지킬 때는 중간 테이블을 하나 더 만들어라
✅ 어떤 테이블에 FK를 넣어도 ‘규칙 1’을 못 지킬 때는 중간 테이블을 하나 더 만들어라.
1.
students (학생)
id | 이름 | 수강 과목 |
1 | 박재성 | 수학, 과학 |
2 | 김재은 | 국어, 수학 |
3 | 김지훈 | 국어, 과학 |
위 테이블을 보면 규칙 1(한 칸에는 한 가지 정보만 들어가도록 만들어라)을 안 지키고 있다.
규칙 1을 지키게 만들기 위해 테이블을 분리해보자.
2.
students (학생)
id | 이름 | 수강 과목 id(FK) |
1 | 박재성 | 2, 3 |
2 | 김재은 | 1, 2 |
3 | 김지훈 | 1, 3 |
courses (수강 과목)
id | 과목명 |
1 | 국어 |
2 | 수학 |
3 | 과학 |
여전히 규칙 1을 안 지키고 있다.
그러면 FK를 students 테이블이 아닌 courses 테이블로 옮겨보자.
3.
students (학생)
id | 이름 |
1 | 박재성 |
2 | 김재은 |
3 | 김지훈 |
courses (수강 과목)
id | 과목명 | 학생 id |
1 | 국어 | 2, 3 |
2 | 수학 | 1, 2 |
3 | 과학 | 1, 3 |
FK의 위치를 다른 테이블로 바꿔봤음도 불구하고 여전히 규칙 1이 안 지켜진다. 이럴 땐 어떻게 해야 할까?
어떤 테이블에 FK를 넣어도 ‘규칙 1’을 못 지킬 때는 중간 테이블을 하나 더 만들어야 한다.
4.
students (학생)
id | 이름 |
1 | 박재성 |
2 | 김재은 |
3 | 김지훈 |
course_registrations (수강 과목 등록)
=> student_courses보다는 동사로 하면 좋다. 직관적으로 의미있게 지으면 가독성이 좋아진다.
id | 학생 id (FK) | 수강 과목 id (FK) |
1 | 1 | 2 |
2 | 1 | 3 |
3 | 2 | 1 |
4 | 2 | 2 |
5 | 3 | 1 |
6 | 3 | 3 |
courses (수강 과목)
id | 과목명 |
1 | 국어 |
2 | 수학 |
3 | 과학 |
위와 같이 테이블을 설계하면 어떤 학생이 어떤 과목들을 수강하는 지까지 다 파악할 수 있으며, 규칙 1을 지킬 수 있게된다.
✅ 또 다른 연습 예제
아래 테이블을 규칙 1을 지키도록 재구성해보자.
movies (영화)
id | 이름 | 출연 배우 |
1 | 베테랑 | 황정민, 오달수 |
2 | 신세계 | 황정민, 이정재 |
3 | 관상 | 이정재, 송강호 |
1. 테이블 분리
movies (영화)
id | 이름 | 출연 배우 id (FK) |
1 | 베테랑 | 1, 2 |
2 | 신세계 | 1, 3 |
3 | 관상 | 1, 4 |
actors (배우)
id | 이름 |
1 | 황정민 |
2 | 오달수 |
3 | 이정재 |
4 | 송강호 |
2. FK 위치 변경
movies (영화)
id | 이름 |
1 | 베테랑 |
2 | 신세계 |
3 | 관상 |
actors (배우)
id | 이름 | 영화 id (FK) |
1 | 황정민 | 1, 2 |
2 | 오달수 | 1 |
3 | 이정재 | 2, 3 |
4 | 송강호 | 3 |
3. 중간 테이블 추가
movies (영화)
id | 이름 |
1 | 베테랑 |
2 | 신세계 |
3 | 관상 |
castings (캐스팅)
=> movies_actors보다 더 직관적이다.
id | 영화 id (FK) | 배우 id (FK) |
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 1 |
4 | 2 | 3 |
5 | 3 | 3 |
6 | 3 | 4 |
actors (배우)
id | 이름 |
1 | 황정민 |
2 | 오달수 |
3 | 이정재 |
4 | 송강호 |
'CODING > 강의노트-JSCODE 박재성' 카테고리의 다른 글
[DB 설계] 섹션 3 - DB 설계의 핵심 원칙 및 전체 과정 (0) | 2025.05.27 |
---|---|
[DB 설계] 섹션 2 - DB 설계 전 필수로 알아야 하는 개념 (0) | 2025.05.09 |