ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๐Ÿ˜€ ๊ณผ์ œ ๊ฐœ์š”

  • ๋‚ด๊ฐ€ ๊ฐœ๋ฐœํ•œ ๊ธฐ๋Šฅ์˜ ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„์— ๋Œ€ํ•ด ์ดํ•ดํ•˜๊ณ , ์„œ๋น„์Šค์˜ ๊ทœ๋ชจ๊ฐ€ ํ™•์žฅ๋˜์–ด MSA ํ˜•ํƒœ๋กœ ์„œ๋น„์Šค๋ฅผ ๋ถ„๋ฆฌํ•œ๋‹ค๋ฉด ์–ด๋–ค ์„œ๋น„์Šค๋กœ ๋ถ„๋ฆฌ ํ™•์žฅ๋ ์ง€ ์„ค๊ณ„ํ•˜๊ณ , ๊ทธ ๋ถ„๋ฆฌ์— ๋”ฐ๋ฅธ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ์˜ ํ•œ๊ณ„์™€ ํ•ด๊ฒฐ๋ฐฉ์•ˆ์— ๋Œ€ํ•œ ์„œ๋น„์Šค ์„ค๊ณ„๋ฌธ์„œ ์ž‘์„ฑ

ํ•ด๋‹น ๊ณผ์ œ์˜ ์ด์œ ๋Š” ํ•œ ํŠธ๋žœ์žญ์…˜์ด ๊ธธ์–ด์งˆ ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ๋Œ€๋น„์ด๋‹ค. ํŠธ๋žœ์žญ์…˜ ์•ˆ์— ํŠธ๋žœ์žญ์…˜์ด ๋ถˆํ•„์š”ํ•œ ๋กœ์ง์—์„œ ์‹œ๊ฐ„์ด ๋งŽ์ด ์†Œ๋น„ ๋  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ๋กœ์ง์ด ๊ธธ์–ด ์„œ๋กœ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์—†์„ ๋กœ์ง์ด ์‹คํŒจํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ์ „์ฒด๊ฐ€ ๋กค๋ฐฑ ๋˜์–ด๋ฒ„๋ฆฌ๊ธฐ๋„ ํ•œ๋‹ค. ์™ธ์˜ ๋ฐ๋“œ๋ฝ ๋ฌธ์ œ ๋“ฑ์„ ์•ผ๊ธฐ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ด ๊ณผ์ œ์˜ ํ•ต์‹ฌ์€ ์„œ๋น„์Šค ๋ถ„๋ฆฌ์˜ ํ™•์žฅ์œผ๋กœ ๋ณด์ด์ง€๋งŒ, ์‚ฌ์‹ค ํŠธ๋žœ์žญ์…˜์„ ๋‚˜๋ˆ ์ฃผ๋Š” ์ž‘์—…์ด ์ค‘์š”ํ•  ๊ฒƒ์ด๋‹ค. (MSA ๋˜ํ•œ ๊ทธ๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•จ์ด ์žˆ์œผ๋‹ˆ..?)


๐Ÿ“š ์‹œ์ž‘ํ•˜๊ธฐ ์•ž์„œ.. MSA๋ž€?

- ๋„๋ฉ”์ธ ์ค‘์‹ฌ์„ ์ค‘์‹ฌ์œผ๋กœ ์„œ๋น„์Šค๋ฅผ ๋ชจ๋ธ๋งํ•˜๊ณ  ๊ตฌํ˜„ํ•˜๋Š” ์•„ํ‚คํ…์ฒ˜

- ๋ถ„๋ฆฌ๋œ ๋„๋ฉ”์ธ ์„œ๋น„์Šค๋“ค์€ HTTP API ๋˜๋Š” ๋น„๋™๊ธฐ ๋ฉ”์‹œ์ง• ๋ฐฉ์‹์œผ๋กœ ํ†ต์‹ 

- ์—ฌ๋Ÿฌ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋‚˜๋ˆ„์–ด์„œ ๊ฐ ์„œ๋ฒ„์— ๋ฐฐํฌํ•ด์„œ ์„œ๋กœ ๊ฐ„์— ํ†ต์‹ ์„ ํ†ตํ•ด ์„œ๋น„์Šค๋ฅผ ์ œ๊ณต

