MySQL 데이터 타입 설명: 성능과 확장성을 위한 올바른 컬럼 타입 선택

目次

1. 소개: MySQL 데이터 타입 목록을 이해해야 하는 이유

MySQL로 테이블을 설계하거나 애플리케이션을 연동할 때 가장 흔히 떠오르는 질문 중 하나는 “이 컬럼에 어떤 데이터 타입을 써야 할까?” 입니다.
INT가 맞을까? 정말 BIGINT가 필요할까? 문자열에는 VARCHAR면 충분할까, 아니면 TEXT가 나을까? 이런 선택은 사소해 보일 수 있지만, 나중에 시스템 전체에 영향을 미치는 기반을 형성합니다.

데이터 타입 선택을 과소평가하면 다음과 같은 문제에 자주 직면하게 됩니다:

  • 데이터가 예상보다 크게 성장하면서 저장 공간을 낭비하게 됨
  • 인덱스가 부풀어 오르고 쿼리 성능이 점차 저하됨
  • 범위를 초과하거나 오버플로우가 발생해 예기치 않은 버그나 예외가 발생함
  • 나중에 컬럼 타입을 변경해야 하는 상황이 생겨 대규모 마이그레이션을 강요받음

즉, MySQL 데이터 타입을 체계적으로 이해하고 사용 사례마다 적절한 타입을 선택하는 것이 성능과 유지보수성을 동시에 향상시키는 가장 빠른 방법입니다.

이 페이지는 주로 다음과 같은 독자를 위해 준비되었습니다:

  • MySQL을 이용해 본격적인 시스템 개발을 시작하려는 엔지니어
  • 기존 테이블 설계를 검토하고 싶은 백엔드/인프라 중심 엔지니어
  • 사용 사례별 “추천 타입”을 찾는 웹 개발자 및 프로그래머

우선 주요 MySQL 데이터 타입을 카테고리별 “목록” 형태로 정리합니다. 이후 핵심 타입(숫자, 문자열, 날짜/시간, JSON, ENUM/SET)을 특징, 전형적인 사용 사례, 선택 팁과 함께 설명합니다. 마지막으로 흔히 저지르는 설계 실수와 회피 방법, 그리고 FAQ를 정리합니다.

이는 단순한 “용어 목록”이 아니라 실제 프로젝트에서 테이블을 설계할 때 막히지 않도록 돕는 의사결정 가이드로 구성되었습니다. 다음 섹션에서는 데이터 타입을 어떻게 생각하고, 카테고리화된 목록을 어떻게 검토할지 살펴보겠습니다.

2. 데이터 타입이란 무엇이며, “올바른 타입 선택”이 왜 중요한가?

데이터베이스에서 “데이터 타입”은 컬럼이 저장할 수 있는 값의 종류를 정의하는 규칙입니다.
MySQL은 정수, 소수, 문자열, 날짜, 바이너리, JSON 등 다양한 데이터 타입을 제공하므로 목적에 맞게 적절히 선택해야 합니다.

데이터 타입의 역할

데이터 타입은 단순히 “포맷 카테고리”가 아닙니다. 동시에 여러 역할을 수행합니다:

  • 데이터 종류 제한(숫자 vs 문자열, 불리언 등)
  • 허용 범위와 자릿수 정의
  • 필요 메모리(스토리지 크기) 결정
  • 인덱스 구조와 검색 성능에 영향
  • 암시적 변환 및 비교 규칙에 영향(예: 문자열 정렬 규칙)

요컨대, 데이터 타입은 단순히 “컨테이너”가 아니라 전체 데이터 관리 라이프사이클에 영향을 미치는 근본적인 설계 선택입니다.

잘못된 타입을 선택하면 어떻게 되는가?

실무에서 잘못된 데이터 타입을 선택하면 다음과 같은 문제가 자주 발생합니다:

• 저장 공간 낭비

예를 들어 BIGINT(8바이트)만 충분한데 DECIMAL이나 LONGTEXT를 사용하면 예상보다 훨씬 많은 디스크 공간을 차지하게 됩니다.

