MariaDB 강좌 / 문자열 타입 선택하기: CHAR·VARCHAR·TEXT
CHAR는 정해진 길이의 코드, VARCHAR는 길이가 달라지는 이름·제목, TEXT는 긴 설명문을 저장할 때 검토하는 문자열 타입입니다. 괄호 안 길이와 실제 저장 바이트 수는 다르며, 문자 집합·끝 공백·정렬 규칙까지 함께 확인해야 올바르게 사용할 수 있습니다.
CHAR·VARCHAR·TEXT의 선택 기준
| 타입 | 선택할 상황 | 주의할 점 |
|---|---|---|
| CHAR(M) | 길이가 일정한 상태 코드·규격 코드 | 짧은 값은 공백으로 채우며 일반 조회에서 끝 공백이 제거됨 |
| VARCHAR(M) | 이름·제목·전자우편 등 길이가 달라지는 값 | M은 최대 문자 수이며 전체 행 크기와 문자 집합의 제한도 받음 |
| TEXT | 긴 상품 설명·본문·메모 | 기본 TEXT 용량은 바이트 기준이며 인덱스·조회 방식도 검토 |
길이가 고정된 값이라고 해서 항상 CHAR가 가장 빠른 것은 아닙니다. 저장 엔진, 문자 집합, 실제 길이와 조회 방식에 따라 결과가 달라집니다. 우선 값의 의미와 입력 정책을 정하고, 성능이 문제가 되는 실제 쿼리에서 비교하세요. VARCHAR(100)은 모든 입력이 정확히 백 글자가 되어야 한다는 조건이 아닙니다.
TEXT에는 별도의 M 길이를 쓰지 않습니다. 기본 TEXT는 최대 65,535바이트를 저장할 수 있으며, 더 긴 값에는 MEDIUMTEXT·LONGTEXT 같은 다른 타입을 검토합니다. 한글과 이모지에서는 글자 수와 바이트 수가 다르므로 65,535글자까지 보관할 수 있다고 해석하면 안 됩니다. TEXT 용량과 처리 조건을 참고하세요.
문자 집합과 문자 수·바이트 수 구분하기
문자 집합(character set)은 문자를 어떤 바이트로 표현할지 정합니다. utf8mb4는 한글과 이모지를 포함한 유니코드 문자를 저장하는 데 사용합니다. 문자열 저장에는 테이블 정의뿐 아니라 접속한 클라이언트의 문자 집합도 영향을 주므로, 4강의 utf8mb4 접속 명령을 이어서 사용합니다.
정렬 규칙(collation)은 문자 비교와 정렬 기준입니다. 같은 문자 집합을 써도 대소문자와 공백 비교 규칙이 달라질 수 있습니다. 여기서는 기존 강좌와 동일한 utf8mb4_unicode_ci를 명시하고, 문자열 자체의 저장과 비교 결과를 구분해서 관찰합니다.
SELECT CHAR_LENGTH('가나다라') AS characters,
LENGTH('가나다라') AS bytes;
utf8mb4 연결에서 위 결과는 문자 수 4, 바이트 수 12입니다. CHAR_LENGTH는 데이터베이스가 처리하는 문자 수이며, 복합 이모지처럼 화면에서 하나로 보이는 모든 글리프의 개수를 세는 함수라고 단정하지 않습니다. 사용자 화면의 글자 제한은 프로그램 쪽의 유니코드 처리 정책도 함께 정해야 합니다.
고정 길이와 가변 길이를 같은 입력으로 비교하기
2~5강에서 준비한 course_user로 shopcourse 데이터베이스에 접속한 상태에서 실행합니다. 접속·SQL 파일 실행 방법은 명령줄 클라이언트 설명을 참고하세요. 서버 버전과 선택한 데이터베이스를 먼저 확인하고, 운영 데이터가 들어 있는 연결에서는 이 실습을 실행하지 않습니다.
SELECT VERSION() AS server_version, DATABASE() AS selected_database; USE shopcourse; SELECT DATABASE() AS selected_database;
기존 상품 테이블과 별개인 string_lab을 만듭니다. PAD_CHAR_TO_FULL_LENGTH 같은 다른 모드의 영향을 배제하고 길이 초과를 오류로 확인하기 위해 이번 연결의 SQL 모드를 STRICT_TRANS_TABLES로 정합니다. 실행 전 값을 변수에 보관해 마지막에 복원합니다.
USE shopcourse;
SET @saved_sql_mode = @@SESSION.sql_mode;
SET SESSION sql_mode = 'STRICT_TRANS_TABLES';
CREATE TABLE string_lab (
item_id INT PRIMARY KEY,
fixed_code CHAR(4) NOT NULL,
title VARCHAR(4) NOT NULL,
description TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO string_lab VALUES
(1, 'AB ', 'AB ', '상품 설명'),
(2, 'CD', '가🙂', NULL);
SELECT item_id, CONCAT('[', fixed_code, ']') AS fixed_display,
CHAR_LENGTH(fixed_code) AS fixed_chars,
CONCAT('[', title, ']') AS title_display,
CHAR_LENGTH(title) AS title_chars, LENGTH(title) AS title_bytes
FROM string_lab ORDER BY item_id;
SELECT CHAR_LENGTH('가나다라') AS characters,
LENGTH('가나다라') AS bytes;
| 행 | fixed_display / fixed_chars | title_display / title_chars / title_bytes |
|---|---|---|
| 1 | [AB] / 2 | [AB ] / 4 / 4 |
| 2 | [CD] / 2 | [가🙂] / 2 / 7 |
대괄호는 CONCAT 함수로 값을 둘러싸 공백이 어디까지 남아 있는지 보여 줍니다. CHAR(4)의 AB 뒤 공백은 이 모드의 조회에서 제거되지만 VARCHAR(4) 값의 끝 공백은 저장·조회에 남습니다. 이 차이는 CHAR의 끝 공백 처리와 VARCHAR의 길이와 공백 규칙에서 확인할 수 있습니다.
LENGTH가 7인 이모지 포함 문자열도 CHAR_LENGTH가 2이므로 VARCHAR(4)에 들어갑니다. 바이트 수를 근거로 두 글자 문자열이 VARCHAR(4)에 들어갈 수 없다고 판단하면 잘못된 제한이 됩니다.
길이 초과는 잘라 넣기보다 입력 규칙을 확인하기
같은 연결에서 아래 문장을 따로 실행합니다. title은 최대 네 문자인데 다섯 문자를 넣으므로 strict 모드에서는 Data too long 오류가 예상됩니다. 이후 SELECT COUNT(*) FROM string_lab;를 실행하면 정상 행 두 개가 유지되어야 합니다.
INSERT INTO string_lab VALUES (3, 'EF', '가나다라마', NULL);
입력을 임의로 자르면 이름과 코드의 의미가 달라질 수 있습니다. 먼저 허용할 길이를 바꿀지, 입력을 거절할지 업무 규칙으로 결정하세요. strict 모드를 끄면 경고와 잘림으로 바뀔 수 있고, 초과한 부분이 공백인 경우에는 처리 조건이 다를 수 있으므로 모든 길이 초과가 똑같이 오류를 낸다고 일반화하지 않습니다.
애플리케이션에서 길이를 검사해도 데이터베이스의 타입 제한은 함께 필요합니다. 반대로 데이터베이스 제한만으로 사용자에게 친절한 오류 설명이 자동으로 생기지는 않으므로 화면 검증과 저장 검증을 나누어 설계합니다.
긴 본문과 식별용 코드를 같은 방식으로 다루지 않기
상품 설명처럼 길이가 크게 달라지는 본문은 TEXT가 적합할 수 있지만, 짧은 코드나 검색 조건 열을 모두 TEXT로 바꾸는 방식은 피합니다. 어떤 열을 실제 조회·정렬·중복 검사에 사용하는지 함께 보세요. 인덱스의 길이 제한과 접두어 인덱스의 적용 범위는 문자 집합과 저장 엔진에 따라 달라집니다.
이 예제의 VARCHAR는 끝 공백을 저장하지만 utf8mb4_unicode_ci 비교에서는 공백이나 대소문자를 같게 판단하는 경우가 있습니다. 저장 문자열이 다르다는 사실만으로 UNIQUE 검사가 통과한다고 가정하지 않습니다. 코드나 이메일의 정규화와 대소문자 정책을 먼저 정해야 중복 검사가 일관됩니다.
사진·압축 파일 같은 바이트 데이터는 문자열 본문과 다른 요구 사항입니다. TEXT를 모든 파일 형식의 저장소로 사용하지 말고 바이너리 타입이나 파일 저장 방식을 따로 검토합니다. 이 강좌의 예제는 사람이 읽는 문자 데이터에 한정합니다.
결과를 확인하고 반복 실습하기
- 문자 수와 바이트 수를 같은 것으로 해석하지 않았는지 확인합니다.
- CHAR 조회에서 끝 공백이 달라지는지 관찰합니다.
- 문자 집합과 정렬 규칙을 SHOW CREATE TABLE string_lab로 확인합니다.
- NULL인 설명문과 빈 문자열을 입력한 경우를 구분합니다. 관련 조건은 NULL·기본값·입력 제약에서 구체적으로 설명합니다.
같은 연결에서 아래로 SQL 모드를 복원합니다. 새 연결에서는 저장 변수가 없어졌으므로 실행하지 말고 현재 모드를 조회합니다.
SET SESSION sql_mode = @saved_sql_mode;
반복 실습 전에는 SELECT DATABASE();와 SHOW CREATE TABLE 테이블명;으로 대상이 이 강좌에서 만든 실습 테이블인지 확인합니다. 보관할 데이터가 있다면 먼저 백업합니다. 아래 명령은 지정한 테이블과 그 안의 데이터를 삭제하므로 확인한 학습용 테이블에만 실행하세요.
DROP TABLE shopcourse.string_lab;
삭제 후에는 본문의 전체 예제를 다시 실행할 수 있습니다. DROP TABLE 같은 데이터 정의 문장은 일반적인 트랜잭션의 ROLLBACK으로 복구할 수 있다고 기대하지 않습니다. 기존 products 테이블은 이 초기화 대상에 포함하지 않습니다.








