1. Prisma의 Transaction
Prisma의 트랜잭션은 여러 개의 쿼리를 하나의 트랜잭션으로 수행할 수 있는
Sequential 트랜잭션과 Prisma가 자체적으로 트랜잭션의 성공과 실패를
관리하는 Interactive 트랜잭션이 존재합니다.
2. Sequential 트랜잭션
- Sequential 트랜잭션 1
- Sequential 트랜잭션 2
Sequentai 트랜잭션은 Prisma의 여러 쿼리를 배열([])로 전달받아,
각 쿼리들을 순서대로 실행하는 특징이 있습니다. 이러한 특징은
여러 작업이 순차적으로 실행되어야 할 때 사용할 수 있습니다.
3. Interactive 트랜잭션
Interactive 트랜잭션은 모든 비즈니스 로직이 성공적으로 완료되거나 에러가 발생한
경우 Prisma 자체적으로 Commit 또는 RollBack을 실행하여 트랜잭션을 관리하는
장점을 가지고 있습니다.
Interactive 트랜잭션은 트랜잭션 진행 중에도 비즈니스 로직을 처리할 수 있어,
복잡한 쿼리 시나리오를 효과적으로 구현할 수 있습니다.
이때, $transation() 메서드의 첫 번째 인자 async(tx)는 저희가 일반적으로 사용하는
prisma 인스턴스와 같은 기능을 수행합니다.
4. 회원가입 API 트랜잭션 적용하기
사용자 및 사용자 정보를 생성하는 과정에서 에러가 발생할 수 있기 때문에,
트랜잭션(Transaction)을 도입해 하나의 작업으로 묶어주겠습니다.
먼저,
을 import 받은 후,
기존 작업 물을 복사한 뒤
//기존 작업 물 붙여 넣기
위와 같은 틀에 붙여넣습니다.
그 후, 우리는 transaction을 사용해야하기 때문에,
prisma의 각 테이블 조회 부분을
으로 수정해주고,
을
으로 테이블 조회 결과를 배열 분해 및 할당으로 전달합니다.
전체 코드 :
위의 코드를 분석해보면,
prisma.$transaction으로 트랜직션을 사용할 것을 명시적으로 작성합니다.
그리고,
해당 tx(transaction) 값으로 해당 쿼리 내부를 실행시킵니다.
마지막으로, 최종 로직이 완료 됐을 때
결과를 반환되고,
에 할당 됩니다.
은 격리수준으로
키를 바탕으로,
Prisma의 TransactionIsolationLevel을 ReadCommitted으로 지정해줍니다.
TranactionIsolationLevel에는
- ReadUncommitted : 트랜잭션이 아직 커밋되지 않은 데이터도 읽을 수 있다.
- ReadCommitted : 실제 커밋된 결과값만 읽을 수 있도록 한다.
- RepeatableRead : 트랜잭션이 시작된 후 데이터를 다시 읽을 때 동일한 결과가 보장됩니다.
- Serializeable : 가장 높은 격리 수준으로, 트랜잭션이 직렬화된 것 처럼 실행됩니다. 모든 종류의 일관성 문제를 방지하지만 성능에 큰 영향을 줄 수 있습니다.
이 존재합니다.
이제 Insomnia에서 회원가입을 진행하면
위와 같이 정상적으로 회원가입이 완료되고,
log.middleware.js 를 통해
Transaction의ISOLATION LEVEL이 READ COMMITTED이라는 걸 확인할 수 있습니다.
만약 고의적으로 Error를 발생시킬 경우,
트랜잭션이 ROLLBACK되는걸 확인할 수 있습니다.
5. 사용자 히스토리 모델 생성하기
사용자 히스토리(UsersHistories) 테이블이 생성되었습니다.
이 테이블은 사용자의 정보가 변경될 때 마다 변경 내역을 로깅(Logging) 하기 위해 사용 됩니다.
사용자 정보 변경 API를 구현하면서, 이 변경 내역을 사용자 히스토리 테이블에도 함께 데이터를
생성하도록 구현하겠습니다.
model UserHistories{
userHistoryId String @id @default(uuid()) @map("userHistoryId")
//uuid()는 실제 생성된 데이터의 날짜나 시간 등 다양한 정보를 제공하는 식별자입니다.
userId Int @map("userId")
changedField String @map("changedField")
oldValue String? @map("oldValue")
newValue String @map("newValue")
changedAt DateTime @updatedAt @map("changedAt")
// Users 테이블과 관계를 설정합니다.
user Users @relation(fields: [userId], references: [userId], onDelete : Cascade)
@@map("UserHistories")
}
내용을 schema.prisma에 추가해줍니다.
그리고,
model Users {
~~~~
userHistories UserHistories[] // 사용자(Users) 테이블과 사용자 히스토리(UserHistories) 테이블이 1 : N 관계를 맺습니다.
}
을 추가시켜줍니다.
위와 같이 수정 및 작성을 완료한 후,
npx prisma db push를 수행해줍니다.
UUID(범용 고유 식별자)란 무엇인가요?
총 4가지 정보를 하이픈(-)으로 구분하여 순차적으로 저장한 데이터 타입입니다.
시간 정보를 포함하고 있어 새성된 순서대로 정렬이 되는 특징을 가지고 있습니다.
사용자 히스토리 테이블은 UUID를 사용하여 컬럼 수를 최소화
하는 것이 로그 테이블에서는 더욱 효율적인 설계가 될 것입니다
6. 사용자 정보 변경 API
Insomnia에서 변경을 시켜보면,
위와 같이 변경이 잘 이뤄지고, History Table에도 잘 반영된 것을 확인할 수 있습니다.
'Node 강의 > 숙련' 카테고리의 다른 글
2-9 [게시판 프로젝트] express-session으로 리팩토링 (0) | 2024.09.09 |
---|---|
2-8 express-session (0) | 2024.09.09 |
2-6 트랜잭션(Transcation) (0) | 2024.09.09 |
2-5 [게시글 프로젝트] 댓글 생성 API (0) | 2024.09.09 |
2-4 [게시판 프로젝트] 게시글 생성 API (0) | 2024.09.09 |