• 쿼리 속도 저하

거대한 TEXT 컬럼에 대해 LIKE 검색을 과도하게 사용하거나, 지나치게 큰 숫자 타입을 선택해 인덱스가 부풀면 SQL 실행 속도가 느려집니다.

• 값 불일치 또는 오버플로우

INT에 들어가지 않는 값을 저장하면 예상치 못한 음수값, 반올림, 기타 문제가 발생할 수 있습니다.

• 높은 비용의 테이블 변경

특히 대용량 테이블에서 ALTER TABLE로 타입을 변경하면 다음과 같은 비용이 발생합니다:

  • 긴 잠금 시간
  • 서비스 영향
  • 데이터 마이그레이션 작업 및 기타 위험

미리 이해해야 할 주요 카테고리

MySQL 데이터 타입은 크게 다음과 같이 구분됩니다:

  • 숫자 타입(정수, 소수)
  • 문자열 타입
  • 날짜·시간 타입
  • 바이너리 타입
  • JSON 타입
  • ENUM / SET 타입
  • 공간 데이터 타입

각 카테고리는 서로 다른 트레이드오프를 가집니다—강점/약점, “가벼움 vs. 무거움,” 그리고 “검색하기 쉬움 vs. 어려움.” 그래서 각 사용 사례에 대한 최적의 타입 선택이 필요합니다.

3. MySQL 데이터 타입 카테고리 (개요 목록)

이 섹션에서는 MySQL에서 사용 가능한 데이터 타입을 카테고리별 개요 목록으로 요약하겠습니다. 실제로 확인하고 싶은 첫 번째 사항은 “어떤 타입이 존재하나?”와 “어떤 것을 사용해야 하나?”입니다.
그래서 여기서는 사용 사례, 주요 특징, 그리고 대표 타입 이름을 명확히 보여주고, 다음 섹션에서 각 카테고리를 더 자세히 설명하겠습니다.

3.1 숫자 타입

숫자 타입은 정수, 소수, 부동소수점 값 등을 포함한 모든 숫자 처리의 기반입니다.
이 카테고리는 ID, 수량, 가격, 플래그 확인 등 다양한 목적으로 가장 자주 사용됩니다.

정수 타입

TypeBytesCharacteristics / Use Cases
TINYINT1B-128 to 127. Ideal for flags and small numbers
SMALLINT2B-32,768 to 32,767. Lightweight integers
MEDIUMINT3BInteger type that can handle a mid-range
INT / INTEGER4BThe most common integer type. Often used for IDs
BIGINT8BLarge values (order numbers, log counters, etc.)

주의사항

  • UNSIGNED를 추가하면 양수 범위가 두 배로 늘어납니다.
  • INT는 많은 경우에 사용되지만, BIGINT를 무심코 사용하면 인덱스가 무거워질 수 있습니다.

소수 / 부동소수점 타입

TypeCharacteristics
DECIMALBest for amounts like currency where errors are unacceptable
NUMERICSynonymous with DECIMAL
FLOATMemory-efficient, but may introduce rounding errors
DOUBLEHigher precision than FLOAT, but errors can still occur

주의사항

  • 돈 관련 데이터의 경우, DECIMAL이 유일하게 합리적인 선택입니다. 부동소수점 타입(FLOAT / DOUBLE)은 오류를 유발할 수 있습니다.
  • 많은 계산이 포함된 경우, 속도/정밀도 트레이드오프로 DOUBLE을 선택하기도 합니다.

기타 숫자 타입

TypeCharacteristics
BITBit-level flag management (0/1)
BOOL / BOOLEANActually an alias for TINYINT(1)

3.2 날짜 및 시간 타입

날짜/시간 처리는 애플리케이션 개발에서 매우 자주 사용됩니다.
목적에 따라 “시간대 동작,” “자동 업데이트,” “초 단위 정밀도” 등의 요소가 다르기 때문에 적절한 타입을 선택하는 것이 중요합니다.

