Skip to content

MySQL ‐ Learning Data Modeling Through Practical Examples

woojin.jang edited this page Apr 7, 2026 · 5 revisions

MySQL - Learning Data Modeling Through Practical Examples

Data Modeling: Logical Design for Boolean Attributes

  • 논리 모델링에서 Boolean(True/False) 타입은 양날의 검과 같다.
  • 비즈니스 요구사항이 정말 단순한 Yes/No로 완벽하게 설명될 때는 최고의 선택이지만, 복잡한 개념을 억지로 압축하려고 할 때는 미래의 기술 부채(Technical Debt)가 된다.

🟢 단순 Yes/No라면 쓰는 것이 좋다(Good Cases)

  • 비즈니스 로직상 더 이상의 부가 정보가 절대 필요 없는 순수한 상태나 플래그(Flag)일 때는 Boolean이 가장 직관적이고 효율적이다.
    • is_deleted(논리적 삭제 여부) : 데이터베이스에서 실제로 레코드를 지우지 않고 숨김 처리만 할 때 사용한다. "삭제되었는가?"에 대한 답은 철저하게 O/X로 나뉜다.
    • is_email_verified(이메일 인증 여부) : 인증을 했거나, 안 했거나 둘 중 하나이다.
    • is_default_address(기본 배송지 여부) : 여러 배송지 중 기본 배송지인지 판별하는 순수한 논리적 플래그이다.
  • 이런 경우 Boolean 속성은 모델을 단순하게 유지해 주고 쿼리의 가독성을 높여주는 아주 좋은 설계이다.

🔴 함축적으로 가져가면 안 좋은 경우(Bad Cases)

  • 현재는 Yes/No처럼 보이지만, 속성 내부에 더 복잡한 의미나 '확장 가능성'이 숨어있는 경우이다.
    • has_discount(할인 적용 여부) : 처음 기획할 때는 "이 상품 할인해?"라는 질문에서 시작하여 Boolean으로 만들기 쉽다. 하지만 서비스가 성장하면 필연적으로 "할인율은 몇 %야?", "할인 기간은 언제까지야?", "쿠폰 할인이야, 정률 할인이야?" 같은 요구사항이 붙는다. 이 경우 Boolean 대신 '할인(Discount)'이라는 별도 테이블이나 더 구체적인 속성들로 도출했어야 한다.
    • is_premium_member(프리미엄 회원 여부) : "유료 회원인가요?"라는 질문엔 Yes/No가 맞지만, 나중에 '골드', '플래티넘' 같은 등급(Tier)이 추가되는 순간 이 컬럼은 쓸모가 없어진다. 처음부터 membership_level(VARCHAR/ENUM 등)이나 별도의 등급 엔티티로 설계하는 것이 안전하다.
    • has_wifi(와이파이 유무) : 식당 정보에서 has_wifi가 True라고 해보자. 사용자가 "비밀번호는 뭔가요?"라고 묻는다면 이 데이터 모델은 대답할 수 없다.

Data Modeling: Physical Design Strategy – One Table per Anchor

CREATE TABLE restaurants (
    restaurant_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    address VARCHAR(200),
    phone VARCHAR(20),
    has_parking BOOLEAN DEFAULT FALSE,
    has_wifi BOOLEAN DEFAULT FALSE,
    has_delivery BOOLEAN DEFAULT FALSE,
    is_vegetarian_friendly BOOLEAN DEFAULT FALSE,
    has_outdoor_seating BOOLEAN DEFAULT FALSE,
    has_live_music BOOLEAN DEFAULT FALSE,
    accepts_credit_card BOOLEAN DEFAULT FALSE,
    is_24_hours BOOLEAN DEFAULT FALSE
    has_rooftop BOOLEAN DEFAULT FALSE
);
  • 장점 : JOIN 필요 없고 별도 테이블이 필요 없다. 초기 개발 단계에서는 굉장히 큰 장점을 가진다.
  • 단점 : 유지보수 및 확장성 관점에서는 굉장히 불리하다.

Data Modeling: Physical Design Strategy – Side Tables

