๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
BackEnd๐ŸŒฑ/Spring

์Šคํ”„๋ง ์ด๋ฒคํŠธ ๋ฐœํ–‰๊ณผ ๊ตฌ๋…์œผ๋กœ ํŠธ๋žœ์žญ์…˜ ๋ถ„๋ฆฌํ•˜๊ธฐ

by dkswnkk 2023. 7. 9.

์„œ๋ก 

์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๋‹ค ๋ณด๋ฉด ๋‹ค์–‘ํ•œ ์™ธ๋ถ€ ๋ชจ๋“ˆ์ด๋‚˜ ์‹œ์Šคํ…œ์„ ์—ฐ๋™ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ์ƒ๊ธฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์„ ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํšŒ์›๊ฐ€์ž… ์‹œ ๋ฉ”์ผ์„ ์ „์†กํ•˜๋Š” ์˜ˆ์‹œ

์ฝ”๋“œ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class UserService {

    private final MessageService messageService;
    private final UserRepository userRepository;


    @Transactional
    public void signUp(String email) {
        // ์œ ์ € ์ €์žฅ
        userRepository.save(new User(email));
        // ๋ฉ”์„ธ์ง€ ๋ฐœ์†ก(์•Œ๋ฆผ, ๋ฉ”์„ธ์ง€ ๋“ฑ ์™ธ๋ถ€ API ์ˆ˜ํ–‰)
        messageService.send(email);
    }
}
@Service
@RequiredArgsConstructor
public class MessageService {

    /**
     * ๋ฉ”์ผ ์ „์†ก ๋กœ์ง
     * (์‹ค์ œ๋กœ๋Š” ์™ธ๋ถ€ ๋ชจ๋“ˆ์ด ๋“ค์–ด๊ฐ)
     */
    @Async
    public void send(String email) {
        System.out.println(email + "์—๊ฒŒ ์ „์†ก ์™„๋ฃŒ");
    }
}

์œ ์ €๋ฅผ ์ €์žฅํ•˜๊ณ , ํ•ด๋‹น ์œ ์ €์˜ ์ด๋ฉ”์ผ๋กœ ๊ฐ€์ž… ์ถ•ํ•˜ ๋ฉ”์ผ์„ ๋ณด๋‚ด๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. 

 

๋ฌธ์ œ

๋จผ์ € ํ๋ฆ„์„ ๋ณด๋ฉด "ํšŒ์›๊ฐ€์ž… ์š”์ฒญ -> ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์œ ์ € ์ €์žฅ -> ๊ฐ€์ž… ์ถ•ํ•˜ ๋ฉ”์ผ ๋ฐœ์†ก"์ž…๋‹ˆ๋‹ค. ํฌ๊ฒŒ ๋ฌธ์ œ๊ฐ€ ์—†์–ด ๋ณด์ด์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‘ ๊ฐ€์ง€์˜ ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋กœ์ง๊นŒ์ง€ ํŠธ๋žœ์žญ์…˜์— ๋ฌถ์ธ๋‹ค.
  2. ๋ฌธ์ œ๋กœ ์ธํ•ด ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ์ด ์ผ์–ด๋‚ฌ์„ ๋•Œ, ์œ ์ €๋Š” ์ €์žฅ๋˜์ง€ ์•Š์ง€๋งŒ ๋ฉ”์ผ์€ ์ „์†ก๋œ๋‹ค.

๋ฌธ์ œ๋ฅผ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. ๋ถˆํ•„์š”ํ•œ ๋กœ์ง๊นŒ์ง€ ํŠธ๋žœ์žญ์…˜์— ๋ฌถ์ธ๋‹ค.

๋จผ์ € ํŠธ๋žœ์žญ์…˜์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•œ ์ปค๋„ฅ์…˜์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ปค๋„ฅ์…˜ ์ƒ์„ฑ์„ ์œ„ํ•ด์„œ๋Š” ๊ฝค ๋งŽ์€ ๋น„์šฉ์ด ์†Œ๋ชจ๋˜๋Š”๋ฐ, ์ด๋Ÿฌํ•œ ๋น„์šฉ์„ ์ ˆ์•ฝํ•˜๊ธฐ ์œ„ํ•ด WAS๊ฐ€ ์‹คํ–‰๋  ๋•Œ DB ์—ฐ๊ฒฐ์„ ์œ„ํ•ด ๋ฏธ๋ฆฌ ์ผ์ • ์ˆ˜์˜ ์ปค๋„ฅ์…˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ํ’€์— ๋‹ด์•„๋’€๋‹ค๊ฐ€ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๋ฉด ํ’€์—์„œ ์ƒ์„ฑ๋˜์–ด ์žˆ๋Š” ์ปค๋„ฅ์…˜ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค(์ปค๋„ฅ์…˜ ํ’€์— ๋Œ€ํ•œ ๋” ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด์ „ ๊ธ€์—์„œ ํ™•์ธ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค).

 