TypeCharacteristics / Use Cases
DATEDate only (YYYY-MM-DD)
TIMETime only (HH:MM:SS)
DATETIMEDate + time. Not affected by time zones
TIMESTAMPDate + time. Stored as UNIX time; affected by time zones; can auto-update
YEARStores the year only (YYYY)

주의사항

  • “업데이트 시각”을 자동으로 관리하고 싶다면 TIMESTAMP가 편리합니다.
  • 정확한 타임스탬프를 저장해야 하는 “로그”나 “히스토리”의 경우 DATETIME이 일반적으로 사용됩니다.

3.3 문자열 / 바이너리 타입

사용자 이름, 이메일, 비밀번호, 설명—문자열은 테이블 설계에서 가장 복잡한 영역인 경우가 많습니다.

고정 길이 문자열

TypeCharacteristics
CHAR(n)Always reserves space for exactly n characters. Suitable for fixed-length data (e.g., country codes)

가변 길이 문자열

TypeCharacteristics
VARCHAR(n)The most common string type. Best for data with varying length

대용량 텍스트 (TEXT 계열)

TypeCharacteristics
TINYTEXTUp to 255 characters
TEXTStrings up to 64KB
MEDIUMTEXTUp to 16MB
LONGTEXTUp to 4GB

주의사항

  • 기사 본문이나 긴 설명과 같은 매우 큰 문자열을 저장해야 할 때 TEXT를 사용하세요.
  • 검색 및 인덱스 설계에 주의하세요.

바이너리 데이터 (BINARY / BLOB)

TypeCharacteristics
BINARY / VARBINARYFixed-length / variable-length binary data
BLOB / MEDIUMBLOB / LONGBLOBLarge binary data such as images and files

※ 일반적으로 대용량 파일은 데이터베이스에 저장하지 않습니다. 대신 외부 스토리지에 저장하는 것이 일반적인 설계입니다.

ENUM / SET 타입 (열거형)

TypeCharacteristics
ENUMSelect exactly one value from a predefined set of strings
SETAn enumeration type that allows selecting multiple values

주의사항

  • 나중에 타입 정의를 변경해야 한다면 유지보수가 무거워집니다.
  • 소규모, 정적 후보에 대해서는 효과적일 수 있습니다.

3.4 JSON 타입

TypeCharacteristics
JSONStores structured data. Officially supported since MySQL 5.7
  • NoSQL 같은 유연성을 얻으면서 JSON 전용 함수를 사용할 수 있습니다.
  • 그러나 자주 검색되는 데이터를 JSON에 압축하는 것은 권장되지 않습니다. 정규화가 가능하다면 구조화된 테이블로 모델링해야 합니다.

3.5 공간 타입

지리적 및 위치 데이터 작업 시 사용됩니다.

TypeCharacteristics
GEOMETRYBase type for spatial data
POINT, LINESTRING, POLYGONCoordinates, lines, areas, and more

일반적인 웹 애플리케이션에서는 자주 사용되지 않지만, 지도 앱이나 GPS 통합에는 중요합니다.

4. 각 데이터 타입 선택 및 사용 방법 (주요 결정 포인트)

이 섹션에서는 위에서 소개한 카테고리를 더 깊이 파고들며, “실제 시나리오에서 어떻게 선택할까”에 초점을 맞춥니다.
이름만 아는 것만으로는 부족합니다—최적의 데이터 타입 선택은 유지보수성, 성능, 미래 확장성에 큰 영향을 미칩니다.

4.1 숫자 타입 선택 방법

정수 타입 선택 기준

정수 타입을 선택할 때는 다음 세 가지 포인트에 중점을 두세요:

1. 필요한 최대 범위 이해

  • 작은 카운터 → TINYINT
  • 제품 수량 / 플래그 → SMALLINT / INT
  • 대규모 ID나 로그 → BIGINT

일부 프로젝트에서는 기본 키에 BIGINT를 과도하게 사용하지만, 이는 인덱스 크기를 쉽게 키우고 성능에 부정적인 영향을 미칠 수 있습니다.

2. UNSIGNED 적극 고려

If you only handle positive values (e.g., numeric IDs, inventory counts)
using UNSIGNED doubles the range and may allow you to use a smaller type.

