2024. 10. 20. 09:59ㆍBACKEND
Prisma 공부하기
최근 이직한 이후 신생회사에서 근무하게 되었고 기술전환을 하는 과정에서 Nest.js와 Prisma를 사용하는 것으로 최종 결정 되었다, 장기적으로 좋은 부분인 것 같다. 이제 1개월이 갓 지났지만 새삼 Node 환경에서 개발을 하다보니 Spring boot환경에 비해 정말 간편하고 빠르고 뭔가 가볍다는 느낌을 많이 받는 것 같다. Prisma에 대해 공부하며 글이 정리 될 때까지 글이 계속 수정 될 것 같다.
ORM에 대하여
나는 개인적으로 JPA를 공부하며 상당히 재밌고 좋다고 느꼈다. 그런데 막상 사용하려고 하거나 실무에서 사용 할 때 주의해야 하는 부분들을 알게 되면서 러닝커브가 높고 쉽지않은 기술이라는 생각도 많이 들었다. 아마도 국내에서 JPA를 가장 잘 아는분은 김영한님이 아닐까 싶은데 김영한님은 자신의 JPA 인프런 강의에서 이런 이야기를 한다.
JPA는 쉬운 기술이 아니에요 객체지향에 대해서도 잘 알아야 하고 SQL에 대한 지식도 뛰어나야 됩니다. 배우기 쉬운 기술은 아니지만 딱 한번 열심히 공부해 놓으면 SQL 노가다로 발생하는 시간을 줄이고 비즈니스 로직을 잘 만들기 위해 고민 할 수 있는 시간이 늘어 납니다
대략 이런 이야기를 했었다. ORM을 사용하려면 많이 공부해야 하고 객체지향과 SQL에 대해서도 많이 경험하고 잘 알아야 한다는 생각에 ORM을 사용하는 것에 대해 걱정이 있었지만 결과적으로 우리팀은 앞으로 Prisma를 사용해 1~2년간 진행할 기술이전에 적용 할 계획이다.
Prisma 준비하기
npm i prisma sqlite
# prisema의 provider로 sqlite를 사용 하도록 설정한다.
npx prisma init --datasource-provider sqlite
위 코드를 실행하면 prisma
라는 디렉토리가 생성되고 schema.prisma
파일이 생성되게 된다.
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
해당 파일에는 DB에 연결하기 위한 코드가 작성되어 있다. .env
파일로 접속정보를 관리한다.
schema.prisma
파일에 스키마를 정의하고 마이그레이션을 하면 DB에 테이블이 생성되게 된다.
JPA에서는 도메인 디렉토리를 생성하고 @Domain 어노테이션으로 스키마를 정의 한 뒤 어플리케이션이 실행되며 테이블을 생성 했지만 prisma에서는 마이그레이션(테이블 생성)을 위한 코드를 실행해 주어야 한다.
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)
authorId Int?
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
위 코드처럼 간략한 schema를 생성하고 shell에서 npx prisma migrate dev --name migrate-history
코드를 실행해 마이그레이션을 한다.
이미지처럼 migrations
디렉토리에 migrations.sql
에는 실제 어떤 SQL이 실행되었는지에 대한 내용이 저장되게 된다.npx prisma migrate dev --name migrate-history
를 입력했기 때문에 디렉토리명이 20241019020359_migrate_history
로 생성되었다 이름을 변경하고 싶다면 --name
옵션 뒤에 이름을 변경하자.
개발을 진행하며 schema가 추가 되거나 필드가 변경되는 등에 변경사항이 생기는 경우 마이그레이션 버전 관리를 위한 파일을 생성해 변경되는 스키마를 작성하고 npx prisma migrate dev --name added_job_title
이렇게 실행하면 added_job_title
라는 이름으로 쿼리의 실행 이력을 저장 할 수 있다. Springboot에서는 이러한 DB의 스키마 변경 관리를 위해 Flyway 라는 마이그레이션 관리툴을 사용 했는데 솔직히 그리 편하다는 느낌은 잘 안들었는데 물론 내가 관리 경험이 부족해서 일 것 같다. prisma는 자체적으로 마이그레이션 관리까지 고려한 것 같은데 잘 사용 할 수 있도록 앞으로 학습해야 할 것들이 많은 것 같다.
CRUD
CRUD를 알아보기 전에 먼저 client 라이브러리를 설치해야 한다. npm i @prisma/client
생성
import { PrismaClient, Prisma } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
let includePosts: boolean = false
let user: Prisma.UserCreateInput
// Check if posts should be included in the query
if (includePosts) {
user = {
email: 'elsa@prisma.io',
name: 'Elsa Prisma',
posts: {
create: {
title: 'Include this post!',
},
},
}
} else {
user = {
email: 'elsa@prisma.io',
name: 'Elsa Prisma',
}
}
// Pass 'user' object into query
const createUser = await prisma.user.create({ data: user })
}
main()
const createMany = await prisma.user.createMany({
data: [
{ name: 'Bob', email: 'bob@prisma.io' },
{ name: 'Bobo', email: 'bob@prisma.io' }, // Duplicate unique key!
{ name: 'Yewande', email: 'yewande@prisma.io' },
{ name: 'Angelique', email: 'angelique@prisma.io' },
],
skipDuplicates: true, // Skip 'Bobo'
})
조회
// By unique identifier
const user = await prisma.user.findUnique({
where: {
email: 'elsa@prisma.io',
},
})
// By ID
const user = await prisma.user.findUnique({
where: {
id: 99,
},
})
수정
const updateUser = await prisma.user.update({
where: {
email: 'viola@prisma.io',
},
data: {
name: 'Viola the Magnificent',
},
})
const updateUsers = await prisma.user.updateMany({
where: {
email: {
contains: 'prisma.io',
},
},
data: {
role: 'ADMIN',
},
})
삭제
const deleteUser = await prisma.user.delete({
where: {
email: 'bert@prisma.io',
},
})
const deleteUsers = await prisma.user.deleteMany({
where: {
email: {
contains: 'prisma.io',
},
},
})
delete의 경우 조건이 여러개인 경우 deleteMany를 사용해야 하므로 주의해야 한다고 한다.
내가 제대로 이해 한 것인지 모르겠는데 아마 id
같은 PK값으로 삭제 할 때에는 delete()
를 사용하면 되고
where에서 condition을 여러를 사용해 삭제하는 경우 deleteMany()
를 사용해야 한다는 말인 것 같다.
ORM을 사용해 보았다면 쉽게 이해 할 것 같다. 특히 ORM은 간단한 CRUD를 사용할때에는 정말 편리한 것 같다.
실제 개발에서는 훨씬 다양한 쿼리를 처리 해야 하고 도메인을 어떻게 잘 정의할 것인가가 어려운 부분이지만.
내용 업데이트 중
'BACKEND' 카테고리의 다른 글
Nest.js 공부하기 (2) (0) | 2024.11.27 |
---|---|
Nest.js 공부하기 (1) (3) | 2024.11.04 |
SOAP 프로토콜 사용하기 (0) | 2024.05.05 |
SpringBoot + Next.js 프로젝트 회고 (1) | 2024.01.11 |
SpringBoot 공부하기 2편 (1) | 2024.01.09 |