ExecutorService 인터페이스
비동기적으로 메서드을 실행시켜 다중 스레드 환경에서 안전하게 작업을 처리,
스레드 간의 작업 분배 및 관리를 담당
submit(Runnable task)
submit(Callable task)Executors
ExecutorService 인터페이스의 구현체를 생성하는 유틸리티 클래스
@Async
설정 메서드를 별도의 스레드에서 실행시켜 기존 트랜잭션이 해당 메서드를 기다리지 않고 코드를 실행할 수 있게 함. 즉 비동기 메서드가 된다.
@EnableAsync
사용 영역을 먼저
@EnableAsync로 지정해야 한다
1. 메인 클래스에 적용(애플리케이션 전체)
2. 특정 클래스나 빈에 적용
회원 등록과 이메일 전송에 대한 트랜잭션 처리
회원 가입을 위한 이메일 전송 실패시 일반적인 처리
(1) 저장된 회원 정보 보관
(2) 저장된 회원 정보 삭제(rollback)또는 ‘미완료’ 상태로 유지
(3) 저장된 회원 정보 보관 및 회원 가입 메시지를 추가 전송
구현 해야할 처리는 (2)번이다
createMember()메서드에@Transactiona설정한 후executorService.submit삭제하여sendEmail()실행,sendEmail()가 기존 트랜잭션에 합류후 예외발생시 자동 롤백
executorService.submit() 를 삭제해도 되는가?
삭제하지 말고 퍼블리셔 -> 리스너를 통한 이벤트 핸들러 클래스를 따로 만들자
MemberEvent
이벤트 객체를 생성할 클래스
이벤트 소스(여기서는 save의 리턴값)를 받는다
EventListener
이벤트 발행시 반응할 이벤트 핸들러이다
`sendEmail()` 메서드 실행 로직을 이쪽으로 옮겨 담았다
createMember
ApplicationEventPublisher 객체 생성,
MemberEvent 객체 생성,
publishEvent(memberEvent) 실행하여 이벤트를 발행한다
createMember()를 이벤트 처리해서 퍼블리셔, 리스너의 이벤트 핸들러 처리
핸들러 처리에서executorService.submit()로 새로운 스레드 진입하여sendEmail()실행,catch부분 보완하여 수동으로 삭제처리
트랜잭션 실패로 인한 자동 롤백이 아닌 수동으로 삭제처리 해도 되는가?
sendEmail()메서드에@Transactional(Propagation.REQUIRED)를 달면
기존createMember()트랜잭션에 합류하지 않을까? -> 실패퍼블리셔가 되어도 스레드가 유지되나,
executorService.submit()되는 순간 다른 스레드가 되어 기존createMember()에 영향을 끼칠수 없음.

5.405
7.438 - 첫 실행에서 포스트맨 자체에 지연이 된 것 같다sendEmail()메서드는 5초의 지연시간이 포함되어 있다
전체 코드의 실행시간에는 거의 차이가 없지만
createMember()의 종료 시점이 달라진다
사진 상의 publishEvent 종료 메세지 출력 후 바로 종료됨)
결과적으로 포스트맨 클라이언트 쪽에서 실행시 sendEmail()메서드를 기다릴 필요가 없어
응답받는 시간이 단축된다
동기(기본)
publishEvent 실행 -> sendEmail 실행/종료 -> publishEvent 종료(응답*)
스택 형식으로 순차진행
비동기
publishEvent 실행 -> publishEvent 종료(응답*)
ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤsendEmail 실행(비동기) -> sendEmail 진행/종료
메서드의 역할 완수 시점에 주의하자