-- 메인 테이블: 핵심 비즈니스 정보만 포함
CREATE TABLE restaurants (
    restaurant_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    address VARCHAR(200),
    phone VARCHAR(20),
    created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Side Table: Boolean 속성들을 별도 테이블로 분리
CREATE TABLE restaurant_flags (
    restaurant_id INT PRIMARY KEY,
    has_parking BOOLEAN DEFAULT FALSE,
    has_wifi BOOLEAN DEFAULT FALSE,
    has_delivery BOOLEAN DEFAULT FALSE,
    is_vegetarian_friendly BOOLEAN DEFAULT FALSE,
    has_outdoor_seating BOOLEAN DEFAULT FALSE,
    has_live_music BOOLEAN DEFAULT FALSE,
    accepts_credit_card BOOLEAN DEFAULT FALSE,
    is_24_hours BOOLEAN DEFAULT FALSE,
    FOREIGN KEY (restaurant_id) REFERENCES restaurants(restaurant_id)
);

-- @Transactional(스프링 생태계에서 사용되는 선언적 어노테이션)

begin;

UPDATE restaurants SET name = 'New Name' WHERE restaurant_id = 1;
UPDATE restaurant_flags SET has_parking = true WHERE restaurant_id = 1;

commit;
  • 장점 : 메인 테이블의 경량화 및 I/O 성능 향상, 메인 테이블 잠금 및 장애 리스크 감소, 확고한 데이터 정합성 보장
  • 단점 : 조회 시 필연적인 JOIN 오버헤드, 근본적인 스키마 유연성 문제 미해결, 애플리케이션 로직의 복잡도 증가

Data Modeling: Physical Design Strategy – Entity-Attribute-Value (EAV)

-- 메인 엔티티 테이블
CREATE TABLE restaurants (
    restaurant_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    address VARCHAR(200),
    phone VARCHAR(20),
    created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- EAV 테이블: 속성을 행으로 저장
CREATE TABLE restaurant_attributes (
    restaurant_id INT NOT NULL,
    attr_name VARCHAR(50) NOT NULL,
    attr_value VARCHAR(100),
    created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (restaurant_id, attr_name),
    FOREIGN KEY (restaurant_id) REFERENCES restaurants(restaurant_id)
);

INSERT INTO restaurant_attributes (restaurant_id, attr_name, attr_value) VALUE (1, 'test', 'true');
INSERT INTO restaurant_attributes (restaurant_id, attr_name, attr_value) VALUE (1, 'has_parking', 'true');
  • 장점 : 무한한 확장성과 궁극의 유연성을 가진다.
  • 단점 : 데이터 정합성 파괴 가능성이 매우 높으며 쿼리 지옥과 성능 저하를 유발한다.
스크린샷 2026-04-08 00 41 15

Database Design Deep Dive: Schema Evolution

  • COPY : 기존 방식으로 테이블을 복사하는 방식
  • INPLACE : 인덱스 재구성하는 방식
  • DEFAULT : MySQL이 자동으로 선택
  • NONE : 락 없이 실행
  • SHARED : 공유 락을 사용
  • EXCLUSIVE : 배타 락을 사용
  • DEFAULT : MySQL이 자동으로 선택
-- 1. 데이터 타입 변경
ALTER TABLE restaurants
    MODIFY COLUMN name VARCHAR(200),
    ALGORITHM=COPY, LOCK=EXCLUSIVE;

-- 2. 컬럼 이름 변경
ALTER TABLE restaurants
    CHANGE COLUMN name restaurant_name VARCHAR(100),
    ALGORITHM=COPY, LOCK=EXCLUSIVE;

❗ALTER TABLE 작업이 긴 다운타임을 유발하는 이유 : 기존 테이블을 복사하고 새로운 테이블을 만드는 과정에서 독점 잠금을 사용하여 다른 모든 작업을 차단해 서비스 다운타임을 발생시키기 때문이다.

Database Design Deep Dive: Modern Alternatives

-- MySQL JSON 테이블 생성
CREATE TABLE restaurants (
    restaurant_id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    attributes JSON
);

-- JSON 데이터 삽입
INSERT INTO restaurants (restaurant_id, name, attributes) VALUES
    (1, 'Pizza Palace', '{"has_parking": true, "has_wifi": true}'),
    (2, 'Burger King', '{"has_parking": false, "has_wifi": true}');
  • 장점 : 스키마 리스(schema-less) 유연성, 데이터 타입의 엄격한 보존(JSON 타입 그대로), 비정형 데이터의 효율적 관리, 강력한 JSON 내장 함수 지원
  • 단점 : 데이터 무결성 제약 부재, 검색 성능 한계(인덱스를 걸기 어려움), 통계 및 집계 어려움, 저장 공간 오버헤드

📖 Java

📖 Kotlin

📖 Coroutine

📖 Spring

📖 Spring Security

📖 Spring Batch

📖 Reactive Programming

📖 Database

📖 MySQL

📖 Redis

📖 JPA

📖 QueryDsl

📖 MSA

📖 Kafka

📖 Apache Flink

  • [Apache Flink - Apache Flink Architecture]
  • [Apache Flink - Stream Processing]
  • [Apache Flink - Data Stream API & Window]
  • [Apache Flink - State Management]

📖 HTTP

📖 AWS

📖 Docker

📖 Kubernetes

📖 CI/CD

📖 Nginx

📖 Monitoring🥈

  • [Monitoring - Log Concept]
  • [Monitoring - Log Level & Filter]
  • [Monitoring - Logback]
  • [Monitoring - Log Collection with ELK Stack]
  • [Monitoring - Log Monitoring with Kibana]
  • [Monitoring - Building a Monitoring System with Spring Boot Actuator]
  • [Monitoring - Server Monitoring with Prometheus and Grafana with Discord Alerts]

📖 Test

📖 Effective Java 3/E

📖 Kotlin Academy - Effective Kotlin

📖 Kotlin Academy - 핵심편

📖 스프링으로 시작하는 리액티브 프로그래밍

📖 가상 면접 사례로 배우는 대규모 시스템 설계 기초 1

📖 가상 면접 사례로 배우는 대규모 시스템 설계 기초 2

📖 Clean Code

📖 리팩토링 2판

📖 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식

📖 GraphQL

Clone this wiki locally