A Developing Developer

Transaction 본문

개발 상식

Transaction

H-JJOO 2023. 2. 28. 21:48

트랜잭션(Transaction)은 데이터베이스(Database)에서 수행하는 작업의 논리적 단위를 말한다.

 

여러 개의 쿼리문으로 이루어진 하나의 논리적인 작업 단위를 말하며, 일련의 작업을 모두 수행하거나 모두 취소하는 것이 가능하다.

 

트랜잭션은 데이터베이스에서 안전하게 데이터를 관리하기 위한 기능 중 하나이다. 예를 들어, 한 번에 여러 개의 계좌에서 돈을 이체하는 작업을 수행할 때, 이체하는 과정에서 일어나는 문제로 인해 중간에 작업이 멈추게 되면, 일부 계좌에서만 이체가 이루어졌을 가능성이 있다. 이러한 문제를 방지하기 위해 트랜잭션을 사용하여 작업이 완료되거나 모두 취소되도록 하여 데이터 일관성을 유지한다.

 

트랜잭션은 보통 ACID라는 속성을 가지고 있습니다. ACID는 다음과 같이 정의된다.

  • 원자성(Atomicity) : 트랜잭션은 전부 실행되거나 전혀 실행되지 않아야함
  • 일관성(Consistency) : 트랜잭션이 실행 전과 후의 데이터는 일관성이 있어야함
  • 고립성(Isolation) : 트랜잭션 실행 중에 다른 트랜잭션의 영향을 받지 않아야함
  • 지속성(Durability) : 트랜잭션으로 인한 데이터 변경은 영구적으로 반영되어야함

- Nest.js 에서 TypeORM 을 사용한 트랜잭션 코드

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Connection } from 'typeorm';
import { User } from './user.entity';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    private readonly connection: Connection,
  ) {}

  async transferFunds(fromUserId: number, toUserId: number, amount: number) {
    return this.connection.transaction(async transactionalEntityManager => {
      const fromUser = await transactionalEntityManager.findOne(User, fromUserId);
      const toUser = await transactionalEntityManager.findOne(User, toUserId);

      if (!fromUser || !toUser) {
        throw new Error('Invalid user IDs');
      }

      if (fromUser.balance < amount) {
        throw new Error('Insufficient funds');
      }

      fromUser.balance -= amount;
      toUser.balance += amount;

      await transactionalEntityManager.save(fromUser);
      await transactionalEntityManager.save(toUser);
    });
  }
}

위 코드에서 transferFunds 메소드는 fromUserId에서 toUserId로 amount만큼의 금액을 이체하는 메소드이다.

 

이 메소드는 this.connection.transaction()을 사용하여 트랜잭션을 실행하고, 해당 트랜잭션 내에서 User 엔티티의 데이터를 조회하고 수정한다.

 

트랜잭션이 정상적으로 완료되면 save() 메소드를 사용하여 변경된 데이터를 저장한다.

 

위 코드에서 transaction() 메소드의 콜백 함수에서 사용된 transactionalEntityManager는 해당 트랜잭션에서만 유효한 EntityManager 이다.

 

이 EntityManager를 사용하여 데이터 조회, 수정, 저장 등의 작업을 수행한다.

 

이 방식으로 트랜잭션을 사용하면, 해당 트랜잭션 내에서 일어나는 모든 작업은 원자성을 보장하며, 데이터 일관성을 유지할 수 있다.

'개발 상식' 카테고리의 다른 글

Redis  (0) 2023.02.27
Scope & Closure  (0) 2023.02.23
TypeORM 에서 'n + 1 problem' 은 어떻게 해결할까?  (0) 2023.02.21
eager 과 lazy loading  (0) 2023.02.21
IoC 와 DI  (0) 2023.02.20