테이블을 만들 때 컬럼마다 타입을 지정해야 한다는 건 DDL에서 봤다. 그런데 막상 INT랑 BIGINT가 뭐가 다른지, VARCHAR랑 TEXT는 언제 구분해서 쓰는지 헷갈리기 시작한다. 이번 글에서 자주 쓰는 타입들을 정리한다.
| 타입 | 크기 | 범위 |
|---|---|---|
TINYINT | 1바이트 | -128 ~ 127 |
SMALLINT | 2바이트 | -32,768 ~ 32,767 |
INT | 4바이트 | 약 -21억 ~ 21억 |
BIGINT | 8바이트 | 매우 큰 정수 |
대부분은 INT로 충분하다. 사용자 ID, 주문 수량, 가격처럼 일반적인 정수값은 INT가 기본이다.
BIGINT는 값이 21억을 넘어갈 가능성이 있을 때 쓴다. 타임스탬프를 밀리초 단위로 저장하거나, 트래픽이 매우 많은 서비스의 PK처럼 숫자가 크게 불어날 수 있는 경우다.
UNSIGNED를 붙이면 음수를 포기하고 양수 범위를 두 배로 늘릴 수 있다.
-- UNSIGNED를 붙이면 0 ~ 42억까지 저장 가능
member_id INT UNSIGNED
| 타입 | 설명 |
|---|---|
FLOAT | 4바이트 부동소수점, 근사값 |
DOUBLE | 8바이트 부동소수점, 근사값 |
DECIMAL(p, s) | 정확한 소수, p는 전체 자릿수, s는 소수점 이하 자릿수 |
FLOAT과 DOUBLE은 근사값이라 미세한 오차가 생길 수 있다. 돈처럼 정확해야 하는 값은 반드시 DECIMAL을 써야 한다.
-- 전체 10자리, 소수점 이하 2자리 (예: 99999999.99)
price DECIMAL(10, 2)
| 타입 | 설명 |
|---|---|
CHAR(n) | 고정 길이. 항상 n바이트를 차지한다 |
VARCHAR(n) | 가변 길이. 실제 저장된 문자열 길이만큼만 차지한다 |
CHAR(10)에 'abc'를 넣으면 나머지 7칸을 공백으로 채워서 항상 10바이트를 쓴다. VARCHAR(10)에 'abc'를 넣으면 3바이트만 쓴다.
길이가 항상 일정한 값(주민등록번호 형식, 국가 코드 등)은 CHAR, 길이가 들쑥날쑥한 이름이나 이메일 같은 값은 VARCHAR가 적합하다.
country_code CHAR(2), -- 'KR', 'US', 'JP' 처럼 항상 2자리
member_name VARCHAR(50), -- 이름은 길이가 다 다르니까
email VARCHAR(100)
긴 문자열을 저장할 때 쓴다. VARCHAR는 최대 65,535바이트까지지만, 실제로 긴 본문을 저장할 때는 TEXT가 더 적합하다.
| 타입 | 최대 크기 |
|---|---|
TEXT | 65,535바이트 (~64KB) |
MEDIUMTEXT | 16MB |
LONGTEXT | 4GB |
게시글 본문, 상품 상세 설명처럼 길이 제한이 없는 텍스트는 TEXT를 쓴다.
| 타입 | 형식 | 설명 |
|---|---|---|
DATE | YYYY-MM-DD | 날짜만 |
TIME | HH:MM:SS | 시간만 |
DATETIME | YYYY-MM-DD HH:MM:SS | 날짜 + 시간 |
TIMESTAMP | YYYY-MM-DD HH:MM:SS | 날짜 + 시간, UTC 기준 저장 |
DATETIME과 TIMESTAMP는 비슷해 보이지만 차이가 있다. DATETIME은 입력한 값을 그대로 저장하고, TIMESTAMP는 내부적으로 UTC로 변환해서 저장한다. 조회할 때는 서버의 타임존에 맞게 다시 변환해서 보여준다.
한국 서버에서만 쓴다면 큰 차이가 없지만, 여러 시간대를 고려해야 하는 서비스라면 TIMESTAMP가 더 안전하다.
created_at DATETIME, -- 가입일시
updated_at TIMESTAMP -- 수정일시 (자동으로 현재 시각 저장 가능)
TIMESTAMP는 DEFAULT CURRENT_TIMESTAMP와 함께 쓰면 행이 삽입될 때 자동으로 현재 시각이 들어간다.
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
TRUE / FALSE를 저장한다. MySQL에서는 내부적으로 TINYINT(1)로 처리된다. TRUE는 1, FALSE는 0으로 저장된다.
is_active BOOLEAN DEFAULT TRUE
미리 정해둔 값 중 하나만 들어올 수 있는 타입이다.
-- 'pending', 'paid', 'cancelled' 중 하나만 저장 가능
status ENUM('pending', 'paid', 'cancelled')
정해진 상태값을 관리할 때 유용하다. 그 외의 값을 넣으려 하면 오류가 난다.
| 종류 | 주요 타입 | 언제 쓰나 |
|---|---|---|
| 정수 | INT, BIGINT | ID, 수량, 일반 정수 |
| 소수 | DECIMAL | 가격, 정확한 소수 |
| 문자열 | VARCHAR, TEXT | 이름/이메일, 긴 본문 |
| 날짜 | DATE, DATETIME, TIMESTAMP | 날짜, 날짜+시간 |
| 기타 | BOOLEAN, ENUM | 참/거짓, 고정 상태값 |
타입을 고를 때 기준은 단순하다. 저장할 값의 종류가 뭔지, 얼마나 큰 값이 들어올 수 있는지, 정확도가 중요한지를 따지면 대부분 자연스럽게 결정된다.