본문으로 건너뛰기
피드

SQLite 쓸 거면 STRICT 테이블을 기본값으로 보자는 주장

backend 약 9분
vote
0
댓글
북마크

SQLite의 STRICT 테이블은 INTEGER 컬럼에 문자열이 들어가는 식의 타입 실수를 막아주는 기능이다. 글쓴이는 SQLite 특유의 유연한 타입 시스템보다, 실수는 빨리 터뜨리는 쪽이 실무에서 낫다고 주장한다. 다만 기존 테이블을 바로 STRICT로 바꾸기 어렵고, SQLite 3.37.0 이상에서만 쓸 수 있다는 제약도 있다.

  • 1

    STRICT 테이블은 INSERT와 UPDATE 시 컬럼 타입을 강하게 검사해 잘못된 타입 입력을 막는다.

  • 2

    허용되는 타입은 INT, INTEGER, REAL, TEXT, BLOB, ANY로 제한된다.

  • 3

    기존 테이블을 ALTER로 STRICT화하는 방법은 없고, 새 STRICT 테이블로 데이터를 복사해야 한다.

  • 4

    SQLite 3.37.0 이전 버전은 STRICT 테이블이 포함된 데이터베이스를 읽지 못한다.

  • 5

    성능 오버헤드는 이론상 있지만, 글쓴이의 간단한 대량 삽입 테스트에서는 뚜렷한 차이가 없었다.

SQLite의 느슨한 타입, 편하긴 한데 실수도 조용히 통과함

  • 글쓴이의 핵심 주장은 간단함. SQLite를 쓸 때는 가능하면 STRICT 테이블을 기본으로 쓰자는 것임

    • SQLite는 기본적으로 타입에 꽤 관대해서, INTEGER 컬럼에 텍스트를 넣는 식의 실수도 받아줄 수 있음
    • 글쓴이는 이걸 “편의”라기보다 “나중에 디버깅 지옥을 여는 구멍”에 가깝게 봄
  • STRICT 테이블을 만들려면 테이블 정의 끝에 STRICT만 붙이면 됨

    • 별도 확장이나 복잡한 설정이 아니라, CREATE TABLE ... STRICT 형태로 끝남
    • 이후 INSERT나 UPDATE에서 컬럼 타입이 맞지 않으면 SQLite가 에러를 냄
  • 다만 SQLite가 완전히 꽉 막힌 타입 검사를 하는 건 아님

    • 예를 들어 문자열 '123'은 손실 없이 정수로 바꿀 수 있으니 INTEGER 컬럼에 들어갈 수 있음
    • 핵심은 “명백히 잘못된 타입”을 조용히 저장하지 않게 만드는 쪽에 가까움

중요

> STRICT 테이블에서 허용되는 타입은 INT, INTEGER, REAL, TEXT, BLOB, ANY뿐임. 오타로 이상한 타입명을 써도 넘어가던 SQLite 기본 동작과는 꽤 다름.

테이블 만들 때부터 이상한 타입 선언을 막아줌

  • SQLite 기본 모드에서는 말도 안 되는 컬럼 타입 이름도 테이블 생성 시 통과될 수 있음

    • 글쓴이는 이런 케이스를 오타, SQLite 타입 시스템에 대한 오해, 혹은 그냥 심각한 실수로 봄
    • STRICT를 붙이면 이런 선언은 바로 에러가 나므로, 문제를 스키마 작성 단계에서 잡을 수 있음
  • STRICT 테이블에서는 컬럼 타입을 아예 생략하는 것도 안 됨

    • 예를 들어 CREATE TABLE tbl (name)처럼 타입 없는 컬럼을 만드는 방식은 허용되지 않음
    • 팀 프로젝트에서는 이런 제약이 오히려 문서화 효과를 냄. 스키마만 봐도 의도가 더 분명해지기 때문임
  • 그래도 완전한 경직성만 강요하는 건 아니고, ANY라는 탈출구가 있음

    • ANY 타입 컬럼은 STRICT 테이블 안에서도 어떤 값이든 받을 수 있음
    • 키-값 저장소나 여러 타입의 잡다한 속성을 담는 컬럼이라면 이쪽이 맞을 수 있음
    • 글쓴이는 본인은 아직 쓸 일이 없었다고 하지만, SQLite 개발진이 말하는 유연한 타입의 사용처와 맞닿아 있음

