SQLite에서는 STRICT 테이블을 우선 사용하라
요약
SQLite의 STRICT 기능을 사용하면 데이터 무결성을 크게 높일 수 있습니다. 이 기능은 정수 열에 텍스트 같은 잘못된 타입이 삽입되는 것을 사전에 차단하여 안정적인 데이터 관리를 가능하게 합니다. 다만, 기존 테이블을 변경하려면 새 테이블 생성 및 데이터 복사가 필요하며, SQLite 3.37.0 이상 버전에서만 지원됩니다.
핵심 포인트
- STRICT 추가로 정수 열에 텍스트 삽입 등 타입 오류를 조기에 차단합니다.
- 데이터 무결성을 높이지만, 기존 테이블은 새 테이블 생성 및 데이터 복사가 필요합니다.
- 지원되는 열 타입이 제한적이며, 유연한 저장을 위해 ANY 타입을 사용할 수 있습니다.
- SQLite 3.37.0 이상 버전에서만 이 기능을 사용할 수 있습니다.
- 테이블 정의 끝에
STRICT
를 추가하면 정수 열에 임의의 텍스트가 들어가는 타입 오류를 조기에 차단해 데이터 무결성을 높일 수 있음
- 삽입·갱신 시 타입을 검사하면서도
'123'
처럼 손실 없이 변환 가능한 값은 허용하며, 열 타입은 INT
, INTEGER
, REAL
, TEXT
, BLOB
, ANY
로 제한됨
- 여러 타입을 담아야 하는 열에는
ANY
를 지정할 수 있어 엄격한 검증과 유연한 저장을 한 테이블 안에서 함께 적용 가능함
- 기존 테이블을 곧바로 STRICT로 바꿀 수는 없어
새 테이블 생성과 데이터 복사가 필요하며, 잘못된 기존 데이터는 정리하거나 형 변환해야 함 - STRICT 테이블은
SQLite 3.37.0 이상에서만 지원되며 이론적인 검사 비용은 있지만, 비공식 실험에서는 뚜렷한 성능·파일 크기 차이가 확인되지 않았음
STRICT 테이블 생성
- SQLite의 STRICT 테이블은 다른 SQL 엔진과 비슷하게 더 엄격한 타입 검사를 적용함
CREATE TABLE
정의 마지막에 STRICT
를 붙이면 됨
CREATE TABLE people (name TEXT) STRICT;
삽입과 갱신의 타입 검사
- 일반 SQLite 테이블은
INTEGER
열에도 'garbage'
같은 텍스트를 저장할 수 있지만, STRICT 테이블은 타입 불일치를 오류로 처리함
CREATE TABLE people_nonstrict (age INTEGER);
INSERT INTO people_nonstrict (age) VALUES ('garbage');
-- 정상 처리됨
CREATE TABLE people_strict (age INTEGER) STRICT;
INSERT INTO people_strict (age) VALUES ('garbage');
-- 오류: cannot store TEXT value in INTEGER column
- 같은 검증이
UPDATE
에도 적용돼 저장 후 값을 변경할 때도 잘못된 타입을 막음
- 단, 값이 손실 없이 변환될 수 있다면 STRICT 테이블에서도 허용됨
- 문자열
'123'
은 정수 123
으로 완전히 변환할 수 있어 아래 두 삽입이 동일하게 처리됨
INSERT INTO people_strict (age) VALUES ('123');
INSERT INTO people_strict (age) VALUES (123);
테이블 정의 단계의 타입 제한
- 일반 테이블에서는 SQLite가 지원하지 않는 타입 이름도 열 선언에 사용할 수 있음
GARBAGE
, DATETIME
, JSON
, UUID
, BLOBB
도 모두 받아들여짐
- 이런 선언은 오타이거나 SQLite가 지원하는 데이터 타입에 대한 오해에서 비롯될 수 있음
STRICT 테이블은 지원하지 않는 타입 이름을 사용하면 생성 단계에서 오류가 발생함
CREATE TABLE tbl (name GARBAGE) STRICT;
CREATE TABLE tbl (name DATETIME) STRICT;
CREATE TABLE tbl (name JSON) STRICT;
CREATE TABLE tbl (name UUID) STRICT;
CREATE TABLE tbl (name BLOBB) STRICT;
- 허용되는 열 타입은
INT
, INTEGER
, REAL
, TEXT
, BLOB
, ANY
뿐임
- 모든 열에 타입을 지정해야 하므로
CREATE TABLE tbl (name)
처럼 타입을 생략할 수 없음
ANY
로 유연성 유지
- 타입이 일정하지 않은 데이터를 저장해야 한다면
ANY
열을 사용할 수 있음
- STRICT 테이블 안에서도
ANY
열에는 정수, 텍스트, 실수, BLOB 등 모든 타입을 저장 가능함
CREATE TABLE tbl (value ANY) STRICT;
INSERT INTO tbl (value) VALUES (123);
INSERT INTO tbl (value) VALUES ('text');
INSERT INTO tbl (value) VALUES (12.34);
INSERT INTO tbl (value) VALUES (X'8647');
기존 테이블 마이그레이션
- 기존 비엄격 테이블을
ALTER
로 곧바로 STRICT 테이블로 바꾸는 방법은 없으므로 처음부터 엄격하게 생성하는 편이 간단함
- 기존 테이블을 전환하려면
새 STRICT 테이블 생성 → 데이터 복사 → 기존 테이블 교체 절차를 거쳐야 함
CREATE TABLE new_people (name TEXT) STRICT;
INSERT INTO new_people SELECT * FROM people;
DROP TABLE people;
ALTER TABLE new_people RENAME TO people;
- 기존 데이터의 정수 열에 텍스트가 들어 있는 등 타입이 잘못됐다면 복사 과정에서 오류가 날 수 있음
- 마이그레이션 전에 데이터를 정리하거나
CAST
로 형 변환해야 할 수 있음
- 새 테이블에만 STRICT를 적용하는 정책도 가능하지만, 테이블마다
검증 강도가 달라져 모든 테이블이 느슨한 경우보다 동작을 예측하기 어려울 수 있음
유연한 타입이 적합한 경우
-
SQLite 개발진은 유연한 타입의 장점을 별도로 정리하며 기본 동작이 유용한 사례를 제시함
-
비엄격 테이블이 합리적일 수 있는 용도는 다음과 같음
-
여러 타입을 그대로 담는
순수 키-값 저장소 -
타입이 서로 다른 기타 속성을 보관하는 공간
-
지저분한 CSV를 직접 가져오면서 유효하지 않은 값까지 잃지 않고 보존해야 하는 경우
-
그러나 예상하지 못한 타입은 미묘한 버그를 일으킬 수 있으므로, 일반적인 테이블에서는 조용히 허용하기보다 즉시 오류를 내는 편이 유리함
-
SQLite 소스에는 비엄격 테이블을
legacy
라고 부르는 주석도 있지만, 공식 문서보다 신뢰할 근거로 삼기는 어려움
버전 호환성
- STRICT 테이블은
2021년 11월 출시된 SQLite 3.37.0 에서 도입됨 - 이전 SQLite 버전에서는 STRICT 테이블을 사용할 수 없음
- 구버전은 STRICT 테이블이 포함된 데이터베이스도 읽지 못함
- 최신 SQLite에서 STRICT 테이블을 생성한 뒤 SQLite 3.36.0으로 같은 데이터베이스를 열면 오류가 발생함
성능과 저장 공간
- STRICT 테이블은 삽입·갱신 시 데이터 타입을 추가로 검사하므로 이론적으로는 더 느릴 수 있음
- 100개 열을 가진 테이블에 수백만 행을 삽입한 비공식 실험에서는 여러 컴퓨터 모두
뚜렷한 성능 차이가 나타나지 않았음 - 디스크의 데이터베이스 파일 크기도 같았지만, 철저한 벤치마크가 아니어서 발견하지 못한 차이가 있을 수 있음
- 열 선호도(column affinity)에 맞지 않는 값이 실수로 저장되는 일을 막아 오히려 성능이 나아질 가능성도 있으나, 별도로 검증되지는 않았음
적용 시 판단할 점
- STRICT 테이블이 모든 데이터 문제를 해결하지는 않지만, 타입 관련 실수를 줄이고
데이터 무결성을 강화함 - 대부분은 테이블 정의에
STRICT
만 추가하면 돼 적용이 간단함
- 일반적인 테이블에서는 엄격한 타입 검증으로 얻는 이점이 마이그레이션 부담, 구버전 비호환성, 제한된 유연성보다 큼
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기