PR CENTER

뉴스룸     |     료실

mobile background

PR CENTER

Spring 트랜잭션 관리 : AOP, Proxy객체 & @Transactional

관리자
2025-01-13
조회수 295

□ AOP(Aspect Oriented Programming) 란?

    - 프로그램의 핵심 로직과 공통으로 사용되는 부가 로직을 분리하여 관리하는 프로그래밍 기법이다.

    - Spring에서 특정 로직(예: 트랜잭션 관리, 로깅, 보안 등)을 메소드 실행 전후에 자동으로 추가한다.

       ; 특정 지점(Join Point)에서 실행될 코드를 정의(Advice)하고, 어떤 지점에서 실행될지를 설정하는 규칙(Pointcut)을 사용

       ; 예를 들어, 트랜잭션 관리, 로깅, 보안 로직을 서비스 메소드 실행 전후로 분리하여 코드 중복을 줄이고 유지보수를 쉽게 한다.


□ Proxy 객체 란?

    - 실제 객체(원본 객체)에 대한 대리자 역할을 하는 객체로, 호출을 가로채거나 동작을 추가하는 데 사용

 

  • Proxy 객체는 AOP를 구현하는데 사용되는 핵심 도구이다.
  • Proxy는 외부 호출 시 동작하도록 설계되어 있다.
  • AOP에서 Proxy 객체는 메소드 호출을 가로채고 부가 로직(Advice)을 실행하는 도구
  • Spring AOP는 주로 JDK 동적 Proxy (인터페이스 기반)와 CGLIB 프록시 (클래스 기반)를 사용


□ Proxy 객체 생성과 동작

    1. Proxy 객체 생성

       a. 빈 후처리 단계에서 AOP 적용 여부를 판별한다

       b. 해당 클래스에 AOP Advice가 적용될 가능성이 있다면 Proxy 객체가 생성된다

           즉, 서비스에 일부 메소드만 Transactional이 걸려 있어도 Proxy가 생성됨


          ◆ Advice : Rollback / Commit 기능 담당

               - AOP에서 특정 시점에서 실행되는 부가 로직을 의미

               - ‘@Transactional’ Annotation이 선언된 method 또는 class에 대해 트랜잭션 처리와 관련된 부가 로직을 적용하는 AOP 기능


       c. Proxy 객체는 Spring Bean으로 등록된다


    2. Proxy 객체 주입

        - Controller 등에 주입 받을 때는 이미 “Proxy인지 원본인지” 정해진 객체가 와 있다


    3. Proxy 객체 동작 : CglibAopProxy.class 참고

        - 가로챈 요청의 Bean 객체를 감싸며 동작한다

        - ‘@Transactional’이 적용된 메서드는 Advice가 적용되고, 아니면 원본 메소드를 호출한다.


           ◆ Bean 後 처리 : Bean을 초기화하기 전후에 커스터마이징 할 수 있는 메커니즘으로, AOP 프록시 객체 생성, 의존성 주입 후 작업 등이 

                                         이루어진다


□ @Transactional 이란?

    - `@Transactional`은 Spring에서 Transaction을 관리하기 위해 사용하는 Annotation이다.

        이 Annotation은 Database 작업 중 오류가 발생했을 때, 작업 내역을 자동으로 Rollback/Commit하는 데 사용된다.


□ @Transactional 과 Proxy 객체의 관계

    - ‘@Transactional’ 은 Proxy 객체의 AOP 기능을 통해 작동한다.

    - Spring이 생성하는 Proxy 객체는 트랜잭션 관리를 담당하는 코드가 포함되어 있다

    - 이 Proxy는 트랜잭션 처리 외에도 Spring AOP의 다른 부가 기능(로깅, 보안 등)을 처리할 수 있다.