์ปค๋„ฅ์…˜ ํ’€์˜ ๊ฐœ์ˆ˜๋Š” ์ œํ•œ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋™์‹œ์— ์ˆ˜๋งŽ์€ ์š”์ฒญ๋“ค์ด ์ปค๋„ฅ์…˜ ํ’€์˜ ๊ฐœ์ˆ˜ ์ด์ƒ์œผ๋กœ ์˜ค๊ฒŒ ๋œ๋‹ค๋ฉด, ์ปค๋„ฅ์…˜์„ ํš๋“ํ•˜์ง€ ๋ชปํ•œ ์š”์ฒญ๋“ค์€ ๋‹ค๋ฅธ ์š”์ฒญ์ด ๋๋‚˜ ์ปค๋„ฅ์…˜์ด ๋ฐ˜๋‚ฉ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋˜๊ณ , ์ด๋กœ ์ธํ•ด ๋ณ‘๋ชฉํ˜„์ƒ ์ฆ‰ ์ง€์—ฐ์ด ์ผ์–ด๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด์ œ ์ด์ „ ์ฝ”๋“œ์—์„œ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๋ถ€๋ถ„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ์˜ ํŠธ๋žœ์žญ์…˜ ํ๋ฆ„

์‹ค์งˆ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํŠธ๋žœ์žญ์…˜์ด ํ•„์š”ํ•œ ๊ฑด ๊ฒ€์€ ํ™”์‚ดํ‘œ์ด์ง€๋งŒ, ์™ธ๋ถ€ API์ธ ํŒŒ๋ž€ ํ™”์‚ดํ‘œ๊นŒ์ง€ ํŠธ๋žœ์žญ์…˜์— ๋ฌถ์—ฌ์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์‹œ๊ฐ„๊นŒ์ง€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋‚ญ๋น„๋˜๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์™ธ๋ถ€ ์„œ๋น„์Šค์˜ ํ˜ธ์ถœ์ด ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ์ง€์—ฐ๋  ๊ฒฝ์šฐ ํŠธ๋žœ์žญ์…˜ ์ž์ฒด๊ฐ€ ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ์ง€์—ฐ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

2. ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์—†๋‹ค.

๊ธฐ์กด์˜ ์˜ˆ์‹œ ์ฝ”๋“œ์— ๋กœ์ง์ด ์ถ”๊ฐ€๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ด…์‹œ๋‹ค.

    @Transactional
    public void signUp(String email) {
        // ์œ ์ € ์ €์žฅ
        userRepository.save(new User(email));
        // ๋ฉ”์„ธ์ง€ ๋ฐœ์†ก(์•Œ๋ฆผ, ๋ฉ”์„ธ์ง€ ๋“ฑ ์™ธ๋ถ€ API ์ˆ˜ํ–‰)
        messageService.send(email);
     	// ๋˜ ๋‹ค๋ฅธ ์–ด๋–ค ์„œ๋น„์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰
        xxxService.execute();
    }

์œ„ ์ฝ”๋“œ์—์„œ ๋˜ ๋‹ค๋ฅธ ์–ด๋–ค ์„œ๋น„์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋‹ค๊ฐ€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฉด ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ์ด ์ผ์–ด๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฉ”์‹œ์ง€ ๋ฐœ์†ก ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์™ธ๋ถ€ ๋ชจ๋“ˆ์ด๊ธฐ ๋•Œ๋ฌธ์— ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ๊ณผ๋Š” ๋ฌด๊ด€ํ•˜๊ฒŒ ์ด๋ฉ”์ผ์„ ์ „์†กํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฒฐ๊ณผ์ ์œผ๋กœ ํšŒ์›๊ฐ€์ž…์ด ์‹คํŒจํ–ˆ์ง€๋งŒ ๊ฐ€์ž…์ถ•ํ•˜ ์ด๋ฉ”์ผ์ด ์ „์†ก๋˜๊ฒŒ ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

ํ•ด๊ฒฐ

ํ•ด๋‹น ๋ฌธ์ œ๋“ค์€ ์Šคํ”„๋ง์—์„œ ์ง€์›ํ•˜๋Š” ApplicationEventPublisher๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

ApplicationEventPublisher๋Š” Spring Framework์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋””์ž์ธ ํŒจํ„ด ์ค‘ ํ•˜๋‚˜์ธ ์˜ต์ €๋ฒ„ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ApplicationEventPublisher๋Š” ์ด๋ฒคํŠธ ๋ฐœํ–‰์ž ์—ญํ• ์„ ํ•˜๋Š”๋ฐ, ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๋ฉด ์ด๋ฒคํŠธ ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•œ ๋ชจ๋“  ๋ฆฌ์Šค๋„ˆ์—๊ฒŒ ํ•ด๋‹น ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๊ณ , ์ด๋ฒคํŠธ์— ๋”ฐ๋ฅธ ์ ์ ˆํ•œ ๋™์ž‘์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

