스프링 MVC - 트랜잭션 처리

ehdrms2034·2020년 8월 25일
0

본 글은 스프링 MVC에 대해 지식을 정리하고 나중에 헷갈릴 때 다시 보기 위한 글입니다 👀

본 게시글은 Spring MVC Quick Start를 참조하여 정리한 글입니다. 📖 👀

본 게시글은 Spring MVC Documentation를 참조하여 정리한 글입니다 📚 👀

스프링에서 트랜잭션을 처리하는 방법을 2가지 제공해준다.

  • 선언적 트랜잭션 처리
  • 어노테이션 트랜잭션 처리

이번 장에는 선언적 트랜잭션 처리에 대해서 서술하고 스프링 부트에 대해 혹은 Spring JPA에 대해 따로 서술하게 될 때 어노테이션 트랜잭션 처리에 대해 글을 포스팅 하겠습니다 👍

스프링에서 트랜잭션 처리를 컨테이너가 자동으로 처리하도록 설정할 수 있는데 이를 선언적 트랜잭션이라고 한다.

스프링의 트랜잭션 설정에서는 앞에서 서술한 AOP가 사용된다. 또한 선언적 트랜잭션 처리는 어노테이션 트랜잭션 처리와는 다르게 xml에서만 사용할 수 있는 기능이다.

또한 <aop:aspect> 를 사용하는 것이 아니라, <aop:advisor> 를 통해서 한 번에 트랜잭션에 관련되어 처리를 해야 된다고, 앞 서 AOP를 설명할 때 언급해뒀던 것 같다.

트랜잭션 네임스페이스 설정

스프링에서는 트랜잭션관련 설정을 앞에서 살펴본 AOP로 처리한다구 했다.
언제나 그랬듯이 applicationContext.xml에서 특정기능을 사용하기 위해서 네임스페이스를 설정해줘야하는데, tx관련 네임스페이스 또한 예외는 아니다. 추가해주자

  • applicationContext.xml
<beans xmlns:aop="http://www.sprirngframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/spring-tx-4.2.xsd"
       >

  <!-- 내용들 -->
</beans>

트랜잭션 관리자 등록

트랜잭션 관련 설정에서 가장 먼저 등록하는 것은 트랜잭션 관리자 클래스이다.
스프링은 다양한 트랜잭션 관리자를 지원하는데, 어떤 기술을 이용하여 데이터베이스 연동을 처리했느냐에 따라 트랜잭션 관리자가 달라진다. 또한 모든 트랜잭션 관리자는 PlatformTransactionManager인터페이스를 구현한 클래스들이다.

  • PlatformTransactionManager.java
public interface PlatformTransactionManager{
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TrnasactionStatus status) throws TransactionException;
}

잘보면 트랜잭션에 필요한 commit 과 rollback 메소드를 가지고 있는 것을 알 수 있다.
또한 우리는 위 인터페이스를 구현한 DataSourceTransactionManager를 통해서 트랜잭션을 처리할 것이다. 왜냐하면 앞에 언급한 것은 JDBC를 기반으로 설명을 했기 때문이다.

만약에 JPA를 이용하여 트랜잭션을 처리하고 싶다면 JPATransactionManager를 등록하면 쉽게 처리할 수 있다.

아무튼 각설하고 트랜잭션 관리자 등록을 위해 DataSourceTransactionManager 클래스를 <bean>으로 등록한다.

  • applicationContext.xml
<!-- 이전에 설정했던 DataSource Bean 그대로다가 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
      destory-method="close">
  <property name="driverClassName" value="org.h2.Driver"/>
  <property name="url" value="jdbc:h2:tcp://localhost/~/test"/>
  <property name="username" value="sa"/>
  <property name="password" value=""/>
</bean>

<bean id="txManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>

이전에 설정했던 dataSource를 txManager의 setProperty로 할당해주어 bean으로 등록한 모습이다.

이제 트랜잭션 관리자 설정을 완료했고 트랜잭션 어드바이스를 설정하여, 트랜잭션할 메소드를 한정한다.

트랜잭션 어드바이스 설정

트랜잭션 관리 기능 어드바이스는 <tx:advice> 엘리먼트를 사용하여 설정한다. 앞에서 트랜잭션 설정을 위한 tx 네임스페이스를 추가했으므로, 다음과 같이 applicationContext.xml에 <tx:advice> 엘리먼트를 이용하여 트랜잭션 관리 어드바이스를 설정한다.

  • applicationContext.xml
<tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
    <tx:method name="get*" read-only="true"/>
    <tx:method name="*"/>
  </tx:attributes>
</tx:advice>

위 설정은 get으로 시작하는 모든 메소드는 readOnly 즉 읽기 전용으로 처리해서 트랜잭션 관리 대상에서 제외하고, 나머지 메소드들은 트랜잭션 관리에 포함할 것이라 설정한 것이다.

위처럼 <tx:method>가 가질 수 있는 속성은 다음과 같다.

|속성|의미|
|--|--|
|name|트랜잭션이 적용될 메소드 이름 지정|
|read-only|읽기 전용 여부 지정(Default : false)|
|no-rollback-for| 트랜잭션을 롤백하지 않을 예외 지정|
|rollback-for| 트랜잭션을 롤백할 예외 지정|

AOP 설정을 통한 트랜잭션 설정

이제 트랜잭션을 어떻게 처리하겠다는 Guideline도 txAdivce를 통해서 지정했으니 어떤 메소드에 대해 트랜잭션을 적용해야 할지에 대해 설정하겠다.

  • applicationContext.xml
<tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
    <tx:method name="get*" read-only="true"/>
    <tx:method name="*"/>
  </tx:attributes>
</tx:advice>

<aop:config>
  <aop:pointcut id="txPointcut"
                expression="execution (* com.x.y.z..*(..))"/>
  <aop:advisor pointcut-ref="txPointcut" advice-ref="txAdvice"/>
</aop:config>

생각보다 간단히 끝이 났다.
주의할 것은 aspect로 처리하는 것이 아니라 advisor 로 트랜잭션 어드바이스를 처리해야 된다는 점.

끝!

다음은 Spring MVC가 어떻게 동작하는지, Servlet의 무엇이고 DispatcherServlet은 어떤 역할을 하는지 포스팅 할 것 같다!

profile
수동적인 과신과 행운이 아닌, 능동적인 노력과 치열함

0개의 댓글