[java] Guice의 트랜잭션 관리

Guice는 Java의 의존성 주입(Dependency Injection) 프레임워크로, 애플리케이션의 객체 간의 의존성을 관리하는 데 사용됩니다. 트랜잭션은 데이터베이스 작업이나 다른 리소스 관리에 필수적인 기능 중 하나입니다. Guice에서 트랜잭션을 관리하는 방법에 대해 알아보겠습니다.

1. Guice의 주요 기능

Guice는 다음과 같은 주요 기능을 제공합니다:

2. Guice에서의 트랜잭션 관리

Guice는 트랜잭션 관리를 위해 AOP(Aspect-Oriented Programming) 라이브러리인 aopalliance을 사용합니다. Guice의 Transactional 어노테이션을 사용하여 트랜잭션을 적용할 수 있습니다.

import com.google.inject.persist.Transactional;

@Transactional
public void doTransactionalOperation() {
    // 트랜잭션 내에서 수행할 작업
}

@Transactional 어노테이션을 메소드 레벨에 적용하면 해당 메소드가 트랜잭션 내에서 실행되도록 보장합니다. Guice는 트랜잭션을 시작하고, 메소드 실행을 감지하여 커밋 또는 롤백합니다.

위의 예제에서 Transactional 어노테이션은 Guice의 persist 모듈과 함께 사용되었습니다. 이 모듈은 Java Persistence API(JPA)를 지원하며, 트랜잭션 관리를 위해 javax.persistence 패키지의 어노테이션과 함께 사용됩니다.

3. 트랜잭션 경계 정의하기

Guice를 사용하여 트랜잭션을 관리할 때, 트랜잭션의 경계(트랜잭션의 시작과 종료)를 정의해야 합니다. 이를 위해 Guice는 TransactionalMethodInterceptor 클래스를 제공합니다.

import com.google.inject.persist.TransactionalMethodInterceptor;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

public class TransactionalInterceptor implements MethodInterceptor {
    private final EntityManager entityManager;

    public TransactionalInterceptor(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        try {
            Object result = invocation.proceed();
            transaction.commit();
            return result;
        } catch (Exception e) {
            transaction.rollback();
            throw e;
        }
    }
}

위의 코드에서 TransactionalInterceptor 클래스는 MethodInterceptor 인터페이스를 구현하며, invoke 메소드 내에서 트랜잭션 경계를 정의합니다. EntityManager를 사용하여 실제로 트랜잭션을 관리하며, 예외가 발생한 경우 롤백합니다.

TransactionalMethodInterceptor 클래스를 사용하려면 Guice 모듈에서 해당 인터셉터를 등록해야 합니다.

import com.google.inject.AbstractModule;
import com.google.inject.persist.PersistService;
import com.google.inject.persist.TransactionalMethodInterceptor;

public class MyModule extends AbstractModule {
    @Override
    protected void configure() {
        bindInterceptor(Matchers.any(), Matchers.annotatedWith(Transactional.class),
                new TransactionalMethodInterceptor(persistService.get()));
    }
}

위의 예제에서 TransactionalMethodInterceptor를 생성할 때 PersistService를 사용합니다. 이는 Guice의 persist 모듈을 사용하여 JPA를 구성하는 데 필요한 클래스입니다.

Guice에서 트랜잭션을 관리하는 방법을 알아보았습니다. 트랜잭션을 적용하여 데이터베이스 작업을 안정적으로 수행하고, 에러 발생 시 롤백할 수 있습니다. Guice의 트랜잭션 관리 기능을 사용하면 코드의 가독성과 유지보수성을 향상시킬 수 있습니다.

참고 자료