어느날, PlanetScale의 무료 플랜 종료 소식이 다가왔다.
얼른 이사가라고 수 통의 이메일을 받았다.
억장 와르르멘션이었다.
편리하게 사이드 프로젝트 데이터베이스를 무료 호스팅하고 있었는데 대안이 필요했다.
planetscale alternative free를 검색해보면 PostgreSQL은 supabase, neon SQLite은 turso, MySQL은 cockroach 등 선택지가 있다.
모두 매력적인 선택지이지만, Vercel Postgres에서 neon을 래핑해서 서빙하다는 소식, 또 요즘 핫한 PostgreSQL를 경험해보고 싶은 마음에 neon을 새둥지로 이사 가보기로 했다.
pgloader로 데이터 옮기기
pgloader는 PostgreSQL 데이터를 등록할 수 있는 오픈소스이다.
이를 활용해 MySQL 데이터를 PostgresSQL로 쉽게 옮길 수 있다.
MacOS 기준, brew로 쉽게 설치를 할 수 있으며,
brew install pgloader
shell
아래 명령어로 MySQL에서 PostgreSQL로 데이터 마이그레이션 할 수 있다.
pgloader --with "quote identifiers" mysql://myuser@myhost/dbname pgsql://pguser@pghost/dbname
shell
자세한 옵션명을 하나 하나 정리하면 아래와 같다.
--with "quote identifiers"
카멜 케이스를 그대로 유지시키는 명령어이다.
그게 아니면 테이블명도 그렇고 칼럼명도 그렇고 스네이크 케이스로 적용된다.
자세한 내용은 공식문서 참고하면 된다.
mysql://myuser@myhost/dbname
우선 PlanetScale CLI를 통해서 로컬 호스트로 DB를 접근할 수 있다.
pscale login
pscale connect mildvu --port 8080
shell
따라서 MySQL 데이터베이스 호스트는 아래같이 입력하면 된다.
mysql://127.0.0.1:8080/mildvu"
shell
pgsql://pguser@pghost/dbname
neon 대시보드에서 데이터베이스 connection string을 받아오면 된다.
마이그레이션 할 땐 Pooled connection 옵션을 적용하지 않아도 괜찮다.
추가적으로 endpoint
옵션을 넣어줘야 하는데 ep-xxx
부분을 잘 찾아서 입력해주면 된다.
postgresql://mildvu_owner:endpoint=ep-xxx;[password]@ep-xxx.ap-southeast-1.aws.neon.tech/main?sslmode=require
shell
최종 형태 및 결과물
메모장에서 위 내용을 잘 조합하고, 이제 터미널에 명령어를 입력하면 된다.
pgloader --with "quote identifiers" mysql://127.0.0.1:8080/mildvu "postgresql://mildvu_owner:endpoint=ep-xxx;[password]@ep-xxx.ap-southeast-1.aws.neon.tech/main?sslmode=require"
shell
그러면 아래 같은 리포트를 볼 수 있다.
크흠.. 나의 데이터는 사실 117.3KB 밖에 되지 않았다.. 작지만 소중해
neon의 Tables에도 데이터가 잘 이전된 것을 확인 할 수 있다 ✨
neon 스키마 이름 변경
현재 데이터는 기존 데이터베이스명인 “mildvu”로 neon의 스키마로 이관이 되었지만, prisma는 이름이 “public”인 스키마를 접근하게 되는 것 같다.
이래 저래 시도해봤지만 결국 스키마명을 수정하여 문제를 해결했다.
neon 대시보드에 있는 SQL Editor
에서 아래 명령어로 스키마명을 변경할 수 있다.
ALTER SCHEMA "mildvu" RENAME TO "public"
sql
prisma 설정
prisma에서 neon의 사용법은 공식문서 가이드 대로 진행하면 된다.
prisma env
neon 대시보드에 있는 Connection string을 가져오면 된다.
여기서는 Pooled connection을 활성화시키자.
DATABASE_URL=postgresql://mildvu_owner:[password]@ep-ancient-firefly-a1fdd8wb-pooler.ap-southeast-1.aws.neon.tech/main?sslmode=require
txt
prisma schema
MySQL 대신 PostgreSQL을 명시하면 된다.
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
previewFeatures = ["driverAdapters"]
}
datasource db {
provider = "mysql"
provider = "postgresql"
url = env("DATABASE_URL")
referentialIntegrity = "prisma"
relationMode = "prisma"
}
prisma
생각보다 큰 충돌은 없었다.
추가적으로 문자열 관련 어노테이션을 수정해주면 되었다.
@db.MediumText
, @db.LongText
→ @db.VarChar()
prisma client
변경된 스키마 바탕으로 prisma client을 생성하고,
npx prisma generate
shell
가이드 대로 코드를 수정하면 된다.
import { neonConfig, Pool } from '@neondatabase/serverless';
import { PrismaNeon } from '@prisma/adapter-neon';
import { PrismaClient } from '@prisma/client';
import ws from 'ws';
declare global {
var _prisma: PrismaClient | undefined;
}
neonConfig.webSocketConstructor = ws;
const connectionString = `${process.env.DATABASE_URL}`;
const pool = new Pool({ connectionString });
const adapter = new PrismaNeon(pool);
const _prisma = global._prisma || new PrismaClient({ adapter });
if (process.env.NODE_ENV === 'development') {
global._prisma = _prisma;
}
export default _prisma;
ts
npx prisma generate
을 하지 않으면 타입 에러, 런타임 에러가 발생하니 꼭 유의하도록 하자.
맺으면서
사이드 프로젝트를 유지보수하는 것이 쉽지가 않는 것 같다.
특히 인프라 이슈가 있을 땐 진짜 맨땅에 헤딩이다.
하지만 덕분에 더 다양한 serverless 플랫폼을 알게 되었고, DB와도 조금 더 친해졌다.
앞으로 더 친해져 봐요 우리…
한편으로 Vercel이 무료 플랜을 종료한다면 어떻하지 머리가 아찔해졌다.