Java2EE Framework/Spring 2.0

스프링 2.0의 트랜잭션 처리 방법

본클라쓰 2010. 6. 7. 13:17

 JDBC를 기반으로 트랜잭션을 처리하는 일반적인 방법은 퍼시스턴스 계층에서 처리하는 방법과 비즈니스 계층에서 처리하는 두 가지 방법이 있다. JDBC를 사용한 트랜잭션 처리는 사용하기 쉽지만 많은 단점을 가지고 있는데 JDBC를 사용한 각각의 트랜잭션 처리 방법에 대해 알아보고 장단점을 파악해 보자.

 

 

1. 퍼시스턴스 계층에서 트랜잭션 처리 방법(컨넥션을 공유해 트랜잭션 처리)

 

conn = getConnection();

 

try {

    conn.setAutoCommit(false);

 

    doSomething1();
    doSomething2();
    doSomething3();

 

    conn.commit();

 

} catch(Exception) {

 

    conn.rollback();

 

} finally {

 

    conn.setAutoCommit(true);

}

 

 이렇게 퍼시스턴스 계층에서 트랜잭션을 구현하게 되면 비즈니스 계층에 구현되어야 할 비즈니스 로직이 퍼시스턴스 계층에 구현되는 현상이 발생한다. 또한, 비즈니스 로직이 복잡하지 않은 경우 퍼시스턴스 계층에 구현하더라도 큰 문제가 없지만, 복잡한 경우 퍼시스턴스 계층에 비즈니스 로직과 퍼시스턴스 구현 로직이 모두 포함되기 때문에 소스코드가 복잡해질 수 밖에 없다. 이로 인해 유지보수가 어려워 진다.

 

 또한, 퍼시스턴스 계층에서 Connection 인스턴스를 인자로 사용해 트랜잭션을 처리할 때는 트랜잭션용 메소드와 그냥 메소드등 통일성 없는 메소드들이 다수 존재하게 된다. 이와 같이 구현될 경우 메소드 호출에 대한 일관성이 없이지기 때문에 퍼시스턴스 계층을 재사용하기 힘들어 진다.

 

 이는 비즈니스 로직이 비즈니스 계층과 퍼시스턴스 계층에 분산되어 구현되기 때문에 비즈니스 계층을 재사용하기 힘들 뿐 아니라 유지보수도 어렵게 된다. 하지만 복잡한 비즈니스 로직을 포함하지 않는 경우 퍼시스턴스 계층에서 트랜잭션을 처리하는 방법도 좋은 선택이다. 그러나 비즈니스 로직이 복잡하고 애플리케이션의 규모가 큰 경우 적합하지 않다.

 

 

2. 비즈니스 계층에서 트랜잭션 처리

 

 비즈니스 계층에서 트랜잭션 처리를 담당하게 될 경우 Connection 객체를 생성, 트랜잭션 처리, 컨넥션 반환과 관련한 모든 작업을 비즈니스 계층이 담당하게 된다.

 

conn = getConnection();

 

try {

    conn.setAutoCommit(false);

 

    some1Dao.execute(conn);
    some2Dao.execute(conn);
    some3Dao.execute(conn);

 

    conn.commit();

 

} catch(Exception e) {

 

    conn.rollback();

 

} finally {

    conn.setAutoCommit(true); 

}

 

 

 비즈니스 계층에서 컨넥션에 대한 관리를 전담하고 있기 때문에 퍼시스턴스 계층의 모든 메소드는 인자로 Connection 인스턴스를 전달받아야 한다. 트랜잭션 처리를 비즈니스 계층에서 담당할 경우 장점은 비즈니스 계층에 모든 비즈니스 로직을 구현하는 것이 가능한 점이다.

 

 비즈니스 계층과 퍼시스턴스 계층을 독립적으로 구현하는 것이 가능하므로 각 계층의 재사용성이 높아진다. 이는 비즈니스 계층에 트랜잭션을 처리할 경우 기본 아키텍처 구조로 애플리케이션을 개발하는 것이 가능해 진다.

 

 그러나 비즈니스 계층에서 비즈니스 로직과 트랜잭션 처리 로직을 같이 구현해야 하고, 컨넥션에 해당하는 try~catch문이 포함되기 때문에 비즈니스 로직의 코드가 복잡해진다. 따라서 비즈니스 계층의 유지 보수성을 저하시킨다는 단점이 있다. 또한, 퍼시스턴스 계층에서 사용하기 위한 공통 모듈을 개발할 때도 이렇게 분리되지 않은 계층의 공통 모듈의 개발은 어렵다.

 

 애플리케이션을 개발할 때 가장 큰 골치거리 중 하나가 트랜잭션을 어디서 처리할 것인지 결정하는 것이다. 프로젝트를 시작하는 시점에 트랜잭션 처리에 대한 기준이 없는 경우 개발자들의 성향에 따라 트랜잭션을 구현하는 경우를 종종 본다.

 

 이와 같이 기준 없이 개발된 애플리케이션을 유지보수해야 하는 상황이 발생하면 끔찍하지 않을 수 없다. 컨넥션 객체는 애플리케이션 전 계층에서 일관성 없이 관리되고, 트랜잭션 또한 일관성 없이 처리되고 있기 때문에 문제가 발생할 경우 문제의 원인을 찾고 해결하는데 상당히 많은 시간을 필요로 하게 된다.

 

 하지만 이 두 방법 중 어떤 것을 선택하는 것이 좋은가에 대한 답은 비즈니스 계층에 트랜잭션을 처리하는 것이 좋다. 하나의 유즈케이스에 해당하는 업무를 처리하는 단위는 비즈니스 계층에서 담당하고 있다. 각 유즈케이스에 해당하는 업무들은 비즈니스 계층의 각 메소드 내에서 하나의 업무 단위로 구현하게 된다. 그러므로 트랜잭션 처리는 비즈니스 계층의 메소드 단위별로 처리하는 것이 맞다.