(์ผ๋‹จ์€ ๋„๋ฉ”์ธ์— ๋”ฐ๋ผ ๋”ฐ๋กœ ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•œ๋‹ค..์ •๋„๋กœ.. ๊ฐˆ๊ธธ์ด ๋ฉ€๋‹ค..(๋ฒŒ์จ ์—‰๋ฉ์ด๊ฐ€ ์•„ํŒŒ์˜จ๋‹ค))

 

๐Ÿ’ป MY ์ฝ˜์„œํŠธ ๋Œ€๊ธฐ์—ด ๋„๋ฉ”์ธ

0. Token (๋Œ€๊ธฐ์—ด)

  > Redis๋กœ ๋Œ€์ฒด๋˜์—ˆ์Œ (์ •ํ™•ํžˆ๋Š” ๋ถ„๋ฆฌ๋˜์–ด MSA๊ฐ€ ํ•„์š” ์—†์Œ)

1. Wallet (์‚ฌ์šฉ์ž ํฌ์ธํŠธ)

  1.1. ํฌ์ธํŠธ ์กฐํšŒ

  1.2. ํฌ์ธํŠธ ์ถฉ์ „

2. Reservation (์˜ˆ์•ฝ)

  2.1 ์˜ˆ์•ฝ ๊ฐ€๋Šฅ ๋‚ ์งœ ์กฐํšŒ

  2.2 ์˜ˆ์•ฝ ๊ฐ€๋Šฅ ์ขŒ์„ ์กฐํšŒ

  2.3 ์˜ˆ์•ฝ

3. Payment (๊ฒฐ์ œ)

  3.1. ๊ฒฐ์ œ

      3.1.1. ์ฝ˜์„œํŠธ ์ž„์‹œ์˜ˆ์•ฝ -> ์˜ˆ์•ฝ์œผ๋กœ ํ™•์ •

      3.1.2. ์ขŒ์„ ์ž„์‹œ์˜ˆ์•ฝ -> ์˜ˆ์•ฝ์œผ๋กœ ํ™•์ •

      3.1.3. ํฌ์ธํŠธ ์ฐจ๊ฐ (๊ธˆ์•ก ๋ถ€์กฑ ์‹œ ์ถฉ์ „ํ•„์š”)

      3.1.4. ํฌ์ธํŠธ ์‚ฌ์šฉ ํžˆ์Šคํ† ๋ฆฌ ์ €์žฅ

 

!. ์ •๋ฆฌ

ํ•ด๋‹น ์„œ๋น„์Šค๋Š” 1๋ฒˆ์˜ ์‚ฌ์šฉ์ž ํฌ์ธํŠธ ๋ถ€๋ถ„๊ณผ 2๋ฒˆ์˜ ์˜ˆ์•ฝ์€ ๊ทธ๋Œ€๋กœ ๋–ผ์–ด๋‚ด๋„ ๋  ์ •๋„๋กœ ํ•ด๋‹น ๊ธฐ๋Šฅ๋งŒ์„ ์‚ฌ์šฉํ•œ๋‹ค. ํ•˜์ง€๋งŒ 3๋ฒˆ์˜ ๊ฒฐ์ œ๋Š” ์˜ˆ์•ฝ ์ •๋ณด๋„ ๋ถˆ๋Ÿฌ์•ผํ•˜๋ฉฐ, ํฌ์ธํŠธ ๋ถ€๋ถ„๋„ ๋ถˆ๋Ÿฌ์•ผ ํ•œ๋‹ค. ๊ทธ๋Ÿผ ๋”ฑ 2๊ฐ€์ง€๋กœ ๋‚˜๋ˆ ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

 

!. ๋ณ€๊ฒฝ

