데이터 타입
테이블 컬럼을 만들 때 저장할 데이터의 종류에 맞는 타입을 지정해야 한다. 잘못된 타입 선택은 저장 공간 낭비, 성능 저하, 정합성 문제를 일으킨다.
핵심: 데이터 타입은 저장 공간, 연산 성능, 정확도, 범위를 모두 고려하여 선택해야 합니다. 특히 금액, 날짜, 문자열은 타입 선택이 매우 중요합니다.
어떻게 쓰는지
컬럼 정의 시 타입 지정
CREATE TABLE product (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
price DECIMAL(10, 2), -- 금액 (정수 10자리, 소수 2자리)
discount DECIMAL(5, 2) DEFAULT 0, -- 할인율
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
타입 변환 (CAST)
-- 문자를 숫자로
SELECT CAST('123' AS INT);
-- 숫자를 문자로
SELECT CAST(123 AS VARCHAR(10));
-- 날짜 포맷 변환
SELECT DATE_FORMAT(created_at, '%Y-%m-%d') FROM product;
언제 쓰는지
| 상황 |
타입 |
이유 |
| 정수 ID(PK) |
✅ INT / BIGINT |
4/8 byte, 빠른 인덱싱 |
| 금액/통화 |
✅ DECIMAL |
정확한 소수점 계산 |
| 과학 계산 |
✅ FLOAT / DOUBLE |
근사치 연산 가능 |
| 이메일·URL |
✅ VARCHAR(255) |
가변 길이, 효율적 |
| 고정 길이 |
✅ CHAR(n) |
주민번호, 국가코드 |
| 긴 텍스트 |
✅ TEXT / LONGTEXT |
게시글, 설명 |
| 상태 플래그 |
✅ TINYINT / BOOLEAN |
1 byte 절약 |
| 생성 일시 |
✅ DATETIME / TIMESTAMP |
DATETIME 권장 |
| JSON 저장 |
✅ JSON |
MySQL 5.7+ |
| 파일 저장 |
✅ VARCHAR (URL) |
실제 파일은 S3 등 |
장점
| 장점 |
설명 |
| 저장 공간 절약 |
적절한 타입 선택으로 메모리 효율성 |
| 검색 성능 |
올바른 타입 = 인덱스 효율성 향상 |
| 연산 속도 |
DECIMAL vs FLOAT는 성능 차이 크다 |
| 정확성 |
금액은 DECIMAL, 날짜는 DATETIME |
| 범위 관리 |
타입으로 저장 가능한 범위 명확 |
단점
| 단점 |
설명 |
| 마이그레이션 비용 |
타입 변경은 대용량 테이블에서 많은 시간 |
| DBMS 호환성 |
JSON, DECIMAL 지원 버전 다름 |
| 유연성 부족 |
범위 초과 시 타입 자체 변경 필요 |
| 암묵적 형변환 |
FLOAT 오차, 문자열 자동 변환 위험 |
숫자형
| 타입 |
크기 |
범위 |
사용 예 |
TINYINT |
1 byte |
-128 ~ 127 (UNSIGNED: 0~255) |
boolean 대용, 상태값 |
SMALLINT |
2 byte |
-32,768 ~ 32,767 |
|
INT / INTEGER |
4 byte |
약 ±21억 |
일반 정수, PK |
BIGINT |
8 byte |
약 ±922경 |
대용량 PK, 타임스탬프 |
DECIMAL(p, s) |
가변 |
정밀한 소수 |
금액·통화 (정확도 우선) |
FLOAT / DOUBLE |
4 / 8 byte |
부동소수점 |
과학 계산 (근사치) |
위험: 금액에 FLOAT/DOUBLE을 쓰면 부동소수점 오차로 계산이 틀릴 수 있다. 반드시 DECIMAL을 사용한다.
문자형
| 타입 |
특징 |
사용 예 |
CHAR(n) |
고정 길이, 빈 공간은 공백 패딩 |
주민번호, 국가코드 등 길이가 항상 일정한 값 |
VARCHAR(n) |
가변 길이, 실제 길이만큼만 저장 |
이름, 이메일 등 길이가 다양한 문자열 |
TEXT |
최대 65,535 byte |
게시글 본문 등 긴 텍스트 |
LONGTEXT |
최대 4GB |
매우 큰 텍스트 |
팁: CHAR(10)은 항상 10바이트를 차지하지만 읽기 속도가 빠르다. VARCHAR(10)은 저장 공간을 아끼지만 길이 정보를 별도로 관리한다. 길이가 고정된 값이라면 CHAR가 유리하다.
날짜·시간형
| 타입 |
형식 |
범위 |
특징 |
DATE |
YYYY-MM-DD |
1000-01-01 ~ 9999-12-31 |
날짜만 저장 |
TIME |
HH:MM:SS |
|
시간만 저장 |
DATETIME |
YYYY-MM-DD HH:MM:SS |
1000-01-01 ~ 9999 |
시간대 변환 없음 |
TIMESTAMP |
YYYY-MM-DD HH:MM:SS |
1970 ~ 2038 |
UTC 저장, 조회 시 시간대 변환 |
주의: TIMESTAMP는 2038년 문제(Unix 32bit 오버플로)가 있다. 장기 보존 데이터는 DATETIME을 쓰되 애플리케이션 레벨에서 UTC 관리를 권장한다.
기타
| 타입 |
설명 |
BOOLEAN / BOOL |
MySQL에서는 내부적으로 TINYINT(1) |
JSON |
MySQL 5.7+, PostgreSQL 9.2+ 지원. JSON 형식 데이터 저장 및 경로 조회 가능 |
BLOB |
이진 데이터 (이미지·파일). 실무에서는 파일 자체는 S3 등 외부 저장소에 두고 DB에는 URL만 저장하는 방식을 선호 |
주의할 점
FLOAT/DOUBLE은 금액에 절대 사용하지 않는다. DECIMAL(10, 2) 같은 형식을 사용한다.
VARCHAR 크기는 여유 있게 설정하되 너무 크면 메모리 낭비가 생긴다. (MySQL VARCHAR(255)가 관행)
TIMESTAMP의 2038년 문제를 인지하고, 신규 개발에서는 DATETIME + 애플리케이션 UTC 관리를 권장한다.
TEXT/BLOB 컬럼은 인덱스를 전체 컬럼에 걸 수 없다. 필요하면 접두사 인덱스(INDEX (col(100)))를 사용한다.