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
'웹 개발' 카테고리의 다른 글
SVG path 스케일링 (for responsive object-path) (0) | 2024.01.31 |
---|---|
Lucia 인증 연동 (Next.js, PlanetScale, Kysely, OAuth) (0) | 2024.01.10 |
shadcn/ui (Next.js) (2) | 2024.01.03 |
Next.js 프로젝트 스택 검토 (2023) (0) | 2023.12.30 |
Next.js 홈페이지 만들기 - 기본 레이아웃 (3/3) (4) | 2023.12.21 |