1. Wallet (์‚ฌ์šฉ์ž ํฌ์ธํŠธ)

  1.1. ํฌ์ธํŠธ ์กฐํšŒ

  1.2. ํฌ์ธํŠธ ์ถฉ์ „

  1.3. ํฌ์ธํŠธ ์ฐจ๊ฐ (๊ธˆ์•ก ๋ถ€์กฑ ์‹œ ์ถฉ์ „ํ•„์š”)

  1.4. ํฌ์ธํŠธ ์‚ฌ์šฉ ํžˆ์Šคํ† ๋ฆฌ ์ €์žฅ

2. Reservation (์˜ˆ์•ฝ)

  2.1 ์˜ˆ์•ฝ ๊ฐ€๋Šฅ ๋‚ ์งœ ์กฐํšŒ

  2.2 ์˜ˆ์•ฝ ๊ฐ€๋Šฅ ์ขŒ์„ ์กฐํšŒ

  2.3 ์˜ˆ์•ฝ

  2.4. ์ฝ˜์„œํŠธ ์ž„์‹œ์˜ˆ์•ฝ -> ์˜ˆ์•ฝ์œผ๋กœ ํ™•์ •

  2.5. ์ขŒ์„ ์ž„์‹œ์˜ˆ์•ฝ -> ์˜ˆ์•ฝ์œผ๋กœ ํ™•์ •

3. Payment (๊ฒฐ์ œ)

  2.1 Wallet์˜ ํฌ์ธํŠธ ์ฐจ๊ฐ์„ ๊ฐ€์ ธ์˜ด

  2.2 Reservation์˜ ์˜ˆ์•ฝํ™•์ •์„ ๊ฐ€์ ธ์˜ด

 

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

ํ˜„์žฌ

    public class PaymentService {
    
        @Transactional
        public PaymentCommand.getPaymentInfo pay(PaymentCommand.Pay pay) {
            LocalDateTime now = LocalDateTime.now();
            Long currentTokenUserId = requestTokenUtil.getCurrentTokenUserId();

            // ์ฝ˜์„œํŠธ ์˜ˆ์•ฝ (์ƒํƒœ ํ™•์ •์œผ๋กœ ๋ณ€๊ฒฝ)
            ConcertReservation concertReservation = concertReservationRepository.findById(pay.concertReservationId());
            concertReservation.reserved();

            // ์ฝ˜์„œํŠธ ์ž๋ฆฌ ํ™•์ •์œผ๋กœ ํ•ด์ค€๋‹ค.
            ConcertSeat concertSeat = concertSeatRepository.findById(pay.seatId());
            concertSeat.setSeatStatusAssign(now);

            // ๊ธˆ์•ก ์ฐจ๊ฐ
            usePointWithOptimisticLock result = getUsePointWithOptimisticLock(currentTokenUserId, now);

            // ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์Œ“๋Š”๋‹ค.
            walletHistoryRepository.save(getWalletHistory(result.wallet(), result.price(), result.balanceBefore(), result.balanceAfter(), now));

            return new PaymentCommand.getPaymentInfo(์˜ˆ์•ฝ์ •๋ณด๋“ค..);
        }
        
    }
  1. ์ฝ˜์„œํŠธ๋ฅผ ๋จผ์ € ์˜ˆ์•ฝํ™•์ • -> ๊ธˆ์•ก์ฐจ๊ฐ์„ ํ•œ๋‹ค ์ด ๋กœ์ง์€ ๋ถ„๋ฆฌํ•˜๋ ค๋‹ˆ ์ด์ƒํ•ด ๋ณด์˜€๋‹ค.
  2. '๊ฒฐ์ œ'๋ผ๋Š” ๋กœ์ง์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋ คํ•˜๋‹ˆ, ํŽธ์˜์ ์— ๋“ค์–ด๊ฐ”์„ ๋•Œ๊ฐ€ ์ƒ๊ฐ์ด ๋‚ฌ๋‹ค. ๋‹ด๋ฐฐ๋ฅผ ์‚ฌ๋ ค๊ณ  "ํ”„๋ Œ์น˜๋ธ”๋ž™ ์ฃผ์„ธ์š”."๋ผ๊ณ  ๋งํ•˜๋ฉด ๋‚ด๊ฐ€ ๊ฒฐ์ œํ•  ๋•Œ๊นŒ์ง€ ๋‹ด๋ฐฐ๋Š” ์ฃผ์ง€ ์•Š๋Š”๋‹ค.
  3. ๊ทธ๋Ÿผ  ๊ฒฐ์ œ๋ผ๋Š” ํ–‰์œ„์ž์ฒด๋Š” ํฌ์ธํŠธ ์ฐจ๊ฐ์— ์žˆ๋‹ค. ์ˆœ์„œ๋ฅผ ๊ธˆ์•ก ์ฐจ๊ฐ ->์ฝ˜์„œํŠธ ์ž๋ฆฌ ํ™•์ •์œผ๋กœ ํ•ด์•ผํ•œ๋‹ค.
  4. '์ฝ˜์„œํŠธ ์ž๋ฆฌ ํ™•์ •'์€ ๊ฒฐ์ œ์™€๋Š” ๊ฑฐ๋ฆฌ๊ฐ€ ์žˆ๋‹ค. ๋ฌผ๋ก  ๊ฒฐ์ œ๋Š” ๋ฌผ๊ฑด์„ ์‚ฌ๋Š” ํ–‰์œ„์ด์ง€๋งŒ,  '์ž๋ฆฌ ํ™•์ •'์€ ๋งˆ์น˜ ์ฟ ํŒก์—์„œ ๋ฌผ๊ฑด์„ ์‚ฌ๋„ ๋ฐฐ์†ก์„ ๊ธฐ๋‹ค๋ ค์•ผ ํ•˜๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ๊ทธ ๋‹ค์Œ์˜ ํ–‰์œ„๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.
  5. ๋ฌผ๋ก  ๋‹ค๋ฅธ ๋ฐฉ๋ฉด์œผ๋กœ๋Š” '๊ฒฐ์ œ'์— '์ฝ˜์„œํŠธ ์ž๋ฆฌ ํ™•์ •'์„ ๋ฌถ์„ ์ˆ˜๋Š” ์žˆ๋‹ค. ๋‹ค๋งŒ ์ด๋ฒˆ์—๋Š” ๋ถ„๋ฆฌ์— ๋ชฉ์ ์ด ์žˆ์œผ๋‹ˆ ์ตœ๋Œ€ํ•œ ์ชผ๊ฐœ ๋ณด์ž.

