데이터베이스 설계 주의사항

데이터베이스를 설계할 때 확신이 없다면 다음 사항들을 반드시 체크해야 합니다.

체크리스트

1. Index (인덱스)

  • 자주 검색되는 컬럼에 인덱스를 설정했는지 확인
  • 복합 인덱스의 순서가 쿼리 패턴에 맞는지 확인
  • 불필요한 인덱스가 성능을 저하시키지 않는지 검토

2. 텍스트 사이즈

  • VARCHAR, TEXT 등의 문자열 컬럼 크기가 적절한지 확인
  • 저장될 데이터의 최대 크기를 고려하여 설정
  • 너무 크게 설정하면 메모리 낭비, 너무 작으면 데이터 손실 발생

3. Nullable 여부

  • 해당 컬럼이 NULL 값을 허용해야 하는지 명확히 정의
  • NOT NULL 제약조건이 필요한 경우 설정
  • NULL 허용 시 애플리케이션에서의 NULL 처리 로직 고려

추가로 고려해야 할 사항

  • Primary Key: 고유 식별자 설계
  • Foreign Key: 테이블 간 관계 정의
  • 기본값(Default): 필요한 경우 기본값 설정
  • 유니크 제약조건: 중복 방지가 필요한 컬럼 식별

데이터베이스 아키텍처 참고 자료

다양한 도메인에 대한 데이터베이스 아키텍처 샘플을 참고하면 설계에 도움이 됩니다.

추천 리소스

이 사이트에서는 다음과 같은 다양한 도메인의 데이터 모델을 확인할 수 있습니다:

  • E-Commerce
  • Healthcare
  • Finance
  • Education
  • Manufacturing
  • 그 외 다수

실제 프로젝트에서 데이터베이스를 설계할 때, 유사한 도메인의 모델을 참고하여 시작하면 효율적입니다.


정규화 (Normalization)

데이터베이스 정규화는 데이터 중복을 최소화하고 무결성을 유지하기 위한 설계 기법입니다.

1정규형 (1NF)

  • 각 컬럼은 원자적 값(Atomic Value)만 포함
  • 반복 그룹 제거

잘못된 예시: phone 컬럼에 “010-1234-5678, 010-9876-5432” 저장

올바른 설계: 별도의 phone_numbers 테이블을 생성하여 각 전화번호를 독립된 행으로 저장

2정규형 (2NF)

  • 1NF를 만족하면서
  • 부분적 함수 종속 제거 (복합 키의 일부에만 종속되는 컬럼 분리)

3정규형 (3NF)

  • 2NF를 만족하면서
  • 이행적 함수 종속 제거 (A -> B -> C에서 A -> C 관계 제거)

반정규화 (Denormalization)

성능 최적화를 위해 의도적으로 정규화를 위반하는 경우도 있습니다. 자주 조인되는 테이블의 컬럼을 중복 저장하여 조회 성능을 향상시킵니다.

상황 정규화 반정규화
데이터 무결성 중시 적합 부적합
읽기 성능 중시 조인 비용 발생 적합
쓰기 성능 중시 적합 데이터 동기화 비용
데이터 변경 빈도 높음 적합 부적합

데이터 타입 선택 가이드

적절한 데이터 타입을 선택하면 저장 공간을 절약하고 쿼리 성능을 높일 수 있습니다.

숫자 타입

타입 범위 바이트 용도
TINYINT -128 ~ 127 1 상태값, 플래그
SMALLINT -32,768 ~ 32,767 2 작은 범위의 코드값
INT -21억 ~ 21억 4 일반적인 ID, 수량
BIGINT 매우 큰 범위 8 큰 범위의 ID, 금액
DECIMAL(M,D) 정밀 소수 가변 금액 (부동소수점 오류 방지)

금액 관련 데이터는 반드시 DECIMAL 타입을 사용해야 합니다. FLOAT이나 DOUBLE은 부동소수점 오류가 발생할 수 있습니다.

문자열 타입

타입 최대 크기 특징
CHAR(n) 255바이트 고정 길이, 패딩
VARCHAR(n) 65,535바이트 가변 길이
TEXT 65,535바이트 긴 텍스트
MEDIUMTEXT 16MB 중간 크기 텍스트
LONGTEXT 4GB 매우 큰 텍스트

길이가 항상 일정한 데이터(예: 국가 코드 ‘KR’, ‘US’)는 CHAR이 더 효율적이고, 가변 길이 데이터는 VARCHAR을 사용합니다.


인덱스 설계 원칙

인덱스는 데이터베이스 성능에 가장 큰 영향을 미치는 요소 중 하나입니다.

인덱스를 생성해야 하는 경우

  • WHERE 절에서 자주 사용되는 컬럼
  • JOIN 조건에 사용되는 컬럼
  • ORDER BY, GROUP BY에 사용되는 컬럼
  • 높은 선택도(Cardinality)를 가진 컬럼

인덱스를 생성하지 말아야 하는 경우

  • 데이터가 적은 테이블 (풀 스캔이 더 빠름)
  • INSERT, UPDATE, DELETE가 빈번한 컬럼
  • 선택도가 낮은 컬럼 (예: 성별, boolean 플래그)

복합 인덱스 순서

복합 인덱스의 컬럼 순서는 매우 중요합니다. 선택도가 높은 컬럼을 앞에 배치하는 것이 일반적입니다.

-- user_id의 선택도가 높으므로 앞에 배치
CREATE INDEX idx_orders ON orders (user_id, status, created_at);

이 인덱스는 WHERE user_id = ?, WHERE user_id = ? AND status = ?, WHERE user_id = ? AND status = ? AND created_at > ? 쿼리 모두에서 활용됩니다. 하지만 WHERE status = ?만 있는 쿼리에서는 이 인덱스를 사용할 수 없습니다.


트랜잭션 격리 수준

동시에 여러 트랜잭션이 실행될 때 데이터 일관성을 어느 수준까지 보장할지 결정하는 설정입니다.

격리 수준 Dirty Read Non-Repeatable Read Phantom Read
READ UNCOMMITTED 가능 가능 가능
READ COMMITTED 불가 가능 가능
REPEATABLE READ 불가 불가 가능
SERIALIZABLE 불가 불가 불가

MySQL InnoDB의 기본 격리 수준은 REPEATABLE READ이며, 대부분의 애플리케이션에서 적합합니다. 격리 수준이 높을수록 데이터 일관성은 보장되지만 동시성 처리 성능이 저하되므로, 서비스 요구사항에 맞게 적절한 수준을 선택해야 합니다.