3. 금액 또는 정밀도가 중요한 값은 DECIMAL 사용

For values where “errors are not acceptable,” avoid FLOAT/DOUBLE and always use DECIMAL.

4.2 날짜 및 시간 타입 선택 방법

The appropriate type depends on your use case.

DATETIME과 TIMESTAMP의 차이점

ItemDATETIMETIMESTAMP
Time zoneNot affectedAffected (converted)
Storage formatA “string-like” date/timeStored as UNIX time
Auto updateManualCan auto-update (e.g., DEFAULT CURRENT_TIMESTAMP)
RangeYear 1000 to 9999Year 1970 to 2038

선택에 대한 일반 규칙

  • 애플리케이션 로그 또는 이벤트 기록DATETIME (시간대 변환 영향을 피함)
  • 업데이트된 타임스탬프를 자동으로 기록하고 싶을 때TIMESTAMP (편리한 자동 업데이트 동작)

YEAR가 유용한 경우

  • 회계 연도 구분, 출시 연도, 설립 연도 등 → 컴팩트하게 관리 (1바이트)

4.3 문자열 타입 선택 방법

CHAR와 VARCHAR 중 선택 방법

CHAR를 사용해야 할 때

  • 길이가 항상 일정함: 지방 코드, 국가 코드, 고정 길이 식별자 등
  • 빠른 접근이 필요하고 업데이트가 드문 데이터

VARCHAR를 사용해야 할 때

  • 길이가 가변적임: 이름, 이메일 주소, 제목 등
  • 대부분 상황에서 가장 좋은 기본 선택

TEXT를 사용해야 할까?

TEXT의 장점

  • 큰 텍스트 지원 (설명, 기사 본문 등)

TEXT 사용 시 주의점

  • 인덱싱이 제한적임(프리픽스 인덱스 필요)
  • JOIN이나 WHERE 절에서 사용 시 성능 저하 가능
  • 검색 및 정렬에 비용이 많이 듦

추천:
본문이나 메모와 같은 “큰 문자열”에는 TEXT를 사용하고,
그 외 대부분의 경우에는 가능한 한 VARCHAR를 사용하십시오.

4.4 JSON 타입 선택 방법

JSON 타입은 매우 유용하지만, “올바르게” 사용해야 합니다.

JSON이 잘 작동하는 경우

  • 필드 수가 가변적인 유연한 설정 또는 데이터
  • 조회가 제한적인 경우, 혹은 애플리케이션이 확장/파싱하는 경우
  • 마스터 테이블이 필요 없는 경량 데이터 저장

JSON이 부적합한 경우

  • 자주 검색하는 데이터
  • 필터링 검색, 집계, JOIN에 사용되는 데이터
  • 정규화되어야 할 구조화된 데이터

경험 법칙:
검색이 필요한 데이터는 정규화하고 구조화된 형태로 다루어야 합니다.
JSON은 “유연하지만 검색에는 약하다”는 점을 잊지 마세요.

4.5 ENUM / SET 타입 선택 방법

ENUM이 적절한 경우

  • 상태가 고정됨: 예) 상태(draft / published / archived)
  • 거의 변하지 않는 소규모 옵션 집합

ENUM 사용 시 주의점

  • 값 추가 또는 변경 시 ALTER TABLE이 필요
  • 애플리케이션 측 정의와 일관성을 잃을 위험

SET이 적절한 경우

  • 다중 선택이 필요한 소규모 데이터(예: 사용 가능한 요일, 혹은 태그 옵션이 몇 개뿐인 경우)

SET 사용 시 주의점

  • 값 조합이 복잡해질 수 있음
  • 다중 값 상태 관리가 어려워질 수 있음

4.6 Binary / BLOB 타입 선택 방법

BINARY / VARBINARY

  • 토큰, ID, 해시 값 등
  • 고정 길이 바이너리(예: 16바이트 UUID)

BLOB 타입의 일반적인 사용 사례

  • 작은 파일, 썸네일 이미지, 암호화 데이터