1์ฐจ ์ˆ˜์ •๋กœ์ง (๋„๋ฉ”์ธ ๋ณ„๋กœ ๋‚˜๋ˆˆ๋‹ค)

    public class PaymentPacade {
    
        @Transactional
        public PaymentCommand.getPaymentInfo pay(PaymentCommand.Pay pay) {
            LocalDateTime now = LocalDateTime.now();
            Long currentTokenUserId = requestTokenUtil.getCurrentTokenUserId();

            // ๊ธˆ์•ก ์ฐจ๊ฐ ๋ฐ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์Œ“๋Š”๋‹ค.
            Wallet result = walletService.getUsePointAndSaveHistory(currentTokenUserId, now);
		
            //์˜ˆ์•ฝ ํ™•์ •
            ConcertReservation reservResult = resevationService.reserved(pay.concertReservationId(), pay.seatId(), now);
            return new PaymentCommand.getPaymentInfo(์˜ˆ์•ฝ์ •๋ณด๋“ค..);
        }
        
    }

        
    public class ResevationService {
    
        pulbic ConcertReservation reserved(Long concertReservationId, Long seatId){
            // ์ฝ˜์„œํŠธ ์˜ˆ์•ฝ (์ƒํƒœ ํ™•์ •์œผ๋กœ ๋ณ€๊ฒฝ)
            ConcertReservation concertReservation = concertReservationRepository.findById(concertReservationId);
            concertReservation.reserved();

            // ์ฝ˜์„œํŠธ ์ž๋ฆฌ ํ™•์ •์œผ๋กœ ํ•ด์ค€๋‹ค.
            ConcertSeat concertSeat = concertSeatRepository.findById(seatId);
            concertSeat.setSeatStatusAssign(now);
            
            retrun concertReservation;
        }
        
    }
  1. PaymentPacade์—์„œ ๊ฐ๊ฐ wallet๊ณผ reservation์˜ ์„œ๋น„์Šค๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์‹์œผ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.
  2. ์ด์ƒํ•œ ์ ์ด ์žˆ๋‹ค. ๋ถ„๋ฆฌ ํ•˜๋Š” ์ด์œ ๋Š” '๋„๋ฉ”์ธ ๋ณ„๋กœ ๋ถ„๋ฆฌ ํ™•์žฅ'๋„ ์žˆ์ง€๋งŒ, ๋ถˆํ•„์š”ํ•œ ํŠธ๋žœ์žญ์…˜์„ ๋งŒ๋“ค์ง€ ์•Š๋Š” ๊ฒƒ์ด๋‹ค.
  3. ํ•˜์ง€๋งŒ ์œ„๋Š” ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๋ฌถ์ด๊ฒŒ ๋œ๋‹ค. ๋‚˜๋ˆ ๋ณด์ž.

