웹 개발

PlanetScale + Kysely 데이터베이스 연동 (Next.js)

깨비아빠0 2024. 1. 4. 20:38
728x90
반응형

Next.js 프로젝트 스택 검토 (2023) 대로 홈페이지를 다시 만들기 위한 두 번째 단계로 Kysely를 사용하여 PlanetScale 데이터베이스를 연동했다.

 

 

 

PlanetScale 데이터베이스 셋업

https://planetscale.com/docs/tutorials/planetscale-quick-start-guide를 따라하면 정말 쉽게 새 데이터베이스를 만들 수 있다. 데이터베이스 생성이 끝나면 대시보드에서 DB 상태를 비롯해 각종 정보를 볼 수 있다.

 

 

우측의 Connect 버튼을 누르면 username 등의 DB 접속 정보를 확인할 수 있는데, Connect with에서 MySQL CLI를 선택하면 나오는 명령을 참고하여 일반적인 DB 클라이언트에서 접속 가능하다.

 

다음은 MySQLWorkbench에서 방금 만든 데이터베이스에 gcp.connect.psdb.cloud:3306 주소로 접속하여, Quick Guide를 따라 샘플 테이블을 만들어 본 화면이다.

 

 

Kysely 셋업

패키지 설치

다음 명령으로 kysely, PlanetScale dialect, kysely-codegen(스키마 코드 생성기)를 설치한다.

npm install kysely kysely-planetscale @planetscale/database
npm install --save-dev kysely-codegen mysql2
mysql2는 kysely-codegen에서 DB에 접속할 때만 사용하므로 --save-dev로 설치한다.

 

데이터베이스 환경변수 추가

Connect 정보 화면에서 Connect with @planetscale/database를 선택하면 DB 접속에 필요한 host, username을 얻을 수 있다. (password는 최초 생성시에만 조회 가능)

DATABASE_HOST, DATABASE_USERNAME, DATABASE_PASSWORD 환경 변수를 .env.local 파일에 저장한다.

 

 

이 환경변수는 비밀번호를 포함하고 있으므로, git에 올리는 대신 Vercel 플랫폼 환경변수 세팅에도 추가한다.

Settings > Environment Variables 페이지에서 아래와 같이 DATABASE_HOST, DATABASE_USERNAME, DATABASE_PASSWORD 환경 변수를 추가하고, 하단의 Save 버튼을 누르면 저장된다.

 

 

DB 스키마 생성

kysely 연동을 위해 먼저 kysely-codegen으로 스키마 인터페이스 정의 파일을 생성한다.

kysely-codegen을 실행하려면 DATABASE_URL 환경 변수가 필요한데, PlanetScale Connect 정보 화면에서 Connect with Node.js를 선택하여 확인할 수 있다. (********을 비밀번호로 변경해줘야 함)

 

 

DATABASE_URL 환경 변수를 .env.local에 추가한 후에 아래와 같이 명령을 실행하면,

npx kysely-codegen --env-file .env.local --out-file lib/db-schema.d.ts

 

다음과 같이 lib 폴더에 db-schema.d.ts 파일이 생성된다.

 

 

데이터베이스 접속 구현

lib/database.ts 파일에 다음과 같이 Kysely 인스턴스를 생성한다.

위에서 추가한 DATABASE_xxx 환경 변수들을 PlanetScaleDialect config에 설정해주고, DB 스키마는 kysely-codegen으로 생성한 스키마 정의를 사용한다.

import 'server-only'

import { Kysely } from 'kysely'
import { PlanetScaleDialect } from 'kysely-planetscale'
import { DB } from './db-schema'
 
export const db = new Kysely<DB>({
  dialect: new PlanetScaleDialect({
    host: process.env.DATABASE_HOST,
    username: process.env.DATABASE_USERNAME,
    password: process.env.DATABASE_PASSWORD,
  }),
})
server-only는 서버에서만 실행되어야 하는 코드임을 구분해주는 패키지로서, "npm install server-only" 명령으로 설치해야 한다.

 

Repository 구현

쿼리 테스트를 위해 repository/products.ts 파일에 샘플로 만들었던 Products 테이블의 Repository 클래스를 추가하였다.

import { db } from '@/lib/database'
import { Products } from '@/lib/db-schema'

export class ProductsRepository {
  async all() {
    return await db.selectFrom('products')
      .selectAll()
      .execute()
  }

  async findById(id: number) {
    return await db.selectFrom('products')
      .where('id', '=', id)
      .selectAll()
      .executeTakeFirst()
  }
}

export const productsRepository = new ProductsRepository()

 

쿼리 테스트

메인 page.tsx에 DB 조회 및 HTML 코드를 추가했다.

export default async function Home() {
  const products = await productsRepository.all()

  return (
    <main ...>
      <ul>
        {products.map((product, index) => (
          <li key={index}>
            {product.id}: {product.name} (category: {product.category_id})
          </li>
        ))}
      </ul>
  ...

 

아래와 같이 products 테이블 레코드들이 정상적으로 출력된다.

 

Vercel 배포 테스트

GitHub에 코드를 push하면 자동으로 빌드가 시작된다.

빌드가 완료된 후 홈페이지에서도 다음과 같이 정상적으로 출력되는 것을 확인할 수 있었다.

 

 

 

 

참고: https://kysely.dev/docs/getting-started?dialect=mysql

 

Getting started | Kysely

Installation

kysely.dev

https://www.ayoubkhial.com/blog/build-fully-typed-web-app-using-next.js-planetscale-drizzle-and-kysely

 

Build a fully typed web app using Next.js, PlanetScale, Drizzle, and Kysely

Harness the power of PlanetScale, Drizzle ORM, and Kysely Query Builder to develop a scalable fully-typed web app.

www.ayoubkhial.com

 

반응형