데이터 타입 표준 (숫자·문자열·불리언) — 언제 어떤 타입을 써야 하는가

INTEGER·DECIMAL·FLOAT의 차이, CHAR·VARCHAR·TEXT의 선택 기준, 불리언 타입의 DBMS별 차이를 정리합니다. 부동소수점 오차 함정과 VARCHAR 길이 설계 가이드도 다룹니다.

· 8 min read · PALDYN Team

타입 선택이 중요한 이유

CREATE TABLE에서 컬럼 타입을 잘못 잡으면 나중에 ALTER TABLE로 바꿔야 한다. 운영 DB에서 타입 변경은 테이블 잠금이나 풀 리빌드를 동반하는 경우가 많다. 처음 설계할 때 한 번만 제대로 하면 평생 편하다.

SQL 표준이 정의한 타입은 크게 세 범주다.

  • 숫자: 정수, 고정소수점, 부동소수점
  • 문자열: 고정 길이, 가변 길이, 대형 텍스트
  • 불리언: 참/거짓

숫자 타입

숫자 데이터 타입

정수 (Integer Family)

타입크기범위
SMALLINT2바이트-32,768 ~ 32,767
INTEGER4바이트±2,147,483,647 (약 ±21억)
BIGINT8바이트±9,223,372,036,854,775,807

대부분의 경우 INTEGER로 충분하다. 사용자 ID처럼 수십억 개를 넘을 수 있는 식별자는 BIGINT를 쓴다. SMALLINT는 상태 코드처럼 값 범위가 매우 좁은 컬럼에 사용하면 공간을 절약할 수 있지만, 실무에서는 그냥 INTEGER를 쓰는 경우도 많다.

고정소수점 (DECIMAL / NUMERIC)

-- p: 전체 유효 자릿수 (precision), s: 소수점 이하 자릿수 (scale)
amount   DECIMAL(12, 2)  -- 최대 9,999,999,999.99
tax_rate NUMERIC(5, 4)   -- 최대 9.9999 (0~1 사이 비율)

DECIMALNUMERIC은 SQL 표준상 동의어이며, 실제 저장 방식도 동일하다. 금액, 세율, 환율, 할인율처럼 오차 없는 정확한 계산이 필요한 모든 곳에 사용한다.

정밀도 규칙:

  • DECIMAL(10, 2) → 정수부 8자리 + 소수부 2자리
  • DECIMAL(5, 5) → 0.XXXXX 형태만 가능 (0 이상 1 미만)
  • scale이 precision보다 클 수 없다

부동소수점 (REAL / DOUBLE PRECISION / FLOAT)

latitude   DOUBLE PRECISION  -- GPS 위도
longitude  DOUBLE PRECISION  -- GPS 경도
score      REAL              -- 분류 확률

IEEE 754 표준에 따라 2진수로 근사 저장하기 때문에 정확한 값을 보장하지 않는다.

-- 부동소수점 오차 예시 (대부분의 언어·DB에서 재현)
SELECT 0.1 + 0.2;
-- 결과: 0.30000000000000004 (또는 유사한 근사값)

이 오차는 DBMS 버그가 아니라 IEEE 754의 본질적 특성이다. 금융 계산에 부동소수점을 쓰면 합산 오차가 누적되어 결국 장부가 맞지 않는다. 금액·이자·환율에는 반드시 DECIMAL/NUMERIC을 사용한다.

부동소수점이 적합한 경우:

  • 과학 계산, 통계, 머신러닝 특성값
  • GPS 좌표처럼 정밀도보다 범위가 중요한 값
  • 성능이 중요하고 약간의 오차가 허용되는 집계

문자열 타입

문자열과 불리언 타입

CHAR(n) — 고정 길이

country_code CHAR(2)   -- 'KR', 'US'
gender_code  CHAR(1)   -- 'M', 'F'

항상 n바이트를 사용한다. 'KR'CHAR(5)에 저장하면 'KR '처럼 뒤에 공백이 패딩된다. 비교 시 후행 공백을 무시하는 DBMS가 많지만 일관성을 위해 항상 정해진 길이의 값만 넣는 컬럼에 사용하는 것이 좋다.

VARCHAR(n) — 가변 길이

name   VARCHAR(100)  NOT NULL
email  VARCHAR(254)  UNIQUE
url    VARCHAR(2048)