2์ฐจ ์ˆ˜์ •๋กœ์ง (ํŠธ๋žœ์žญ์…˜์„ ๋‚˜๋ˆˆ๋‹ค. feat Event)

    public class PaymentPacade {
    
        @Transactional
        public PaymentCommand.getPaymentInfo pay(PaymentCommand.Pay pay) {
            LocalDateTime now = LocalDateTime.now();
            Long currentTokenUserId = requestTokenUtil.getCurrentTokenUserId();

            // ๊ธˆ์•ก ์ฐจ๊ฐ ๋ฐ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์Œ“๋Š”๋‹ค.
            Wallet result = walletService.getUsePointAndSaveHistory(currentTokenUserId, now);
		
            //์˜ˆ์•ฝ ํ™•์ •
            reservedEventPublisher.publishEvent(pay);
            
            return new PaymentCommand.getPaymentInfo(์˜ˆ์•ฝ์ •๋ณด๋“ค..);
        }
        
    }

        @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
        pulbic void reserved(PaymentCommand.Pay pay){
            // ์ฝ˜์„œํŠธ ์˜ˆ์•ฝ (์ƒํƒœ ํ™•์ •์œผ๋กœ ๋ณ€๊ฒฝ)
            ConcertReservation concertReservation = concertReservationRepository.findById(pay.concertReservationId);
            concertReservation.reserved();

            // ์ฝ˜์„œํŠธ ์ž๋ฆฌ ํ™•์ •์œผ๋กœ ํ•ด์ค€๋‹ค.
            ConcertSeat concertSeat = concertSeatRepository.findById(pay.seatId);
            concertSeat.setSeatStatusAssign(now);
           
        }

 

1. ์œ„ ์ฒ˜๋Ÿผ ํ•˜๋ฉด Event๋ฅผ ์ด์šฉํ•˜๊ธฐ์— ํŠธ๋žœ์žญ์…˜์˜ ๋ฒ”์œ„๊ฐ€ ๋‚˜๋‰˜๊ฒŒ ๋˜๋ฉฐ, ๋”ฐ๋ผ์„œ ๊ฒฐํ•ฉ๋ ฅ๊นŒ์ง€ ๋‚ฎ์ถ”๊ฒŒ ๋œ๋‹ค.

2. ๋‹ค๋งŒ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค. ๋งŒ์•ฝ '์˜ˆ์•ฝ ํ™•์ •' ๋กœ์ง์—์„œ ์˜ˆ์™ธ๊ฐ€ ํ„ฐ์ง„๋‹ค๋ฉด?

3. ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒ ์ง€๋งŒ ์œ„์˜ ๊ฒฝ์šฐ, ํฌ์ธํŠธ ์ฐจ๊ฐ์€ ๋กค๋ฐฑ์ด ๋˜์–ด์•ผ ํ•œ๋‹ค.

 

