본문 바로가기
개발 방법론

데이터베이스 트랜잭션이 둘 이상의 애그리거트 인스턴스를 수정하지 못하게 하라!

by 시니성 2023. 11. 12.

Domain-Driven Design(DDD)의 중요한 원칙 중 하나인 "데이터베이스 트랜잭션이 애그리게이트의 둘 이상의 인스턴스를 수정하지 못하게 하라"에 대해 설명하겠습니다. 이 원칙은 애그리게이트의 일관성과 경계를 유지하는 데 중요한 역할을 합니다.

애그리게이트란 무엇인가?

DDD에서 애그리게이트는 관련된 객체의 클러스터로, 일관된 변경을 보장하는 역할을 합니다. 각 애그리게이트는 단일 루트 엔티티를 갖고, 이 루트 엔티티를 통해서만 애그리게이트 내의 다른 객체들과 상호작용할 수 있습니다. 이런 구조는 애그리게이트의 내부 상태를 외부로부터 보호하고, 복잡성을 관리하는 데 도움이 됩니다.

원칙의 중요성

이 원칙은 각 애그리게이트가 자체적으로 일관성을 유지할 수 있도록 보장합니다. 둘 이상의 애그리게이트 인스턴스를 하나의 트랜잭션에서 수정하면, 일관성이 깨질 위험이 있습니다. 예를 들어, 한 트랜잭션에서 두 개의 애그리게이트를 수정할 때, 하나는 성공하고 다른 하나는 실패하면 데이터 일관성이 손상될 수 있습니다.

예시코드: 잘 적용된 시나리오

가상의 시나리오로, 사용자의 계정 정보를 관리하는 애그리게이트와 주문 정보를 관리하는 애그리게이트를 가정해보겠습니다.

// 사용자 계정 애그리게이트
class UserAccount {
    fun updateAccountDetails(details: AccountDetails) {
        // 계정 정보 업데이트 로직
    }
}

// 주문 애그리게이트
class Order {
    fun updateOrderStatus(status: OrderStatus) {
        // 주문 상태 업데이트 로직
    }
}

// 서비스 레이어
class UserService {
    fun updateUserAccount(userId: String, details: AccountDetails) {
        val account = accountRepository.findById(userId)
        account.updateAccountDetails(details)
        accountRepository.save(account)
    }
}

class OrderService {
    fun updateOrderStatus(orderId: String, status: OrderStatus) {
        val order = orderRepository.findById(orderId)
        order.updateOrderStatus(status)
        orderRepository.save(order)
    }
}

여기서 각 서비스는 하나의 애그리게이트만을 다루며, 각각의 작업은 별도의 트랜잭션으로 처리됩니다.

예시코드: 잘못 적용된 시나리오

// 잘못된 서비스 레이어
class BadService {
    fun updateUserAndOrder(userId: String, orderId: String, details: AccountDetails, status: OrderStatus) {
        val account = accountRepository.findById(userId)
        val order = orderRepository.findById(orderId)

        account.updateAccountDetails(details)
        order.updateOrderStatus(status)

        accountRepository.save(account)
        orderRepository.save(order)
    }
}

이 예에서 BadService는 하나의 트랜잭션에서 두 개의 서로 다른 애그리게이트를 수정합니다. 이는 DDD의 원칙을 위반하며, 데이터 일관성 문제를 일으킬 수 있습니다.

분석

잘 적용된 시나리오에서는 각 애그리게이트의 변경이 독립적으로 수행되어, 데이터의 일관성과 무결성이 보장됩니다. 반면, 잘못

적용된 시나리오에서는 여러 애그리게이트의 변경이 하나의 트랜잭션 내에서 이루어지기 때문에, 한 쪽의 실패가 전체 트랜잭션의 실패를 초래하고 데이터 무결성을 위협할 수 있습니다. 이를 통해 DDD에서 강조하는 각 애그리게이트의 독립성과 일관성 경계의 중요성을 이해할 수 있습니다.