본문 바로가기

백엔드/Prisma + GraphQL

Prisma2 CLI를 사용하여 데이터베이스 테이블 생성

인스타그램 클론코딩에 사용된 schema.prisma 파일로 부터 데이터베이스 테이블을 생성해 보겠습니다.

참조: GraphQL with Prisma2 설계 구조

schema.prisma

[인스타그램 클론코딩] Prisma2 데이터 모델링 포스트에서는 모델링만 했지만, 사실 schema.prisma 파일에 데이터베이스Prisma 클라이언트에 대한 설정도 해 주어야 합니다.

// 데이터베이스 설정
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

// Prisma 클라이언트 설정
generator client {
  provider = "prisma-client-js"
  binaryTargets = ["rhel-openssl-1.0.x"]
  //binaryTargets = ["native"]
}

model User {
  ...
}

model Post {
  ...
}

...

참조: Prisma2 클라이언트 생성

.env

Prisma를 초기화할 때 ./prisma 폴더에 schema.prisma 파일과 함께 생성되는 환경변수 파일입니다.

해당 파일에 정의된 DATABASE_URL 환경변수를 위의 schema.prisma 파일에서 불러옵니다.

 

Prisma 클라이언트를 생성할 때, Prisma CLI 모듈이 알아서 동일한 폴더의 .env를 참조하기 때문에 별다른 설정은 필요없습니다.

참조: Prisma2 설치 (CLI, 클라이언트)

DATABASE_URL="mysql://USER:PASSWORD@HOST:PORT?OPTIONS"

USER, PASSWORD

  • 현재 Prisma가 지원하는 데이터베이스는 Postgre, MySQL, SQLite입니다. 이 중 Postgre와 MySQL은 데이터베이스 생성시 사용자 이름과 패스워드를 설정해야 합니다. SQLite는 파일 주소만 입력하면 됩니다.
  • Prisma 클라이언트에 데이터베이스에 접근할 수 있도록 데이터베이스 사용자 이름과 패스워드를 알려주어야 합니다.

HOST

  • 데이터베이스의 앤드포인트입니다.
  • 클라이언트에서 HOST 주소를 사용하여 데이터베이스에 접근합니다.
  • 저의 경우는 AWS RDS에서 MySQL 데이터베이스를 사용하고 있습니다. 당연히 Azure나 GCP 데이터베이스 서비스도 인스턴스 생성시 HOST 주소도 같이 제공할 것입니다.

AWS RDS MySQL 인스턴스

PORT

  • MySQL(3306), Postgre(5432) 기본 포트가 사용됩니다.
  • 물론 설정에 따라 얼마든지 달라질 수 있습니다.

OPTIONS

  • Prisma 클라이언트가 데이터베이스와 통신할 때 데이터베이스의 connection_pool 갯수, 연결 타임아웃 등을 설정할 수 있습니다.
  • 필수는 아닙니다.
  • 데이터베이스 종류마다 다른 옵션이 있습니다.

참고

테이블 생성

이제 명령어 단 두 줄이면 Prisma CLI가 .env의 DATABASE_URL에 입력했던 데이터베이스에 접속하여 Prisma 모델(schema.prisma)과 동일한 구조의 테이블을 생성합니다.

npx prisma migrate save --name init --experimental
npx prisma migrate up --experimental

Prisma CLI가 생성한 테이블

Prisma CLI가 테이블 생성에 사용했던 SQL 명령어는 다음과 같습니다. Prisma의 Relation이 데이터베이스의 Relation으로 변환된 것을 확인할 수 있습니다.

User 테이블

CREATE TABLE `User` (
	`avatar` VARCHAR(191) NOT NULL DEFAULT 'https://3.bp.blogspot.com/-qtEejOg1NHA/Xobmg2y_QeI/AAAAAAAAIVE/UFKPvpeHjKUqCEFOX8lT4MsKz-PwpEGJgCLcBGAsYHQ/s1600/default_user.png' COLLATE 'utf8mb4_unicode_ci',
	`bio` VARCHAR(191) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci',
	`createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	`email` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
	`firstName` VARCHAR(191) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci',
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`lastName` VARCHAR(191) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci',
	`updatedAt` DATETIME(3) NOT NULL,
	`userName` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
	`name` VARCHAR(191) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci',
	PRIMARY KEY (`id`) USING BTREE,
	UNIQUE INDEX `User.userName` (`userName`) USING BTREE,
	UNIQUE INDEX `User.email` (`email`) USING BTREE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=70
;

Post 테이블

CREATE TABLE `Post` (
	`caption` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
	`createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`location` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
	`updatedAt` DATETIME(3) NOT NULL,
	`userId` INT(11) NOT NULL,
	PRIMARY KEY (`id`) USING BTREE,
	INDEX `userId` (`userId`) USING BTREE,
	CONSTRAINT `Post_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `instagureng`.`User` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=98
;

Like 테이블

CREATE TABLE `Like` (
	`createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`postId` INT(11) NOT NULL,
	`updatedAt` DATETIME(3) NOT NULL,
	`userId` INT(11) NOT NULL,
	PRIMARY KEY (`id`) USING BTREE,
	INDEX `userId` (`userId`) USING BTREE,
	INDEX `postId` (`postId`) USING BTREE,
	CONSTRAINT `Like_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `instagureng`.`User` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
	CONSTRAINT `Like_ibfk_2` FOREIGN KEY (`postId`) REFERENCES `instagureng`.`Post` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=110
;

File 테이블

CREATE TABLE `File` (
	`createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`postId` INT(11) NOT NULL,
	`updatedAt` DATETIME(3) NOT NULL,
	`url` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
	PRIMARY KEY (`id`) USING BTREE,
	INDEX `postId` (`postId`) USING BTREE,
	CONSTRAINT `File_ibfk_1` FOREIGN KEY (`postId`) REFERENCES `instagureng`.`Post` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=238
;

Comment 테이블

CREATE TABLE `Comment` (
	`createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`postId` INT(11) NOT NULL,
	`text` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
	`updatedAt` DATETIME(3) NOT NULL,
	`userId` INT(11) NOT NULL,
	PRIMARY KEY (`id`) USING BTREE,
	INDEX `userId` (`userId`) USING BTREE,
	INDEX `postId` (`postId`) USING BTREE,
	CONSTRAINT `Comment_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `instagureng`.`User` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
	CONSTRAINT `Comment_ibfk_2` FOREIGN KEY (`postId`) REFERENCES `instagureng`.`Post` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
AUTO_INCREMENT=54
;

_UserFollows 테이블

CREATE TABLE `_UserFollows` (
	`A` INT(11) NOT NULL,
	`B` INT(11) NOT NULL,
	UNIQUE INDEX `_UserFollows_AB_unique` (`A`, `B`) USING BTREE,
	INDEX `_UserFollows_B_index` (`B`) USING BTREE,
	CONSTRAINT `_UserFollows_ibfk_1` FOREIGN KEY (`A`) REFERENCES `instagureng`.`User` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
	CONSTRAINT `_UserFollows_ibfk_2` FOREIGN KEY (`B`) REFERENCES `instagureng`.`User` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
;