ํ๋ฆ„์„ ์‚ดํŽด๋ณด๋ฉด "ํšŒ์› ๊ฐ€์ž… -> ํšŒ์› ๊ฐ€์ž… ์™„๋ฃŒ ์ด๋ฒคํŠธ ๋ฐœํ–‰ -> ํšŒ์› ๊ฐ€์ž… ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋™์ž‘ -> ๋ฉ”์ผ ์„œ๋น„์Šค ์ˆ˜ํ–‰"์œผ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ํ•œ๋ฒˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

UserService

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class UserService {

    private final ApplicationEventPublisher applicationEventPublisher;
    private final UserRepository userRepository;


    @Transactional
    public void signUp(String email) {
        userRepository.save(new User(email));

        applicationEventPublisher.publishEvent(new MessageEvent(email));
    }
}

๊ธฐ์กด์— UserService์—์„œ MessageService๋ฅผ ์˜์กดํ•˜๊ณ  ์žˆ์—ˆ๋˜ ์ฝ”๋“œ๋ฅผ ApplicationEventPublisher๋ฅผ ์ฃผ์ž…๋ฐ›๋„๋ก ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.

ApplicationEventPublisher์˜ ๊ตฌํ˜„์ฒด๋Š” ์Šคํ”„๋ง์ด ํ•ด์ฃผ๋ฉฐ, ์ด๋ฒคํŠธ ๋ฐœํ–‰์ž๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฆฌ์Šค๋„ˆ๊ฐ€ ๋ˆ„๊ตฌ์ธ์ง€, ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ์•Œ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‹จ์ง€ ์ง€๊ธˆ์ฒ˜๋Ÿผ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๋ฉฐ, ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ๋ฆฌ์Šค๋„ˆ์˜ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค.

MessageEvent

public class MessageEvent {
    private String email;

    public MessageEvent(String email) {
        this.email = email;
    }
}

Spring์—์„œ๋Š” ํŠน์ • ํƒ€์ž…์˜ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋ฉด, ๊ทธ ํƒ€์ž…์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋ฉ”์„œ๋“œ๊ฐ€ ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ด๋ฒคํŠธ์˜ ํƒ€์ž…์ด ๋ฆฌ์Šค๋„ˆ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํŠน์ • ํƒ€์ž…์˜ ์ด๋ฒคํŠธ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ณ , ๊ทธ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ด๋ฒคํŠธ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” MessageEvent๊ฐ€ ํŠน์ • ํƒ€์ž…์˜ ์ด๋ฒคํŠธ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

EventListener

@Component
@RequiredArgsConstructor
public class EventListener {
    private final MessageService messageService;

    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true)
    public void handleAfterCommitEmailSending(MessageEvent messageEvent) {
        messageService.send(messageEvent.getEmail());
    }
}

์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฆฌ์Šค๋„ˆ์˜ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ๋ฐœํ–‰๋œ ์ด๋ฒคํŠธ๋Š” ApplicationContext์—์„œ @EventListener ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ Listener handler๋ฅผ ์ฐพ์•„์„œ ์ธ์ž๋กœ ๋ฐ›์•„๋“ค์—ฌ์ง€๊ณ  ํŠน์ • ๋กœ์ง์ด ์ˆ˜ํ–‰๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ @TransactionalEventListener๋Š” Spring Framework์—์„œ ์ œ๊ณตํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ, ํŠธ๋žœ์žญ์…˜ ๊ฒฝ๊ณ„์—์„œ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ ค๋Š” ๋ฉ”์„œ๋“œ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ด ์–ด๋…ธํ…Œ์ด์…˜์€ ํŠธ๋žœ์žญ์…˜์˜ ์ƒ๋ช… ์ฃผ๊ธฐ(ex: ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹ ๋˜๋Š” ๋กค๋ฐฑ๋œ ํ›„)์— ๋”ฐ๋ผ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

@TransactionalEventListener์˜ ๋Œ€ํ‘œ์ ์ธ ์†์„ฑ์—๋Š” ๋‹ค์Œ์˜ ๋„ค๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. phase
  2. classes
  3. fallbackExecution
  4. condition

