Logo

Prisma 처음 시작하기

최근에 ORM으로 Prisma를 선택하는 자바스크립트 또는 타입스크립트 프로젝트가 부쩍 많아진 느낌입니다. 이번 포스팅에서는 차세대 ORM 프레임워크로 각광받고 있는 Prisma에 대해서 함께 알아볼까요?

Prisma란?

Prisma는 자바스크립트와 타입스크립트 커뮤니티에서 주목받고 있는 차세대 ORM(Object Relational Mapping) 프레임워크입니다.

데이터베이스와 상호작용하는 응용 애플리케이션을 개발할 때, 프로그래머가 직접 SQL을 작성하지 않아도 되므로, 개발 생산성을 높여주는 측면에서 기존에 사용되던 Sequelize나 TypeORM과 같은 여타의 ORM과 유사한데요. Prisma는 여기서 한 발자국 더 나아가 효과적인 데이터 모델링을 위한 간단하지만 강력한 자체적인 스키마 문법을 제공하고 이 스키마를 통해서 DB 마이그레이션과 클라이언트 코드 생성을 완전히 자동으로 생성해줍니다.

따라서 개발자 입장에서는 데이터베이스에 접근하기 위해서 작성해야하는 코드가 비약적으로 줄어들 뿐만 아니라 스키마 파일 하나만 잘 관리하면 되기 때문에 유지보수에도 훨씬 수월해지는 이점이 있습니다. 뿐만 아니라 CLI나 GUI가 도구가 잘 갖춰져 있어서 개발자 경험도 상당히 띄어난 것으로 알려져있습니다.

Prisma CLI 설치

Prisma는 개발자가 좀 더 편리하게 Prisma를 설정하고 사용할 수 있도록 강력한 CLI(명령 줄 인터페이스) 도구를 제공하고 있습니다. 따라서 Prisma CLI를 통해서 Prisma 시작하시는 것을 강력하게 추천드리고 싶습니다.

그럼 터미널을 열고 npm 패키지 매니저로 prisma 패키지를 개발 의존성으로 설치합니다.

$ npm i -D prisma

added 2 packages, and audited 3 packages in 8s

found 0 vulnerabilities

이제 npxprisma라는 커맨드를 사용할 수 있는데요. 단순히 터미널에서 prisma 커맨드를 실행해보면 간단한 설명서를 보실 수 있으실 겁니다.

$ npx prisma

◭  Prisma is a modern DB toolkit to query, migrate and model your database (https://prisma.io)

Usage

  $ prisma [command]

Commands

            init   Set up Prisma for your app
        generate   Generate artifacts (e.g. Prisma Client)
              db   Manage your database schema and lifecycle
         migrate   Migrate your database
          studio   Browse your data with Prisma Studio
        validate   Validate your Prisma schema
          format   Format your Prisma schema

Flags

     --preview-feature   Run Preview Prisma commands

Examples

  Set up a new Prisma project
  $ prisma init

  Generate artifacts (e.g. Prisma Client)
  $ prisma generate

  Browse your data
  $ prisma studio

  Create migrations from your Prisma schema, apply them to the database, generate artifacts (e.g. Prisma Client)
  $ prisma migrate dev

  Pull the schema from an existing database, updating the Prisma schema
  $ prisma db pull

  Push the Prisma schema state to the database
  $ prisma db push

  Validate your Prisma schema
  $ prisma validate

  Format your Prisma schema
  $ prisma format

npx나 npm 명령어에 대한 자세한 설명은 관련 포스팅를 참고 바랍니다.

Prisma 프로젝트 구성

다음으로 Prisma CLI를 이용해서 새로운 Prisma 프로젝트를 구성해보겠습니다.

위의 커맨드 설명서에 나와있는 것처럼 prisma init 명령어를 이용하시면 되고요. 데이터베이스는 최대한 간단한 실습을 위해서 파일 기반인 SQLite를 사용해보려고 합니다. Prisma는 기본적으로 PostgreSQL를 데이터베이스로 사용하기 때문에 이를 위해서는 --datasource-provider 옵션을 sqlite로 줘야 합니다.

$ npx prisma init --datasource-provider sqlite

✔ Your Prisma schema was created at prisma/schema.prisma
  You can now open it in your favorite editor.

Next steps:
1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started
2. Run prisma db pull to turn your database schema into a Prisma schema.
3. Run prisma generate to generate the Prisma Client. You can then start querying your database.

More information in our documentation:
https://pris.ly/d/getting-started

이제 프로젝트의 구조를 보면 prisma 디렉토리 안에 schema.prisma 파일이 생성되어 있는 것을 볼 수 있을 것입니다.

$ tree -L 2 -a
.
├── .env
├── .gitignore
├── node_modules
│   ├── .bin
│   ├── .package-lock.json
│   ├── @prisma
│   └── prisma
├── package-lock.json
├── package.json
└── prisma
    └── schema.prisma

Prisma 스키마 작성

이제 Prisma의 심장과도 같은 schema.prisma을 작성해야하는데요. Prisma는 어떤 데이터베이스를 사용하든 동일한 방식으로 데이터 모델링을 할 수 있도록 자체적인 스키마 문법을 제공하고 있습니다.

그럼 간단하게 id, email, name 필드(field)로 이뤄진 User 모델(model)에 대한 스키마를 작성해보겠습니다.

prisma/prisma.schema
model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
}

관계형 데이터베이스의 관점에서 Prisma의 모델은 테이블(table)이 되고 Prisma의 필드는 칼럼(column)이랑 대응된다고 생각하시면 이해가 편하실 것 같습니다.

DB 마이그레이션 실행