3์ฐจ ์ˆ˜์ •๋กœ์ง (๋กค๋ฐฑ ์ •์ฑ…)

    public class PaymentPacade {
    
        @Transactional
        public PaymentCommand.getPaymentInfo pay(PaymentCommand.Pay pay) {
			...
            //ํฌ์ธํŠธ ์ฐจ๊ฐ
            pay.Wallet(wallet);
            //์˜ˆ์•ฝํ™•์ • ์ด๋ฒคํŠธ ํ˜ธ์ถœ
        }
        
    }

        @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
        pulbic void reserved(PaymentCommand.Pay pay){
           try {
            // ์ฝ˜์„œํŠธ ์˜ˆ์•ฝ (์ƒํƒœ ํ™•์ •์œผ๋กœ ๋ณ€๊ฒฝ)
            ConcertReservation concertReservation = concertReservationRepository.findById(pay.concertReservationId);
            concertReservation.reserved();

            // ์ฝ˜์„œํŠธ ์ž๋ฆฌ ํ™•์ •์œผ๋กœ ํ•ด์ค€๋‹ค.
            ConcertSeat concertSeat = concertSeatRepository.findById(pay.seatId);
            concertSeat.setSeatStatusAssign(now);
           } catch(Exception e) {
           		log.warn("์˜ค๋ฅ˜๋ฐœ์ƒ");
                ํฌ์ธํŠธ์ฐจ๊ฐ๋กค๋ฐฑPublisher.publishEvent(pay);
           }
        }
        
        @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
        pulbic void RollbackPoint(PaymentCommand.Pay pay){
            try {
            	Wallet wallet = pay.wallet;
            	wallet.RollbackPoint(pay);
           } catch(Exception e) {
           		์žฌ์‹œ๋„ ๋กœ์ง..
           }
        }

1. ์˜ˆ์™ธ๊ฐ€ ํ„ฐ์ง€๋ฉด ํฌ์ธํŠธ๋ฅผ ์ฐจ๊ฐํ•˜๋Š” ๋กค๋ฐฑ์„ ๋˜ ๋ถˆ๋Ÿฌ์™€์•ผํ•œ๋‹ค.

2. ๋กค๋ฐฑ ๋กœ์ง์—๋„ ๋˜ ์˜ˆ์™ธ๊ฐ€ ํ„ฐ์งˆ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ํ•  ๊ฒƒ์ธ๊ฐ€??????? 

 

        @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
            public void rollbackPoint(PaymentCommand.Pay pay) {
                int attempts = 0;
                boolean success = false;
        
                while (attempts < MAX_RETRIES && !success) {
                    try {
                        Wallet wallet = pay.wallet;
                        wallet.rollbackPoint(pay);
                        success = true; // ์„ฑ๊ณตํ•˜๋ฉด ๋ฐ˜๋ณต๋ฌธ ์ข…๋ฃŒ
                    } catch (Exception e) {
                        attempts++;
                        if (attempts >= MAX_RETRIES) {
                            // ๋กœ๊น… ๋˜๋Š” ์•Œ๋ฆผ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
                            log.warn("์žฌ์‹œ๋„ ํšŸ์ˆ˜ ์ดˆ๊ณผ: " + e.getMessage());
                            
                            //**DB์— ํ•ด๋‹น ์‹คํŒจ ์ •๋ณด๋ฅผ ๋‹ด์•„์ค€๋‹ค
                        } else {
                            log.warn("์žฌ์‹œ๋„ ์ค‘... ์‹œ๋„ ํšŸ์ˆ˜: " + attempts);
                }
            }
        }
    }

 

1. ์ด๋ ‡๊ฒŒ ์žฌ์‹œ๋„ ํ›„์—๋„ ๊ณ„์† ์˜ˆ์™ธ๊ฐ€ ํ„ฐ์ง„๋‹ค๋ฉด ์–ด์ฉ” ์ˆ˜ ์—†๋‹ค. ํ•ด๋‹น ์ •๋ณด๋ฅผ ์ž˜ ์กฐํ•ฉํ•ด db์— ๋‹ด๋Š”๋‹ค.

