Spring/JPA

태태개발일지 - 비동기처리

태태코 2024. 12. 11. 14:19
반응형

동기

작업이 순차적으로 실행된다. 하나의 작업이 끝나야 다음 작업을 진행할 수 있다.

 

public void syncExample() {
    System.out.println("파일 다운로드 시작");
    downloadFile(); // 파일 다운로드가 끝날 때까지 대기
    System.out.println("파일 다운로드 완료");
}

public void downloadFile() {
    try {
        Thread.sleep(3000); // 3초 동안 대기 (파일 다운로드 시뮬레이션)
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

 

파일 다운로드가 끝날 때 까지 기다렸다가 아래의 다운로드 완료를 찍는다.

 

비동기 

전 동작고 관계없이 기다리지 않고 바로 실행한다.

@Service
public class AsyncService {
    @Async
    public void asyncMethod() {
        System.out.println("비동기 메서드 실행: " + Thread.currentThread().getName());
    }
}

@RestController
@RequestMapping("/example")
public class ExampleController {
    private final AsyncService asyncService;

    public ExampleController(AsyncService asyncService) {
        this.asyncService = asyncService;
    }

    @GetMapping("/test")
    public String testAsync() {
        System.out.println("컨트롤러 실행: " + Thread.currentThread().getName());
        asyncService.asyncMethod(); // 별도의 스레드에서 실행
        return "요청 완료";
    }
}

 

@Async 이라는 어노테이션을 붙이게 된다면, 이 메서드는 비동기로 처리되어 앞단의 메서드를 기다리지 않고 실행하게 된다.

 

 

너무 간단한 내용이지만 블로그에 작성한 이유가있다.

 

만약 같은 클래스 내에서 @Async가 붙은 메서드를 사용한다면????

 

@Service
public class TransactionService {
    @Transactional
    public void parentTransaction() {
        System.out.println("부모 트랜잭션 시작");
        childTransaction();
    }

    @Async
    @Transactional
    public void childTransaction() {
        System.out.println("자식 트랜잭션 실행 (별도 스레드): " + Thread.currentThread().getName());
    }
}

 

 

결과: 결과부터 말하자면, 비동기처리되지않고, 동기처리된다. 

 

 

*여기에는 이유가있다 *

spring은 트랜잭션과 동기/비동기 처리를 프록시를 사용하여 처리한다. 하지만 같은 클래스 내에서 메서드로 호출할 경우, 이를 외부호출이 아닌 자기 호출로 판단하여, 프록시를 사용하지 않기 때문에 비동기처리가 무효화되고, 동기적으로 처리되는 것이다. 이는 앞서 트랜잭션에 관련하여 블로깅한 내용과 동일하다

 

.

프록시에 역할에 대해서 간단하게 설명해보자면.

 

  • 프록시는 실제 빈(Bean)을 감싸는 래퍼 객체다.
  • 외부에서 해당 빈의 메서드를 호출하면, 호출은 먼저 프록시를 거친다.
  • 프록시는 호출을 가로채어 필요한 추가 작업(트랜잭션 처리, 비동기 실행 등)을 수행한 뒤 실제 메서드를 호출한다.

 

즉:

Java에서 같은 객체의 메서드를 호출하면, 이는 this 참조를 사용한 직접 호출로 처리된다.
Spring이 프록시를 사용하는 방식은 외부 호출만 가로채는 방식으로 설계되어 있기 때문에 같은 클래스 내의 트랜잭션과 동기/비동기 처리는 먹히지 않을 수 있다.

 

 

반응형

'Spring > JPA' 카테고리의 다른 글

태태코딩 - 영속성 컨텍스트  (0) 2024.12.21
태태개발일지 - 트랜잭션?  (0) 2024.12.03
태태개발일지 - JPA PK Key  (0) 2024.12.03
태태개발일지 - 양방향 연관관계  (1) 2024.11.22
태태개발일지 - JPA 슈퍼타입  (1) 2024.11.20