□ @Transactional 과 접근 제한자


    ▷ 접근 제한자와 AOP 적용

         - Proxy는 외부 호출 시 동작하도록 설계되어 있기 때문에, 내부 호출은 Proxy를 거치지 않음으로 AOP가 적용되지 않는다.


         - `@Transactional` + `public` : 외부 호출일 경우에만 트랜잭션 적용. 내부에서 호출 시 적용되지 않음

         - `@Transactional` + `private` : 프록시를 거치지 않아 트랜잭션이 적용되지 않음

              ■ 해결 방법 : 자기 참조 방식으로 호출하거나, 별도의 클래스로 분리해야 한다.

                  - 자기 참조 방식은 추천하지 않는다! (`this.methodB()` → `otherService.methodB()` )

                  - 내부 메소드 호출에서도 AOP를 적용하려면 해당 메소드를 다른 서비스(Bean)에서 호출하거나, 설계를 재구성해야 한다.

 

              ■ 예시

                  Q. 최상위 서비스 메소드에서 호출되는 여러 개의 하위 메소드가 있을 때, 그 중 일부에만 롤백 처리가 필요하다면?

                   A. 롤백 처리가 필요한 메소드만 다른 서비스/클래스로 분리해서 `@Transactional` + `public` 을 건다.

 

    - 사용 예시

```java

        public class MainService {

                   ...

                   public void test1() {

                             subService.nonTransactional();     

                   }

                   public void test2() {

                             subService.transactional();

                   }

                   public void test3() {

                     subService.callPrivateTransactional();

                   }

         }      

        public class SubService {

                   public void nonTransactional(){

                             transactional();

                  }

         

                  @Transactional

                  public void transactional() {

                            privateMethod();

                  }

         

                  @Transactional

                  public void callPrivateTransactional() {

                            privateTransactional();

                  }

    

                  private void privateMethod(){

                  }

         

                  @Transactional(propagation = Propagation.NEW)

                  private void privateTransactional(){

                  }

         }

        ```



메소드 
호출
트랜잭션 
적용 여부
특징
test1()
없음

test2()
적용
`privateMethod` 은 트랜잭션 일부로 포함
test3()
적용
`privateTransactional()`은 직접 호출되므로 AOP 적용 안 됨


         - Spring 6.0 부터는 protected와 default 메서드에도 @Transactional 이 적용되도록 바뀜


□ @Transactional 과 예외 처리

    - ‘@Transactional’은 예외가 메서드 경계를 벗어나 전파될 때만 Transaction을 롤백 상태로 만든다

   

    ▷ 롤백 대상인 예외

         - 추가적인 설정 없이 롤백 되는 예외는 ‘Error’, `RuntimeException`(Exception>Unchecked) 이다.

            ; `rollbackFor=RuntimeException.class` → 불필요


    ▷ 롤백 대상이 아닌 예외

         - `CheckedException`, `UncheckedException` (런타임예외 제외)는 예외 발생 시 롤백 되지 않는다.

            ; rollbackFor 설정을 통해 롤백 대상에 추가할 수 있다.


▷ 예시

```java

    public class ParentService {

       ...

       @Transactional(nonRollbackFor=RuntimeException.class, rollbackFor=IOExcpetion.class)

       public void test(){

                 childService.runtimeRollback();

                 childService.checkedRollback();

       }

    }

   

    public class ChildService {

       ...

      

       public void runtimeRollback() {

                 // ...

                 throw new RuntimeException("롤백 대상이 아니라고!");

       }

      

       public void checkedRollback() throws IOException {

                 try {

                            ...

                 } catch (IOException e){

                            throw e;

                 }

        }

     }

    ```



         - ‘RuntimeException’ 발생시 상위 메소드로 예외는 전파되지만, 트랜잭션은 롤백되지 않고 커밋된다.

         - ‘IOException’ 발생시 rollbackFor 설정에 의해 롤백된다.


                                                                                                                                                                                            


                                                                                                                                                                                                        ⭐ 발표자 : 이현진님

2 0

페이지 바로가기

@2024 K2SYSTEMS. All rights reserved.

HOME       |       ABOUT US       |       SOLUTION       |       PR CENTER       |       CONTACT       |       인재채용       |       kakao i cloud 고객센터  

@2024 K2SYSTEMS. All rights reserved.