2. DB์— ๋‹ด๊ธด ์ •๋ณด๋ฅผ ํ›„์— ๋ฐฐ์น˜์— ๋Œ๋ฆฐ๋‹ค. ๊ทธ๋ž˜๋„ ์•ˆ๋˜๋ฉด ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์•Œ๋ฆผ์„ ๋ฐœ์†กํ•ด์„œ ํ•ด๋‹น ํ”„๋กœ๊ทธ๋žจ์„ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

3. ๋งˆ์ง€๋ง‰์œผ๋กœ ํ•ด๋‹น ๋กœ์ง์ด MSA๋กœ ์ˆ˜์ •๋œ๋‹ค๋ฉด?

 

4์ฐจ ์ˆ˜์ •๋กœ์ง (MSA..?)

    public class PaymentPacade {
    
        @Transactional
        public PaymentCommand.getPaymentInfo pay(PaymentCommand.Pay pay) {
            LocalDateTime now = LocalDateTime.now();
            Long currentTokenUserId = requestTokenUtil.getCurrentTokenUserId();

            // ๊ธˆ์•ก ์ฐจ๊ฐ ๋ฐ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์Œ“๋Š”๋‹ค.
            Wallet result = walletService.getUsePointAndSaveHistory(currentTokenUserId, now);
		
            //์˜ˆ์•ฝ ํ™•์ •
            reservedEventPublisher.publishEvent(pay);
            
            return new PaymentCommand.getPaymentInfo(์˜ˆ์•ฝ์ •๋ณด๋“ค..);
        }
    }

        @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
        pulbic void reserved(PaymentCommand.Pay pay){

			//์•„์›ƒ๋ฐ•์Šค ํŒจํ„ด?
            String result = reservedClient.reserved(pay);
				
            if(result.equals("fail")){
            	//์žฌ์‹œ๋„ ๋กœ์ง
                // ์žฌ์‹œ๋„ ์‹คํŒจ ์‹œ DB ์ €์žฅ..
            }
        }

 

1. ์œ„์˜ ๋กœ์ง์ฒ˜๋Ÿผ ๋‹ค๋ฅธ api๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์ •๋ณด๋ฅผ ๋ฐ›๋Š”๋‹ค.

2. ์‹คํŒจ์‹œ ์žฌ์‹œ๋„ ๋กœ์ง์„ ์‚ฌ์šฉํ•œ๋‹ค.

3. ๋งŒ์•ฝ api ์š”์ฒญ ์ค‘์— ๋Œ€์ƒ api์—์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ ์—ฐ๊ฒฐ์ด ๋Š๊ธด๋‹ค๋ฉด ์•„์›ƒ๋ฐ•์Šค ํŒจํ„ด์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

4. ํ˜ธ์ถœ ๋ถ€๋ถ„์˜ ํ•ด๋‹น ์š”์ฒญ์„ db์— ๋„ฃ๊ณ  ์ž˜ ๋„์ฐฉํ–ˆ์„ ๋•Œ์— db์— ๋„์ฐฉ์™„๋ฃŒ๋กœ ์ƒํƒœ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋Š” ์‹์œผ๋กœ ํ•ด๋‹น ์š”์ฒญ์˜ ์„ฑ๊ณต์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 

 

๋์œผ๋กœ

์•„์ง ํŠธ๋žœ์žญ์…˜ ๋ถ„ํ• ์— ๋Œ€ํ•ด ๋ฏธ์ˆ™ํ•˜์—ฌ ๋งŽ์ด ๋ฏธํกํ–ˆ๋‹ค. ์ž‘์€ ์„ค๊ณ„์ด์ง€๋งŒ ํŠธ๋žœ์žญ์…˜์„ ์–ด๋–ป๊ฒŒ ๋ถ„๋ฆฌํ•ด์•ผ ๋˜๋Š”์ง€์— ๋Œ€ํ•œ ๊ฐ์„ ์žก๋Š” ์†Œ์ค‘ํ•œ ์‹œ๊ฐ„์ด์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.