단점도 있음. 특히 기존 테이블 마이그레이션이 귀찮음

  • 이미 만들어진 일반 테이블을 ALTER TABLE로 바로 STRICT로 바꾸는 방법은 없어 보인다고 함

    • 현실적인 방법은 새 STRICT 테이블을 만들고, 기존 데이터를 복사하는 식의 마이그레이션임
    • 문제는 기존 데이터 안에 이미 잘못된 타입 값이 섞여 있으면 복사 과정에서 에러가 난다는 것
  • 그래서 기존 SQLite DB에 뒤늦게 도입할 때는 데이터 청소가 먼저 필요할 수 있음

    • 숫자 컬럼에 문자열이 들어가 있으면 변환하거나 제거해야 함
    • “새 테이블부터만 STRICT로 하자”는 규칙도 가능하지만, 테이블마다 검증 강도가 달라져서 오히려 헷갈릴 수 있음

💡

> 새 프로젝트라면 처음부터 STRICT를 켜는 쪽이 훨씬 깔끔함. 기존 DB에 도입할 때는 스키마 변경보다 데이터 정리가 더 큰 작업이 될 수 있음.

SQLite 개발진의 철학과는 살짝 결이 다름

  • 흥미로운 지점은 SQLite 개발진이 유연한 타입 시스템을 단순한 실수로 보지 않는다는 점임

    • SQLite 공식 문서에는 “유연한 타입의 장점”을 설명하는 페이지가 있음
    • 순수 키-값 저장소, 여러 타입의 속성 저장, 지저분한 CSV를 원본 손실 없이 가져오는 경우 같은 예시를 듦
  • 글쓴이는 이 철학을 이해하긴 하지만, 대부분의 경우에는 엄격한 타입이 낫다고 봄

    • 예상 못 한 데이터 타입 때문에 미묘한 버그를 겪은 경험이 많다고 함
    • 조용히 잘못 저장되는 것보다, 삽입 시점에 크게 터지는 편이 낫다는 입장임
  • 이건 정적 타입 대 동적 타입 논쟁과도 닮아 있음

    • 빠르게 아무거나 넣을 수 있는 유연함이 좋은 상황도 있음
    • 반대로 장기 유지보수나 팀 개발에서는 “안 되는 건 안 된다”고 DB가 말해주는 편이 더 싸게 먹힐 때가 많음

버전 호환성과 성능은 체크해야 함

  • STRICT 테이블은 SQLite 3.37.0부터 들어간 기능임

    • 해당 버전은 2021년 11월에 나왔음
    • 더 오래된 SQLite를 쓰는 환경이라면 이 기능 자체를 쓸 수 없음
  • 더 중요한 건 구버전 SQLite가 STRICT 테이블이 포함된 DB를 읽지 못한다는 점임

    • 최신 SQLite에서 STRICT 테이블을 만든 뒤, SQLite 3.36.0 같은 구버전으로 열면 에러가 남
    • 모바일 앱, 임베디드 환경, 오래된 런타임에 SQLite가 묶여 있는 경우에는 배포 대상 버전을 꼭 확인해야 함
  • 성능은 이론상 약간 느려질 수 있음

    • INSERT나 UPDATE 때 타입 검사를 추가로 해야 하기 때문임
    • 하지만 글쓴이가 100개 컬럼짜리 테이블에 수백만 행을 넣는 간단한 스크립트를 여러 머신에서 돌려봤을 때는 뚜렷한 차이가 없었다고 함
    • 디스크 파일 크기도 같았다고 함. 아주 엄밀한 벤치마크는 아니지만, 보통의 사용에서는 큰 부담으로 보기 어렵다는 쪽임
  • 결론은 꽤 실용적임. SQLite를 대충 쓰지 말고, 실수를 줄이는 기본값을 고르자는 이야기임

    • STRICT는 만능 해결책은 아니지만, 잘못된 타입 저장이라는 흔한 버그 클래스를 줄여줌
    • 새 테이블을 만들 때 붙이는 비용은 낮고, 나중에 데이터가 오염된 뒤 치르는 비용은 훨씬 큼

