Drizzle로 비즈니스 로직 짜다 보니 트랜잭션 함수 안에서 다른 트랜잭션 함수를 호출하게 됩니다. 이게 문제 없나요? 안쪽 트랜잭션이 따로 commit 되거나, 바깥쪽이 롤백돼도 안쪽이 살아남거나 하는 일이 있나요?
async function createOrder(...) {
return db.transaction(async tx => {
// ...
await chargePayment(tx, ...) // 이게 또 transaction 시작
})
}
async function chargePayment(tx, ...) {
return tx.transaction(async tx2 => {
// ...
})
}
댓글 3
안전합니다. Drizzle의 중첩
transaction()은 PostgreSQL의 SAVEPOINT로 자동 변환됩니다. 별도 트랜잭션이 아니라 같은 트랜잭션 안의 부분 마커입니다.실제 SQL 흐름
안쪽이 throw 하면
안쪽 에러를 try/catch로 잡으면 안쪽만 부분 롤백하고 바깥은 계속 진행 가능. 이게 SAVEPOINT의 강점.
실용 패턴 — 부분 실패 허용
한 가지 주의 — 안쪽 에러를 try/catch로 잡지 않으면 바깥까지 전파돼서 전체 롤백됩니다. "이 단계는 실패해도 OK"임을 명시적으로 처리해야 부분 롤백이 동작합니다.
안 되는 게 정답이고, 그래서 함수를 tx 받게 만들지 db 받게 만들지 하나로 정하는 게 핵심입니다.
패턴 1: 항상 tx 받기 (재사용성↑)
패턴 2: db 또는 tx 둘 다 받기 (편의성↑)
Drizzle은
db와Tx의 transaction 메서드 시그니처가 같아서 패턴 2가 깔끔합니다. 도메인 함수는 항상Executor를 받게 통일하세요.