하지만 주의

  • 데이터베이스에 대용량 파일을 저장하면 백업이 무거워짐
  • 읽기/쓰기 부하도 증가 → 실제 시스템에서는 외부 스토리지 + 경로 관리가 권장됩니다

5. 실습: 테이블 설계 시 “데이터 타입 참조 목록” 활용 방법

이 섹션에서는 테이블을 설계할 때 MySQL 데이터 타입 목록을 실무 흐름에 어떻게 활용하는지 설명합니다.
단순히 타입을 외우는 것이 아니라, 논리와 단계에 따라 “왜 해당 타입을 선택했는지”를 정리하면 더 높은 품질의 데이터베이스 설계가 가능합니다.

5.1 단계 1: 컬럼의 “목적”과 “성격” 명확히 하기

First, clearly define what will be stored in the column.

체크리스트

  • 숫자형, 문자열, 날짜, 혹은 플래그인가요?
  • 가변 길이인가요, 고정 길이인가요?
  • 최대값 또는 최대 길이는 얼마인가요?
  • NULL을 허용해야 하나요?
  • 향후 확장될 가능성이 있나요?

여기서 애매한 가정으로 진행하면, 나중에 타입 선택이 불필요하게 복잡해집니다.

5.2 단계 2: 필요한 범위와 형식 추정

다음으로, 저장할 값들의 상한/하한, 문자 길이, 그리고 필요한 정밀도를 추정하세요.

예시: ID 컬럼

  • 최대 레코드 수가 수천만? 수억에 이를까요? → 이를 통해 INT가 충분한지, BIGINT가 필요한지 판단할 수 있습니다.

예시: 제품명

  • 평균 15~25자, 최대 약 50자? → VARCHAR(50)이면 충분합니다. TEXT는 불필요합니다.

예시: 가격

  • 정밀도가 필요한가요? → DECIMAL(10,2)와 같은 타입을 선택해야 합니다.

5.3 단계 3: 데이터 양과 성능 고려

MySQL 데이터 타입을 선택하면 성능에 직접적인 영향을 미칩니다.

주요 고려 사항

  • 너무 큰 타입 → 저장 공간을 많이 차지하고 인덱스를 무겁게 만듭니다
  • TEXT / BLOB → 검색 성능 저하
  • JSON → 유연하지만 검색에는 약합니다
  • TIMESTAMP → 자동 업데이트와 비교에 효율적

특히 인덱스가 있는 컬럼은 가능한 가장 가벼운 데이터 타입을 사용해야 합니다.

5.4 단계 4: 샘플 데이터로 타입 검증

테이블을 설계한 후, 수십에서 수백 행의 테스트 데이터를 삽입하고 동작을 검증하세요.

확인 항목

  • 의도치 않은 반올림이나 절단 문제가 있나요?
  • VARCHAR가 충분한가요, 아니면 TEXT여야 하나요?
  • 날짜/시간 정렬 및 검색이 기대대로 동작하나요?
  • JSON 읽기/쓰기 성능

실제와 유사한 데이터로 테스트하면 “이론적 오판”을 줄일 수 있습니다.

5.5 단계 5: 확장성 및 유지보수성 고려

테이블 설계의 최종 단계에서, 향후 변경이 쉬운지 확인하세요.

무거운 타입 변경 예시

  • ENUM (값을 추가할 때 ALTER TABLE 필요)
  • TEXTVARCHAR (확장은 쉽지만 축소는 위험함)
  • FLOATDECIMAL (의미가 바뀔 수 있음)

향후 확장이 예상되는지를 판단해 타입을 선택하세요.

5.6 단계 6: CREATE TABLE 예시 (실용 샘플)

아래는 일반적인 웹 애플리케이션에서 흔히 사용되는 데이터 타입 선택 기준을 반영한 예시 테이블입니다.