기술 맥락

  • SQLite는 원래 “값의 타입”을 더 중요하게 보는 쪽이라서, 다른 SQL 데이터베이스처럼 컬럼 타입을 강하게 강제하지 않아요. 이 설계는 작은 도구나 임시 데이터 저장에는 편한데, 앱이 커지면 잘못된 값이 조용히 누적될 수 있거든요.

  • STRICT 테이블은 이 지점을 스키마 레벨에서 바꾸는 선택이에요. 애플리케이션 코드에서 매번 검증하는 대신, DB가 INSERT와 UPDATE 시점에 타입을 확인하게 해서 실수를 더 이른 단계에서 잡자는 거예요.

  • 마이그레이션이 까다로운 이유도 여기 있어요. 기존 일반 테이블에는 이미 INTEGER 컬럼 안의 텍스트처럼 느슨한 데이터가 들어가 있을 수 있으니, 새 STRICT 테이블로 복사하는 순간 그동안 묵혀둔 문제가 한꺼번에 드러나요.

  • 그래서 팀에서 SQLite를 실서비스 저장소로 쓴다면, 새 스키마부터 STRICT를 기본값으로 둘지 정하는 게 중요해요. 나중에 바꾸려면 코드 수정만이 아니라 데이터 정리, 배포 대상 SQLite 버전 확인, 구버전 호환성까지 같이 봐야 하거든요.

SQLite를 ‘가벼운 장난감 DB’처럼 쓰는 시대는 지났고, 앱 내부 저장소부터 엣지 환경까지 꽤 진지한 곳에서 굴러간다. 그래서 타입 실수를 조용히 받아주는 기본 동작보다, STRICT로 초기에 터뜨리는 선택이 팀 단위 개발에서는 꽤 현실적인 방어선이 될 수 있다.

댓글

댓글

댓글을 불러오는 중...

backend

왜 아직도 Lisp를 배워볼 만한가

Lisp는 괄호가 많은 이상한 언어처럼 보이지만, 핵심은 문법이 아니라 언어 자체를 확장할 수 있다는 점에 있음. 매크로, 코드-데이터 동일성, REPL 중심 개발이 합쳐지면 프로그램을 '작성'한다기보다 살아 있는 시스템을 계속 진화시키는 방식으로 개발하게 됨.

backend

EDB 포스트그레스 AI, 포레스터 멀티모델 데이터 플랫폼 리더 선정

EDB의 AI 데이터 플랫폼 EDB 포스트그레스 AI가 2026년 2분기 포레스터 웨이브 멀티모델 데이터 플랫폼 보고서에서 리더로 선정됐음. 트랜잭션, 분석, AI 워크로드를 하나의 플랫폼에서 다루는 흐름이 강해지는 가운데, EDB는 전략과 현재 제공 기능 모두에서 높은 평가를 받았다고 밝힘.

backend

Bun, Zig에서 Rust로 갈아탔다: 11일짜리 초대형 런타임 포팅 실험

Bun 팀이 53만 줄이 넘는 Zig 코드베이스를 Rust로 기계적으로 포팅했고, Bun v1.4.0부터 Rust 기반으로 전환될 예정임. 핵심 이유는 성능보다 안정성이었고, use-after-free, double-free, 메모리 누수 같은 문제를 컴파일러와 타입 시스템으로 더 빨리 잡기 위해서였음. Claude Code 워크플로 64개를 병렬로 돌려 11일 만에 전 플랫폼 테스트 통과까지 밀어붙인 사례라, LLM 기반 대규모 코드 마이그레이션의 꽤 강한 신호탄임.

backend

시카고 미술관 API에 숨어 있는 ‘조회수 낮은 작품’ 필드

시카고 미술관 API에는 웹사이트에서 거의 조회되지 않은 작품을 표시하는 불리언 필드가 있다. 기준은 2010년 1월 1일 이후 조회수 200회 미만으로, API 설계 안에 꽤 인간적인 큐레이션 포인트가 숨어 있는 셈이다.

backend

유엔넷 DB 관리 솔루션, 오라클에서 PostgreSQL로 가는 일본 시장 노린다

유엔넷이 일본 PostgreSQL 기술지원 기업 뮤텍과 독점 공급 계약을 맺고 DB 성능 분석 솔루션 타란튜너를 일본에 공급해. 오라클에서 PostgreSQL로 전환하는 기업이 늘면서 SQL 지연, 잠금 경합, 실행 계획 비교 같은 운영 관리 수요를 겨냥한 움직임이야.