[Drizzle ORM] MariaDB schema.ts 생성 실패(Silent Fail) 원인 및 해결
[Drizzle ORM] MariaDB 연동 시 schema.ts 생성 실패(Silent Fail) 원인 및 완벽 해결 가이드
최근 웹 개발 트렌드에서 서버리스(Serverless)와 엣지 컴퓨팅(Edge Computing)의 결합은 피할 수 없는 대세가 되었습니다. 특히 초경량 웹 프레임워크인 Hono와 Cloudflare Workers, 그리고 타입 안정성을 극대화해 주는 Drizzle ORM의 조합은 압도적인 퍼포먼스와 개발 경험을 제공합니다. 하지만 완벽해 보이는 이 스택에도 실제 인프라 환경과 맞물릴 때 예상치 못한 치명적인 함정이 존재합니다.
혹시 완벽한 연결 설정을 마쳤음에도 npx drizzle-kit pull (또는 introspect) 명령어가 schema.ts 파일을 뱉어내지 않고 조용히 종료되는 이른바 '침묵의 실패(Silent Fail)' 현상을 겪고 계신가요? 에러 로그조차 남지 않아 네트워크 드라이브 권한부터 OS 설정까지 뒤지며 귀중한 시간을 허비하고 계실 분들을 위해, 결론부터 가볍게 말씀드리겠습니다. 여러분의 설정이나 OS 환경의 문제가 아닙니다. 범인은 바로 MariaDB의 'JSON 데이터 타입'이며, 해당 컬럼을 일시적으로 LONGTEXT로 변경하는 것만으로 이 지독한 버그를 즉시 해결할 수 있습니다.
지금부터 수많은 개발자를 절망에 빠뜨렸던 이 버그의 정확한 원인과, 아키텍처 수준에서의 기술적 분석, 그리고 가장 우아하고 확실한 해결책을 상세히 파헤쳐 보겠습니다.
1. 완벽한 거짓말: 침묵의 실패(Silent Fail) 현상
Drizzle ORM을 도입하여 기존 데이터베이스의 스키마를 코드로 추출(Reverse Engineering)하려 할 때, 우리는 보통 다음과 같은 터미널 로그를 마주하게 됩니다.
Bash
[✓] 8 tables fetched [✓] 58 columns fetched [✓] 4 indexes fetched [⢿] 1 check constraints fetching [✓] 0 views fetched
로그상으로는 분명 Contabo와 같은 원격 VPS 서버에 구축된 MariaDB에 성공적으로 접근하여 테이블과 컬럼 정보를 100% 읽어온 것처럼 보입니다. 하지만 추출 작업의 마지막 단계인 '파일 생성(File Writing)' 단계로 넘어가지 못한 채 프롬프트가 조용히 종료됩니다. verbose 옵션이나 디버그 모드를 켜도 예외(Exception)를 던지지 않기 때문에, 많은 개발자들이 이를 프로젝트 폴더 내 .prettierrc 충돌이나 윈도우 환경의 물리 드라이브(Z: 등) 쓰기 권한 문제로 오인하곤 합니다 [출처: Drizzle ORM 커뮤니티 트러블슈팅 사례 분석].
2. 기술적 원인 규명: MariaDB와 Drizzle AST 엔진의 치명적 불협화음
이 문제의 근본적인 원인을 이해하기 위해서는 MariaDB가 내부적으로 데이터를 처리하는 방식과 Drizzle Kit의 코드 생성기(AST Generator)가 메타데이터를 파싱하는 로직을 동시에 이해해야 합니다.
첫째, MariaDB의 JSON 타입은 독립된 타입이 아닙니다. 순수 MySQL과 달리, MariaDB에서 JSON 데이터 타입은 사실 LONGTEXT 데이터 타입에 CHECK (json_valid(column_name))이라는 제약조건(Check Constraint)이 자동으로 은닉되어 붙어있는 일종의 별칭(Alias)이자 매크로입니다 [출처: MariaDB Official Documentation - JSON Data Type]. 즉, 개발자가 단순히 JSON 컬럼을 생성하더라도, DB 엔진 내부적으로는 데이터의 무결성을 검증하기 위한 CHECK 제약조건이 강제로 생성되는 것입니다.
둘째, Drizzle Kit의 파싱 엔진 결함입니다. Drizzle Kit(v0.31.x 기준)이 기존 DB 구조를 읽어올 때, MariaDB의 information_schema.check_constraints 시스템 테이블에 접근하여 제약조건을 가져옵니다. 이때 MariaDB는 컬럼명과 결과값을 반환하는데, 내부적으로 자동 생성된 JSON 검증용 제약조건이나 복잡한 표현식(Expression)을 만났을 때 Drizzle의 파서가 해당 문법을 TypeScript 코드로 번역하지 못하고 뇌 정지(Hang) 상태에 빠지게 됩니다 [출처: Drizzle ORM GitHub Issue Tracker - Introspection Silent Failure]. 최악의 문제는 이 과정에서 예외 처리가 제대로 되어 있지 않아 프로세스가 시스템 에러 없이 강제 종료(Exit 0) 처리된다는 점입니다.
💡 실제 프로젝트 사례: tb_finance_chart 테이블의 비극
실제 금융 데이터나 API 응답 로그를 수집하는 시스템을 설계할 때, 응답 데이터를 통째로 저장하기 위해 JSON 타입을 빈번하게 사용합니다. 예를 들어 tb_finance_chart라는 테이블에 API 응답 결과를 담는 chart_data 컬럼을 JSON 타입으로 지정했다고 가정해 보겠습니다. Drizzle Kit은 이 8개의 테이블 중 단 하나의 테이블에라도 숨겨진 CHECK 제약조건(JSON 타입)이 존재한다면, tablesFilter 옵션으로 해당 테이블을 제외하려 시도하더라도 전체 프로세스를 중단시켜 버립니다. 결국 개발자는 원인도 모른 채 전체 스키마 생성을 포기하게 되는 상황에 이릅니다.
3. 해결책: '눈속임'을 통한 스키마 추출 전략
문제의 원인이 파악되었다면 해결은 명쾌합니다. Drizzle Kit의 파서가 해석하지 못하는 MariaDB의 '숨겨진 CHECK 제약조건'을 추출 순간에만 일시적으로 제거해 주는 것입니다. 이를 가장 안전하게 수행하는 방법은 문제가 되는 JSON 컬럼을 잠시 LONGTEXT로 속이는 것입니다.
아래에 제시된 3단계의 SQL 쿼리 및 터미널 명령어 프로세스를 순서대로 진행하시기 바랍니다.
Step 1. 범인 색출 (JSON 컬럼 확인)
먼저 현재 사용 중인 데이터베이스 내에 JSON 타입으로 선언된 컬럼이 정확히 어디에 존재하는지 파악해야 합니다. DB 관리 툴(DBeaver, DataGrip 등)에서 아래 쿼리를 실행합니다.
SQL
SELECT
TABLE_NAME,
COLUMN_NAME
FROM
information_schema.COLUMNS
WHERE
TABLE_SCHEMA = '본인의_데이터베이스명'
AND DATA_TYPE = 'json';
Step 2. 타입 임시 변경 및 제약조건 해제
위 쿼리를 통해 JSON 타입이 적용된 테이블과 컬럼(예: tb_finance_chart의 chart_data 컬럼)을 확인했다면, 이를 일시적으로 LONGTEXT로 변경합니다. 이 작업을 수행하면 MariaDB 내부의 CHECK (json_valid()) 제약조건이 해제됩니다. (기존 데이터가 삭제되거나 손상되지 않으니 안심하셔도 됩니다.)
SQL
-- Drizzle Kit이 멈추지 않도록 타입을 LONGTEXT로 일시 변경 ALTER TABLE tb_finance_chart MODIFY chart_data LONGTEXT;
Step 3. Drizzle Schema 추출 및 원상 복구
이제 장애물이 모두 제거되었습니다. 터미널로 돌아가 스키마 추출 명령어를 실행합니다.
Bash
npx drizzle-kit pull
명령어를 실행하자마자 지긋지긋했던 침묵을 깨고 프로젝트 폴더 내에 schema.ts 파일이 완벽하게 생성되는 것을 확인할 수 있습니다. 성공적으로 파일을 얻어냈다면, 생성된 TypeScript 코드 내에서 해당 컬럼을 .json() 타입으로 수동 보정해 주고, DB의 데이터 타입 역시 원래의 JSON으로 복구해 줍니다.
SQL
-- 추출 완료 후 DB 구조 원상 복구 ALTER TABLE tb_finance_chart MODIFY chart_data JSON;
맺음말: 도구의 맹점을 극복하는 엔지니어링
우리는 종종 강력한 프레임워크와 자동화 도구에 의존하며, 도구가 내뱉는 침묵을 나의 설정 실수로 자책하곤 합니다. 하지만 이번 MariaDB와 Drizzle ORM의 충돌 사례에서 볼 수 있듯, 각 시스템(DBMS와 ORM)이 데이터를 바라보고 해석하는 저수준(Low-level)의 차이에서 발생하는 아키텍처 결함은 언제든 발생할 수 있습니다.
결론적으로, MariaDB 환경에서 Drizzle Kit이 조용히 종료된다면 당황하지 마시고 데이터베이스 내의 JSON 타입 컬럼을 색출하여 일시적으로 LONGTEXT로 변경한 뒤 추출(pull)을 시도하십시오.
이러한 도구의 맹점을 파악하고 우회로를 설계해 내는 과정이야말로 개발자가 단순한 코더를 넘어 시스템 엔지니어로 성장하는 가장 가치 있는 경험일 것입니다. 본 포스팅이 원인 모를 'Silent Fail' 버그로 밤을 지새우는 수많은 개발자들의 퇴근 시간을 앞당기는 데 도움이 되기를 진심으로 바랍니다.