phase๋Š” ํŠธ๋žœ์žญ์…˜์˜ ์–ด๋Š ์‹œ์ ์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. TransactionPhase ์—ด๊ฑฐํ˜• ํƒ€์ž…์˜ ๊ฐ’์œผ๋กœ ์„ค์ •๋˜๋ฉฐ, ๋‹ค์Œ ๊ฐ’๋“ค์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • AFTER_COMMIT : default ๊ฐ’์œผ๋กœ์จ, ํŠธ๋žœ์žญ์…˜์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ปค๋ฐ‹๋œ ํ›„์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. 
  • AFTER_ROLLBACK: ํŠธ๋žœ์žญ์…˜์ด ๋กค๋ฐฑ๋œ ํ›„์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • AFTER_COMPLETION: ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹๋˜๊ฑฐ๋‚˜ ๋กค๋ฐฑ๋œ ํ›„์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • BEFORE_COMMIT: ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹๋˜๊ธฐ ์ „์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

fallbackExecution๋Š” ํŠธ๋žœ์žญ์…˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ์—†์„ ๋•Œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ• ์ง€ ๋ง์ง€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. default๋Š” false๋กœ ํŠธ๋žœ์žญ์…˜์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ณณ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ–ˆ์„ ๊ฒฝ์šฐ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. true๋กœ ์„ค์ •ํ•˜๋ฉด ํŠธ๋žœ์žญ์…˜์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋„ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ํŠธ๋žœ์žญ์…˜์ด ์—†์„ ๊ฒฝ์šฐ์—๋Š” phase์†์„ฑ์ด ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.

classes๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ฒ˜๋ฆฌํ•  ์ด๋ฒคํŠธ์˜ ํƒ€์ž…๋“ค์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ์†์„ฑ์„ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์˜ ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ํƒ€์ž…์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

condition์€ SpEL(Spring Expression Language) ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์กฐ๊ฑด์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์†์„ฑ์„ ์ด์šฉํ•˜๋ฉด ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์ด๋ฒคํŠธ๋งŒ์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@TransactionalEventListener ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์  ์ด ํฌ์ŠคํŒ…๋„ ๋„์›€์ด ๋˜๋‹ˆ ํ•œ๋ฒˆ ์ฝ์–ด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

๊ฒฐ๋ก 

์ด๋ฒคํŠธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ฃผ๋œ ์žฅ์ ์€ ๋‹ค์–‘ํ•œ ๋„๋ฉ”์ธ ๊ฐ„ ์˜์กด์„ฑ์„ ๋ถ„๋ฆฌํ•˜๊ณ , ๋Š์Šจํ•œ ๊ฒฐํ•ฉ์„ ํ†ตํ•ด ๋ชจ๋“ˆ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด A ์„œ๋น„์Šค๋Š” B์„œ๋น„์Šค์— ๋Œ€ํ•ด ์ „ํ˜€ ์•Œ์ง€ ๋ชปํ•ด๋„ B์„œ๋น„์Šค์˜ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ์„œ๋น„์Šค๋Š” ๋…๋ฆฝ์ ์œผ๋กœ  ์šด์˜๋˜๊ณ  ์ˆ˜์ •๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์„œ๋น„์Šค ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์•„์ง‘๋‹ˆ๋‹ค. 

์ด๋ฒคํŠธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๋‹จ์ ์€ ์ด๋ฒคํŠธ๋ฅผ ์ •์˜ํ•˜๊ณ , ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” ๋“ฑ์˜ ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‹œ์Šคํ…œ์˜ ์ „๋ฐ•์ ์ธ ํ๋ฆ„์„ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋˜์–ด ๋””๋ฒ„๊น…๊ณผ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ์‹คํ–‰ ์ˆœ์„œ๋Š” ๋ณด์žฅ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋ฒคํŠธ ์ˆœ์„œ์— ์˜์กดํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ๋ณต์žกํ•˜๊ณ  ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ด๋ฒคํŠธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•„์š”๋กœ ํ•˜๋Š” ์ƒํ™ฉ์—์„œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.(ex. ์•Œ๋ฆผ๋„ ๋ฐœ์†กํ•˜๊ณ  ๋ฉ”์ผ๋„ ๋ฐœ์†กํ•˜๋Š” ๊ฒฝ์šฐ์™€ ๊ฐ™์€ ๊ฒฝ์šฐ) ๋˜ํ•œ ์—ฌ๋Ÿฌ ์„œ๋น„์Šค๊ฐ€ ๋™์ผํ•œ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ๋‹ค๋ฅด๊ฒŒ ๋ฐ˜์‘ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ์ด๋ฒคํŠธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ฃผ๋ฌธ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๊ฒฐ์ œ ์„œ๋น„์Šค๋Š” ๊ฒฐ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ์žฌ๊ณ  ์„œ๋น„์Šค๋Š” ์žฌ๊ณ ๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๊ณ , ๋ฐฐ์†ก ์„œ๋น„์Šค๋Š” ๋ฐฐ์†ก์„ ์ค€๋น„ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ์— ๊ฐ ์„œ๋น„์Šค๋Š” ๋™์ผํ•œ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ์ž์‹ ๋งŒ์˜ ๋ฆฌ์Šค๋„ˆ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ฐธ๊ณ 

๋Œ“๊ธ€