실제 데이터 길이만큼만 저장한다. n은 최대 허용 바이트/문자 수이며, 초과 시 오류가 발생한다. 가장 범용적인 문자열 타입이다.

VARCHAR 길이 설계 가이드:

용도권장 길이근거
이메일254RFC 5321 최대값
URL2048실용적 상한
사람 이름100충분한 여유
주소 한 줄255일반적 관례
UUID 문자열36형식 고정

VARCHAR는 실제 저장 크기만큼만 공간을 쓰므로 길이를 넉넉하게 잡아도 낭비가 없다. 너무 짧게 잡으면 나중에 ALTER TABLE을 해야 한다.

TEXT — 길이 제한 없음

body    TEXT  -- 게시글 본문
log_msg TEXT  -- 로그 메시지

SQL 표준에는 없고 DBMS 확장 타입이다. PostgreSQL에서는 길이 제한 없이 저장하고, MySQL에서는 65,535바이트까지 허용한다(더 긴 경우 MEDIUMTEXT, LONGTEXT 사용).

주의할 점은 TEXT 컬럼에는 인덱스를 일반 방식으로 생성할 수 없거나(또는 접두사 인덱스가 필요하다). 자주 검색 조건으로 쓰이는 컬럼이라면 VARCHAR(n)을 사용하는 것이 낫다.


불리언 타입

is_active  BOOLEAN  DEFAULT TRUE
is_deleted BOOLEAN  DEFAULT FALSE
has_paid   BOOLEAN

SQL의 불리언은 TRUE, FALSE, NULL 세 가지 값을 가진다. NULL은 “알 수 없음(UNKNOWN)“을 의미하며 참도 거짓도 아니다.

-- NULL 조건은 IS NULL / IS NOT NULL로 검사
SELECT * FROM accounts WHERE is_active;             -- TRUE인 행만
SELECT * FROM accounts WHERE is_active IS NULL;     -- 값이 없는 행
SELECT * FROM accounts WHERE NOT is_active;         -- FALSE인 행만

-- 주의: NULL = FALSE가 아님
SELECT * FROM accounts WHERE is_active = FALSE;     -- NULL 행은 포함되지 않음

DBMS별 차이

DBMSBOOLEAN 지원내부 구현
PostgreSQL네이티브 지원1바이트
MySQL 8+BOOLEAN 키워드TINYINT(1) 별칭 (0/1)
Oracle 21c 이전미지원NUMBER(1) 관례 사용
Oracle 23c+네이티브 지원
SQL Server미지원BIT (0/1) 사용

MySQL에서 BOOLEAN으로 정의한 컬럼은 실제로 TINYINT(1)로 저장된다. TRUE는 1, FALSE는 0이다. 따라서 WHERE is_active = 1도 작동하지만, 가독성을 위해 WHERE is_active = TRUEWHERE is_active를 쓰는 것이 좋다.


DBMS별 타입 이름 비교

표준PostgreSQLMySQLOracle
INTEGERINT4 / INTEGERINTNUMBER(10)
BIGINTINT8 / BIGINTBIGINTNUMBER(19)
DECIMAL(p,s)동일동일NUMBER(p,s)
DOUBLE PRECISIONFLOAT8 / 동일DOUBLEBINARY_DOUBLE
VARCHAR(n)동일동일VARCHAR2(n)
BOOLEAN동일TINYINT(1)NUMBER(1) / 23c+

정리

  • 금액, 세율, 환율에는 DECIMAL(p, s) 또는 NUMERIC(p, s).
  • 부동소수점(FLOAT, REAL, DOUBLE)은 오차가 있다. 과학·좌표 등에만 사용.
  • 문자열은 고정 길이면 CHAR, 가변이면 VARCHAR, 긴 본문이면 TEXT.
  • VARCHAR 길이는 넉넉히 잡자 — 낭비 없이 크게 설계하는 것이 낫다.
  • 불리언은 SQL 3값 논리(TRUE, FALSE, NULL)임을 기억하자.
  • DBMS마다 타입 이름이 다르지만 표준 타입을 쓰면 이식성이 높아진다.

지난 글: CREATE TABLE 기초 — 테이블을 제대로 정의하는 방법

다음 글: 데이터 타입 표준 (날짜·시간) — DATE·TIME·TIMESTAMP와 타임존 함정


읽어주셔서 감사합니다. 😊