이제 작성한 Prisma 스키마를 토대로 SQLite 데이터베이스에 테이블을 생성해야하는데요. 이를 위해서는 prisma migrate dev 커맨드를 사용할 수 있습니다.

$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": SQLite database "dev.db" at "file:./dev.db"

SQLite database dev.db created at file:./dev.db

Applying migration `20230226182528_init`

The following migration(s) have been created and applied from new schema changes:

migrations/
  └─ 20230226182528_init/
    └─ migration.sql

Your database is now in sync with your schema.

Running generate... (Use --skip-generate to skip the generators)

added 2 packages, and audited 5 packages in 6s

found 0 vulnerabilities

✔ Generated Prisma Client (4.10.1 | library) to ./node_modules/@prisma/client in 37ms

이 커맨드는 여러 가지 일을 합니다.

우선 prisma 디렉토리 안에 SQLite를 위해서 dev.db라는 파일이 생성해줍니다.

참고로 SQLite가 사용할 파일 경로는 prisma.schema 파일의 datasource 구역에 정의가 되어있으며,

prisma/prisma.schema
datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

이미 .env 파일에 DATABASE_URL 환경 변수의 값이 명시되어 있습니다.

.env
DATABASE_URL="file:./dev.db"

두 번째로 이 커맨드는 마이그레이션 파일을 prisma/migrations 디렉토리에 생성해주는데요. 현재 날짜와 시간 그리고 --name 옵션에 넘겼던 문자열이 조합되어 디렉토리명이 만들어지고, 그 안에 migration.sql 파일이 생성됩니다.

이 파일 안에는 SQLite에서 테이블과 인덱스를 생성하기 위한 필요한 SQL이 담겨져 있습니다.

prisma/migrations/20230226182528_init/migration.sql
-- CreateTable
CREATE TABLE "User" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "email" TEXT NOT NULL,
    "name" TEXT
);

-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");

이 커맨드는 DB 마이그레이션을 실행까지 해주기 때문에 그에 따라 dev.db 파일이 수정이 됩니다. 하지만 dev.db는 사람이 직접 읽을 수 있는 형태의 데이터가 아니므로 잠시 뒤에 확인할 수 있는지에 대해서 따로 살펴볼께요.

마지막으로 이 커맨드는 Prisma 클라이언트(client) 코드까지 생성을 해주는데요. 이 클라이언트 코드를 사용하여 우리는 매우 간편하게 데이터베이스에 접근할 수 있을 것입니다.

프로그램 작성

이제부터 데이터베이스에 사용자를 저장하고 그 사용자를 조회하는 간단한 타입스크립트 프로그램을 작성해보겠습니다.

우선 typescript@types/node, ts-node 패키지를 개발 의존성으로 설치하겠습니다. @types/node는 타입스크립트로 Node.js에서 돌아가는 코드를 작성할 때 필요하며, ts-node는 타입스크립트로 작성된 코드를 Node.js에서 실행하기 위해서 필요합니다.

$ npm i -D typescript @types/node ts-node

added 19 packages, and audited 24 packages in 3s

found 0 vulnerabilities

이전 단계에서 자동으로 생성해놓은 Prisma 클리언트 코드는 @prisma/client 패키지로부터 PrismaClient라는 클래스 이름으로 불러올 수 있는데요. 이 PrismaClient 클래스로 생성한 인스턴스의 user 속성을 통해서 우리는 User 테이블에 데이터를 추가/조회/수정/삭제를 수행할 수 있습니다.

그럼 index.js 파일을 생성하고 다음과 같은 타입스크립트 코드를 작성해보겠습니다.

index.ts
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

async function main() {
  await prisma.user.create({    data: {      email: "user@test1.com",    },  });  const users = await prisma.user.findMany();  console.log(users);}

main()
  .then(async () => {
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });

위 프로그램을 터미널에서 ts-node 커맨드를 통해 실행해보면 데이터베이스에 저장된 사용자 레코드가 조회되어 출력되는 것을 볼 수 있을 겁니다.

$ npx ts-node index.ts
[ { id: 1, email: 'user@test.com', name: null } ]

Prisma Studio 활용

Prisma는 데이터베이스에 저장된 데이터를 브라우저 상에서 좀 더 편하게 확인하고 편집할 수 있도록 Prisma Studio라는 GUI(그래픽 사용자 인터페이스) 도구도 제공하고 있는데요. 터미널에서 prisma studio 커맨드를 실행하면 새로운 브라우저 창이 열리고 각 모델에 대한 테이블이 시각화될 것입니다.

$ npx prisma studio
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Prisma Studio is up on http://localhost:5555
imports from "@prisma/client/runtime" are deprecated.
Use "@prisma/client/runtime/library",  "@prisma/client/runtime/data-proxy" or  "@prisma/client/runtime/binary"

마치면서

이상으로 간단한 실습을 통해서 Prisma 프로젝트를 시작하고 필수적인 기능들을 체험해보았습니다. 기존에 Sequelize나 TypeORM과 같은 ORM 라이브러리를 써보셨다면 특별히 새로울 것이 없겠지만, 이러한 ORM 개념을 처음 접하시는 분들에게는 조금 어려운 내용이 되었을 것 같기도 합니다.

본 포스팅에서 다룬 부분은 사실 Prisma가 제공하는 방대한 기능의 빙산의 일각이라고 볼 수 있는데요. 추후 다른 포스팅을 통해서 Prisma의 여러 가지 기능들을 좀 더 깊게 알아보는 시간을 갖도록 하겠습니다.

Prisma 관련 포스팅은 Prisma 태그를 통해서 쉽게 만나보세요!