CREATE TABLE products (
    id           BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name         VARCHAR(100) NOT NULL,
    price        DECIMAL(10,2) NOT NULL,
    stock        INT UNSIGNED NOT NULL DEFAULT 0,
    status       ENUM('draft', 'published', 'archived') NOT NULL DEFAULT 'draft',
    description  TEXT,
    created_at   DATETIME NOT NULL,
    updated_at   TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

이 예시의 핵심 포인트

  • id : 향후 규모를 고려해 BIGINT UNSIGNED 사용
  • name : 중간 길이 가변 문자열 → VARCHAR
  • price : 금액 값 → 정밀한 DECIMAL
  • stock : 재고 수량 → INT UNSIGNED
  • status : 고정된 값 집합 → ENUM
  • description : 길어질 수 있는 텍스트 → TEXT
  • updated_at : 편리한 자동 업데이트 TIMESTAMP

보시다시피, 모든 타입 선택에는 명확한 이유가 있어야 하며, 그 이유를 설명할 수 있는 것이 좋은 설계의 특징입니다.

6. 흔히 저지르는 실수와 회피 방법

MySQL은 다양한 데이터 타입을 제공하기 때문에 실제 프로젝트에서 흔히 발생하는 실수가 여러 가지 있습니다. 이 섹션에서는 전형적인 함정을 강조하고 실용적인 대책을 제시합니다.

6.1 과도하게 큰 데이터 타입 사용

일반적인 예시

  • 모든 ID를 BIGINT로 지정
  • 모든 문자열을 VARCHAR(255)로 설정
  • 비텍스트 콘텐츠에 TEXT 사용

문제점

  • 저장 공간 낭비
  • 인덱스 비대화로 쿼리 성능 저하
  • 네트워크 대역폭 낭비(데이터 전송량 증가)

회피 방법

  • 최대값과 최소값을 미리 추정한다
  • VARCHAR 길이를 근거에 따라 설정한다
  • 필요할 때만 TEXT를 사용한다

6.2 부동소수점(FLOAT/DOUBLE) 사용 시 소수값(정밀도 문제)

일반적인 예시

  • FLOAT 로 가격을 저장한다
  • 반올림 오류로 숫자 비교가 실패한다

회피 방법

  • 금액 및 정밀도가 중요한 값에는 DECIMAL 을 사용한다
  • 과학적이거나 일시적인 계산을 제외하고는 FLOAT / DOUBLE 사용을 피한다

6.3 과도하게 큰 VARCHAR 컬럼

일반적인 예시

  • 기본값으로 VARCHAR(255) 사용
  • 약 30자만 저장하는 컬럼에 큰 길이를 설정

문제점

  • 메모리와 저장소 낭비
  • 인덱스가 종종 무거워진다

회피 방법

  • 실제 데이터에서 평균 및 최대 길이를 추정한다
  • 불필요하게 큰 크기를 피한다 (예: 이메일 주소 → VARCHAR(100))

6.4 TEXT 타입 남용

일반적인 예시

  • “문자열 = TEXT” 라고 가정한다
  • 필터링이나 검색이 필요한 데이터를 TEXT 로 사용한다

문제점

  • 인덱싱 제한이 많다
  • LIKE 검색이 무겁다
  • JOIN에서 처리 속도가 느려진다

회피 방법

  • 설명이나 본문 같은 장문 콘텐츠에만 TEXT 를 사용한다
  • 가능하면 검색 가능한 문자열은 VARCHAR 에 저장한다

6.5 속성을 이해하지 못한 채 날짜/시간 타입 선택

일반적인 예시

  • 모든 경우에 DATETIME 사용
  • “updated at”에 DATETIME 사용해 자동 업데이트가 안 되게 함
  • 시간대 차이로 타임스탬프가 이동한다

회피 방법

  • 자동 업데이트가 필요하면: TIMESTAMP
  • 시간대 이동을 피하고 싶다면: DATETIME
  • 연도만 필요하면: YEAR

6.6 ENUM / SET을 너무 가볍게 사용

일반적인 예시

  • 앞으로 옵션이 바뀔 수 있음에도 ENUM 사용
  • SET 을 콤마 구분 리스트처럼 사용

문제점

  • 변경 시 ALTER TABLE 필요
  • 애플리케이션 측 정의와 불일치 가능성 증가

회피 방법

  • 값이 늘어날 수 있으면 별도 마스터 테이블에서 관리
  • 셋이 작고 확실히 고정된 경우에만 ENUM 사용

6.7 “편리함” 때문에 JSON에 과도하게 담기

일반적인 예시

  • 정규화해야 할 구조를 JSON에 담는다
  • 자주 검색되는 데이터를 JSON에 저장한다

문제점

  • 검색 성능 저하
  • 인덱스 효율 감소 / 사용 어려움
  • 애플리케이션 측 파싱 작업 증가
  • 스키마 없는 설계로 일관성 깨지기 쉬움

회피 방법

  • 검색하지 않는 데이터에만 JSON 사용
  • 설정과 같은 ‘작고 가변적인 데이터’에만 제한
  • JOIN 및 검색에 사용되는 정보를 정규화

6.8 타입 변경 비용을 과소평가

문제점

  • 대형 테이블에서 ALTER TABLE 은 매우 무거울 수 있다
  • 서비스 다운타임이나 긴 락 시간이 발생할 수 있다
  • 경우에 따라 데이터 마이그레이션이 필요하다

회피 방법

  • 설계 단계에서 향후 성장 계획
  • ENUM 을 신중히 사용
  • DECIMAL 의 정밀도/스케일에 여유를 둔다 (하지만 과도하게 하지 않는다)

7. 요약

MySQL은 다양한 데이터 타입을 제공하며, 선택한 타입은 성능, 확장성, 유지보수성에 큰 영향을 미칩니다.
특히 데이터가 지속적으로 증가하는 웹 애플리케이션 같은 환경에서는 초기 설계 결정이 장기적인 품질에 직접적인 영향을 줍니다.

이 글의 주요 요점

  • 데이터 타입은 “값의 종류, 범위, 정밀도, 저장소, 성능”에 영향을 주는 중요한 요소이다.
  • 숫자, 문자열, 날짜/시간, JSON, ENUM/SET, BLOB 타입은 각각 장단점이 있다.
  • 정수, 문자열, 날짜/시간 타입이 가장 많이 사용되므로 올바른 선택이 중요하다.
  • JSON과 ENUM은 편리하지만 오용하면 유지보수가 어려워진다.
  • TEXTBLOB을 과도하게 사용하면 성능이 저하될 수 있다.
  • 합리적인 설계 접근법은: “목적 → 범위 → 성능 → 확장성”이다.

오늘부터 사용할 수 있는 설계 체크리스트

  • 컬럼의 목적이 명확히 정의되어 있나요?
  • 가능한 최대값과 최소값을 이해하고 있나요?
  • 선택한 VARCHAR 길이에 대한 근거가 있나요?
  • 금액에 DECIMAL을 사용하고 있나요?
  • “updated at” 타임스탬프가 TIMESTAMP와 자동 업데이트로 적절히 관리되고 있나요?
  • ENUM을 사용하기 전에 향후 값이 증가할 가능성을 고려했나요?
  • JSON을 과도하게 사용해 검색이 느려지는 설계를 피하고 있나요?
  • 대용량 데이터셋에서 무거운 ALTER TABLE 작업을 피하도록 설계했나요?

마무리

MySQL 데이터 타입을 선택할 때 항상 단 하나의 “정답”이 있는 것은 아닙니다.
하지만 목적과 미래 성장을 염두에 두고 선택한다면 주요 문제를 예방하고 데이터 구조를 깔끔하게 유지할 수 있습니다.

궁극적으로 최선의 선택은 프로젝트의 특성, 데이터 양, 그리고 애플리케이션 요구사항에 따라 달라집니다. 하지만 이 글에서 소개한 기준을 기반으로 삼으면 어떤 상황에서도 더 나은 데이터 타입 선택을 할 수 있을 것입니다.

다음으로 실제 업무에서 자주 묻는 질문들을 정리한 FAQ 섹션을 소개하겠습니다.
타입 선택에 확신이 서지 않을 때, 먼저 이 FAQ를 확인하면 보다 원활하게 결정할 수 있습니다.

8. FAQ

MySQL 데이터 타입 선택은 실제 경험에 따라 결정이 크게 달라질 수 있는 영역입니다.
여기서는 개발 팀에서 자주 묻는 질문들을 모아 간결하고 명확한 답변을 제공합니다.

Q1. INT와 BIGINT 중 어느 것을 사용해야 할까요?

A: 기본적으로 INT를 사용하세요. 미래에 21억을 초과할 가능성이 있을 때만 BIGINT를 사용하세요.

INT(4바이트)는 약 21억까지 지원하며 대부분의 애플리케이션에 충분합니다.
로그, 고트래픽 서비스, 혹은 매우 많은 ID를 발행할 가능성이 있는 시스템에는 BIGINT를 고려하세요.

Q2. VARCHAR와 TEXT 중 어느 것을 사용해야 할까요?

A: 검색이 필요하면 VARCHAR를 사용하고, 장문 콘텐츠에는 TEXT를 사용하세요.

  • VARCHAR : 인덱스 친화적이며 검색에 유리
  • TEXT : 긴 콘텐츠에 적합하지만 검색이나 JOIN에는 최적이 아님

TEXT를 과도하게 사용하면 성능 저하를 초래할 수 있습니다.

Q3. 금액을 DOUBLE로 저장해도 될까요?

A: 아니요. 항상 DECIMAL을 사용하세요.

DOUBLEFLOAT는 반올림 오류를 발생시킬 수 있어 금액이나 정밀도가 중요한 값에는 적합하지 않습니다.
비즈니스 시스템에서는 DECIMAL(10,2) 또는 DECIMAL(12,2)가 일반적인 표준입니다.

Q4. DATETIME과 TIMESTAMP의 차이를 잘 모르겠어요. 어떻게 선택해야 할까요?

A: 자동 업데이트가 필요하면 TIMESTAMP를 사용하고, 시간대 변환 없이 정확한 타임스탬프를 저장해야 하면 DATETIME을 사용하세요.

  • TIMESTAMP : 자동 업데이트 및 시간대 변환 지원
  • DATETIME : 시간대 영향을 받지 않으며 날짜/시간을 그대로 저장

DATETIME은 로그 및 히스토리 테이블에 자주 사용됩니다.

Q5. ENUM을 사용해도 안전할까요?

A: 값이 “절대 변하지 않을” 경우에만 유용합니다.

ENUM은 가볍고 편리하지만, 값을 추가하거나 변경하려면 ALTER TABLE이 필요합니다.
값이 늘어날 가능성이 있는 필드의 경우, 별도의 테이블에서 마스터 관리하는 것이 권장됩니다.

Q6. 지금은 JSON만 사용해도 될까요?

A: 검색이 필요 없는 데이터에만 JSON을 사용하세요. 검색이 필요한 데이터는 정규화해야 합니다.

JSON은 유연하지만 성능상의 약점이 있습니다.

  • 검색에 약함
  • 인덱스 구조가 복잡해짐
  • 데이터 일관성 유지가 어려워짐

설정 및 옵션과 같이 검색 조건으로 사용되지 않는 속성에는 잘 활용됩니다.

Q7. VARCHAR의 최대 길이는 어떻게 결정해야 할까요?

A: 실제 데이터를 기반으로 최대값을 추정하고 약간의 여유를 두세요.

예시: 이메일 주소 → VARCHAR(100)이면 충분합니다
예시: 사용자 이름 → VARCHAR(50)이면 보통 충분합니다

“그냥 255”와 같이 무작정 크게 잡는 것은 권장되지 않습니다.

Q8. 잘못된 타입을 선택했을 경우, 나중에 변경할 수 있을까요?

A: 예, 변경은 가능하지만 대용량 테이블에서는 매우 무거운 작업이 될 수 있습니다.

ALTER TABLE은 전체 스캔 및 재구축을 수반하는 경우가 많아,
다운타임이나 긴 잠금 시간이 발생할 수 있습니다.

초기 설계 단계에서의 신중한 계획이 가장 중요합니다