Drizzle는 TypeScript를 사용하여 다양한 모델과 데이터베이스에서 지원하는 속성으로 스키마를 정의할 수 있게 해줍니다.
스키마를 정의하면, 이는 향후 쿼리( Drizzle-ORM 사용)와 마이그레이션( Drizzle-Kit 사용)에서 수정할 때의 기준이 됩니다.
마이그레이션 과정에서 Drizzle-Kit을 사용한다면, 스키마 파일에 정의된 모든 모델을 내보내야 합니다.
이렇게 해야 Drizzle-Kit이 해당 모델을 가져와 마이그레이션 차이(diff) 과정에서 사용할 수 있습니다.
스키마 파일 구성하기
여러분은 SQL 스키마를 TypeScript에서 직접 선언할 수 있습니다. 이때 모든 스키마를 하나의 schema.ts 파일에 작성하거나, 여러 파일로 나누어 작성할 수도 있습니다. 선호하는 방식을 선택하면 됩니다. 자유롭게 구성하세요!
스키마를 한 파일에 정의하기
Drizzle에서 스키마를 선언하는 가장 일반적인 방법은 모든 테이블을 하나의 schema.ts 파일에 넣는 것입니다.
참고: 스키마 파일 이름은 원하는 대로 지정할 수 있습니다. 예를 들어 models.ts 등으로 지을 수 있습니다.
이 방법은 정의할 테이블 모델이 많지 않거나, 모든 모델을 하나의 파일에 유지하는 것이 괜찮을 때 잘 작동합니다.
예시:
drizzle.config.ts 파일에서 스키마 파일의 경로를 지정해야 합니다. 이 설정을 통해 Drizzle은 schema.ts 파일을 읽고, 마이그레이션 생성 과정에서 이 정보를 사용합니다. drizzle.config.ts 파일과 Drizzle 마이그레이션에 대한 자세한 내용은 다음 링크를 참고하세요: 링크
스키마를 여러 파일로 나누기
Drizzle 모델(테이블, 열거형, 시퀀스 등)은 하나의 파일에만 작성할 필요 없이 원하는 파일에 배치할 수 있습니다.
단, 모든 모델을 해당 파일에서 export 해야 Drizzle Kit이 이를 가져와 마이그레이션에 사용할 수 있습니다.
예를 들어, 각 테이블을 별도의 파일로 분리할 수 있습니다.
drizzle.config.ts 파일에서 스키마 폴더의 경로를 지정해야 합니다. 이 설정을 통해 Drizzle은 schema 폴더를 재귀적으로 탐색하고 모든 파일에서 Drizzle 테이블을 가져옵니다. drizzle.config.ts 파일과 Drizzle 마이그레이션에 대한 자세한 내용은 링크를 참고하세요.
또한, 원하는 방식으로 그룹화할 수도 있습니다. 예를 들어, 사용자 관련 테이블, 메시징 관련 테이블, 제품 관련 테이블 등을 그룹으로 묶을 수 있습니다.
drizzle.config.ts 파일에서 스키마 파일의 경로를 지정해야 합니다. 이 설정을 통해 Drizzle은 schema.ts 파일을 읽고 마이그레이션 생성 과정에서 이 정보를 사용합니다. drizzle.config.ts 파일과 Drizzle 마이그레이션에 대한 자세한 내용은 링크를 참고하세요.
데이터 스키마 설계하기
Drizzle 스키마는 사용 중인 데이터베이스의 여러 모델 타입으로 구성됩니다. Drizzle을 사용하면 다음과 같은 요소를 정의할 수 있습니다:
컬럼과 제약 조건이 있는 테이블
스키마(PostgreSQL 전용)
열거형(Enums)
시퀀스(PostgreSQL 전용)
뷰
구체화된 뷰(Materialized Views)
기타 요소
이제 하나씩 살펴보면서 Drizzle로 스키마를 정의하는 방법을 확인해 보겠습니다.
테이블과 컬럼 선언
Drizzle에서 테이블은 데이터베이스에서와 마찬가지로 최소 1개의 컬럼을 정의해야 합니다. 중요한 점은 Drizzle에는 공통 테이블 객체가 없다는 것입니다. 여러분은 사용할 데이터베이스 종류(PostgreSQL, MySQL, SQLite)를 선택해야 합니다.
PostgreSQL 테이블
MySQL 테이블
SQLite 테이블
기본적으로 Drizzle은 데이터베이스 쿼리에서 TypeScript의 키 이름을 컬럼 이름으로 사용합니다. 따라서 예제의 스키마와 쿼리는 아래와 같은 SQL 쿼리를 생성합니다.
이 예제는 db 객체를 사용하지만, 이 문서에서는 db 객체 초기화 방법을 다루지 않습니다. 데이터베이스 연결 방법을 알고 싶다면 연결 문서를 참고하세요.
TypeScript 키 = 데이터베이스 키
TypeScript 코드와 데이터베이스에서 서로 다른 이름을 사용하고 싶다면 컬럼 별칭을 사용할 수 있습니다.
카멜 케이스와 스네이크 케이스
데이터베이스 모델 이름은 주로 snake_case 규칙을 따르는 반면, TypeScript에서는 모델 이름에 camelCase를 사용하는 것이 일반적입니다. 이로 인해 스키마에서 많은 별칭 정의가 필요할 수 있습니다. 이를 해결하기 위해 Drizzle는 데이터베이스 초기화 시 하나의 선택적 매개변수를 포함하여 TypeScript의 camelCase를 데이터베이스의 snake_case로 자동 매핑하는 방법을 제공합니다.
이러한 매핑을 위해 Drizzle DB 선언에서 casing 옵션을 사용할 수 있습니다. 이 매개변수는 데이터베이스 모델 명명 규칙을 지정하고 모든 JavaScript 키를 그에 따라 매핑하려고 시도합니다.
이렇게 설정하면 TypeScript에서 firstName으로 정의된 필드가 데이터베이스에서는 first_name으로 자동 변환되어 쿼리가 실행됩니다.
고급 활용
Drizzle ORM을 사용할 때 몇 가지 유용한 트릭이 있습니다. Drizzle이 완전히 TypeScript 파일로 이루어져 있다면, 여러분은 일반 TypeScript 프로젝트에서 할 수 있는 모든 작업을 코드에 적용할 수 있습니다.
자주 사용되는 기능 중 하나는 컬럼을 다른 곳으로 분리한 후 재사용하는 것입니다. 예를 들어, updated_at, created_at, deleted_at 컬럼을 생각해보겠습니다. 많은 테이블이나 모델에서 이러한 세 가지 필드를 사용하여 시스템 내 엔티티의 생성, 삭제, 업데이트를 추적하고 분석할 수 있습니다.
이러한 컬럼을 별도의 파일에 정의한 후, 모든 테이블 객체에 가져와서 확장할 수 있습니다.
이렇게 하면 코드의 재사용성이 높아지고, 유지보수가 쉬워집니다.
스키마
PostgreSQL
MySQL
SQLite
PostgreSQL에는 스키마라는 엔티티가 있습니다. (이를 폴더라고 부르는 것이 더 적절할 것 같습니다.) 이는 PostgreSQL에서 다음과 같은 구조를 만듭니다.
pgSchema를 사용하여 PostgreSQL 스키마를 관리하고, 그 안에 다른 모델들을 배치할 수 있습니다.
Drizzle를 사용하여 관리할 스키마를 정의합니다.
그런 다음 스키마 객체 안에 테이블을 배치합니다.
MySQL에는 스키마라는 엔티티가 있지만, MySQL 용어로는 이는 데이터베이스와 동일합니다.
drizzle-orm을 사용하여 이를 정의하고 쿼리에서 사용할 수 있지만, drizzle-kit에 의해 감지되거나 마이그레이션 플로우에 포함되지는 않습니다.
Drizzle를 사용하여 관리할 스키마를 정의합니다.
그런 다음 스키마 객체 안에 테이블을 배치합니다.
SQLite에는 스키마 개념이 없으므로, 단일 SQLite 파일 컨텍스트 내에서만 테이블을 정의할 수 있습니다.
예제
기본 개념을 이해했다면, 실제 프로젝트에서 사용할 스키마 예제를 정의해 보겠습니다. 이를 통해 더 나은 이해를 얻을 수 있습니다.
모든 예제는 generateUniqueString을 사용합니다. 이 함수의 구현은 모든 스키마 예제 이후에 제공됩니다.