일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- Git
- ML
- PRISMA
- python
- GAN
- C++
- PyTorch
- ts
- react
- SOLID
- review
- DB
- figma
- sqlite
- ps
- html
- vscode
- nodejs
- mongo
- frontend
- API
- Linux
- threejs
- js
- Express
- UI
- DM
- CSS
- postgresql
- CV
- Today
- Total
아카이브
[DB][Prisma] transaction 설정하기 본문
DB API를 구현할 때는 한 번의 요청에 대해 여러 개의 함수를 실행하는 경우가 있습니다.
이 때 중요한 것은 모든 함수가 한 번에 수행되어야 하는 것인데,
중간에 오류가 발생해 처리가 중단되면, 처리가 완결되지 않은 불완전한 상태로 남기 때문입니다.
예를 들어 상품 재고를 관리하는 서버를 생각해봅시다.
아래 코드는 주문(order) 요청을 처리하는 엔드포인트로, 크게 두 가지 절차를 진행합니다.
1. order 테이블에 새로운 주문정보에 해당하는 record를 추가
2. 해당 주문에서 요청한 상품들의 수량만큼 product 테이블에서 각 record들의 quantity를 감소
(자세한 구현사항은 생략했습니다)
const prisma = new PrismaClient();
app.post('/orders', async (req, res) => {
// ...
// 1. order 테이블에 새로운 record를 추가합니다.
const order = await prisma.order.create({
// ...
});
// 2. 주문한 수량만큼 product 테이블에서 해당 record들의 quantity를 감소합니다.
const queries = productIds.map((productId) =>
prisma.product.update({
// ...
})
);
await Promise.all(queries);
// ...
res.status(201).send(order);
});
위 코드는 문법상으로는 문제가 되지 않습니다.
하지만, 만약 1. order record 추가가 된 후 2. product record quantity 감소 단계에서 에러가 발생하면 문제가 됩니다.
이 경우 엔드포인트는 오류와 함께 종료될 것이고, 주문은 처리되었지만 재고는 감소되지 않은 채로 끝나기 때문입니다.
따라서 엔드포인트 함수들을 안전하게 실행시키려면 1, 2 두 단계가 한 번에 실행되도록 해서
1, 2 모두 실행되지 않거나 모두 실행되는 경우만 존재하도록 해야 합니다.
Prisma에서는 $transaction 함수를 이용해서 이를 구현할 수 있습니다.
$transaction이 받는 인자는 transaction으로 묶을 함수들의 리스트입니다.
await PrismaClient.$transaction([func1, func2, ...]);
$transaction을 이용하면 위 예시를 아래와 같이 구현할 수 있습니다.
2번 단계는 transaction에서 반환할 필요가 없으므로 destructuring(...)처리를 하고, order만 반환하도록 했습니다.
const prisma = new PrismaClient();
app.post('/orders', async (req, res) => {
// ...
const [ order ] = await prisma.$transaction([
// 1. order 테이블에 새로운 record를 추가합니다.
const order = await prisma.order.create({
// ...
}),
// 2. 주문한 수량만큼 product 테이블에서 해당 record들의 quantity를 감소합니다.
...productIds.map((productId) =>
prisma.product.update({
// ...
})
),
]);
// ...
res.status(201).send(order);
});
'Backend > DB' 카테고리의 다른 글
[DB][Mongo] MongoDB에 대해서 (0) | 2025.02.15 |
---|---|
[PostgreSQL][Render] Render로 PostgreSQL DB 배포하기 (1) | 2024.08.28 |
[DB][Prisma] foreign key를 이용해 일대다/일대일/다대다 관계 정의하기 (0) | 2024.08.26 |
[DB][Prisma] PrismaClient 함수 정리 (0) | 2024.08.25 |
[DB][Prisma] Prisma에서 데이터 시딩하기 (0) | 2024.08.24 |