MySQL은 ENUM 값을 내부적으로 정수 키(인덱스 번호)로 저장하여 각 ENUM 멤버를 참조합니다. 즉, ENUM으로 선언한 문자열 목록의 첫 번째 항목은 1, 두 번째 항목은 2처럼 내부적으로 번호가 매겨집니다.
ENUM 컬럼에 숫자를 저장하면 안 되는 이유
ENUM 컬럼에 정수 값을 직접 저장하지 말아야 하는 가장 큰 이유는, MySQL이 입력된 숫자를 값(value)이 아니라 인덱스(index)로 해석하기 때문입니다. 개발자가 특정 값을 저장하려는 의도였더라도 MySQL은 이를 멤버 목록의 위치 참조로 처리해 버리기 때문에, 의도와 전혀 다른 데이터가 저장될 수 있습니다.
예제
다음 예제를 통해 문제를 명확히 확인할 수 있습니다.
mysql> CREATE TABLE enmtest(Val ENUM('0','1','2'));
Query OK, 0 rows affected (0.18 sec)
mysql> INSERT INTO enmtest VALUES ('1'), (1);
Query OK, 2 rows affected (0.19 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM enmtest;
+-----+
| Val |
+-----+
| 1 |
| 0 |
+-----+
2 rows in set (0.00 sec)위 예제에서 첫 번째 삽입은 '1'을 문자열로 넣었고, 두 번째 삽입은 실수로 따옴표 없이 숫자 1을 넣었습니다. 그 결과 MySQL은 숫자 1을 값이 아닌 인덱스 값, 즉 멤버 목록의 첫 번째 항목인 '0'에 대한 내부 참조로 해석했습니다. 그래서 조회 결과에 '0'이 저장되어 있는 것을 볼 수 있습니다.
주의해야 할 점
이러한 동작 방식 때문에 다음과 같은 문제가 발생할 수 있습니다.
- 문자열 '1'과 숫자 1이 서로 다른 결과를 만들어 데이터 불일치가 발생합니다.
- 나중에 ENUM 목록의 순서를 변경하면 기존에 저장된 인덱스 기반 데이터의 의미가 완전히 달라집니다.
- 디버깅 시 실제 저장된 값과 화면에 표시되는 값이 달라 혼란을 초래합니다.
따라서 ENUM 컬럼에는 반드시 정의된 문자열 값을 명시적으로(따옴표를 붙여) 저장해야 하며, 숫자 자체를 데이터로 다루어야 하는 경우라면 ENUM 대신 INT, TINYINT 같은 숫자 타입 컬럼을 사용하는 것이 훨씬 안전합니다.