JSCODE Logo
프로그래밍 과외블로그후기멘토진
회사명 : JSCODE대표 : 박재성사업자 등록번호 : 244-22-01557통신판매업 : 제 2023-인천미추홀-0381 호
학원 명칭 : 제이에스코드(JSCODE)원격학원학원설립ㆍ운영 등록번호 : 제6063호

서울특별시 구로구 경인로 20가길 11(오류동, 아델리아)

Copyright ⓒ 2025 JSCODE - 최상위 현업 개발자들의 프로그래밍 교육 All rights reserved.

이용약관개인정보처리방침
← 블로그 목록으로 돌아가기

[실습] 게시글 작성 API에 Saga 패턴 적용시키기 - 2

JSCODE 박재성
JSCODE 박재성
2025-12-06
author
JSCODE 박재성
category
MSA
createdAt
Dec 6, 2025
series
비전공자도 이해할 수 있는 MSA 입문/실전
slug
practice-apply-saga-to-post-create-2
type
post
updatedAt
Dec 6, 2025 05:43 AM

✅ 게시글 작성 API의 Saga 패턴이 잘 작동하는 지 테스트해보기

  1. 어떤 식으로 작동했는 지 추적하기 좋게 코드 추가하기
    1. service/BoardService
      public void create(CreateBoardRequestDto createBoardRequestDto) { // 게시글 저장을 성공했는 지 판단하는 플래그 boolean isBoardCreated = false; Long savedBoardId = null; // 포인트 차감을 성공했는 지 판단하는 플래그 boolean isPointDeducted = false; try { // 게시글 작성 전 100 포인트 차감 pointClient.deductPoints(createBoardRequestDto.getUserId(), 100); isPointDeducted = true; // 포인트 차감 성공 플래그 System.out.println("포인트 차감 성공"); // 게시글 작성 Board board = new Board( createBoardRequestDto.getTitle(), createBoardRequestDto.getContent(), createBoardRequestDto.getUserId() ); Board savedBoard = this.boardRepository.save(board); savedBoardId = savedBoard.getBoardId(); isBoardCreated = true; // 게시글 저장 성공 플래그 System.out.println("게시글 저장 성공"); // 게시글 작성 시 작성자에게 활동 점수 10점 부여 userClient.addActivityScore(createBoardRequestDto.getUserId(), 10); System.out.println("포인트 적립 성공"); } catch (Exception e) { if (isBoardCreated) { // 게시글 작성 보상 트랜잭션 => 게시글 삭제 this.boardRepository.deleteById(savedBoardId); System.out.println("[보상 트랜잭션] 게시글 삭제"); } if (isPointDeducted) { // 포인트 차감 보상 트랜잭션 => 포인트 적립 pointClient.addPoints(createBoardRequestDto.getUserId(), 100); System.out.println("[보상 트랜잭션] 포인트 적립"); } // 실패 응답으로 처리하기 위해 예외 던지기 throw e; } }
       
  1. board-service 서버 다시 실행시키기
    1.  
  1. DB 데이터 정리하기
    1. 체크하기 쉽게 포인트는 1000포인트로 맞춰놓기
      notion image
       
  1. 활동 점수 적립 API에 예외 코드 잘 있는 지 확인
    1. 이전에 트랜잭션을 테스트하기 위해, ‘포인트 적립 → 게시글 작성 → 활동 점수 적립’의 작업 중에 ‘활동 점수 적립’에서 예외가 발생하도록 만들었었다.
      service/UserService
      @Service public class UserService { ... @Transactional public void addActivityScore( AddActivityScoreRequestDto addActivityScoreRequestDto ) { User user = userRepository.findById(addActivityScoreRequestDto.getUserId()) .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); user.addActivityScore(addActivityScoreRequestDto.getScore()); userRepository.save(user); throw new RuntimeException("에러 발생"); } }
       
  1. 게시글 작성 API 테스트해보기
    1. notion image
       
  1. board-service의 로그 확인하기
    1. notion image
      로그만 봤을 때는 정상적으로 모든 작업이 잘 취소된 것처럼 보인다. DB도 확인해보자.
       
  1. DB 확인하기
    1. notion image
      notion image
      notion image
      중간에 에러가 발생했을 때 일부 작업만 취소되지 않고, ‘포인트 차감, 게시글 작성, 활동 점수 적립’의 모든 작업이 취소됐다는 걸 알 수 있다.
       
  1. 에러 발생하는 코드 주석 처리하기
    1. 그럼 이번에는 에러 코드를 주석 처리하고, 정상적으로 ‘게시글 작성 API’가 잘 처리되는 지도 확인해보자.
      service/UserService
      @Service public class UserService { ... @Transactional public void addActivityScore( AddActivityScoreRequestDto addActivityScoreRequestDto ) { User user = userRepository.findById(addActivityScoreRequestDto.getUserId()) .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); user.addActivityScore(addActivityScoreRequestDto.getScore()); userRepository.save(user); // throw new RuntimeException("에러 발생"); } }
       
  1. user-service 서버 다시 실행시키기
    1.  
  1. 게시글 작성 API 테스트해보기
    1. notion image
       
  1. DB 확인하기
    1. notion image
      notion image
      notion image
      ‘포인트 차감, 게시글 작성, 활동 점수 증가’의 작업이 전부 정상적으로 작동했다는 걸 알 수 있다.
 
 

✅ 정리

Saga 패턴을 활용해 MSA 환경에서도 모든 작업이 하나의 트랜잭션으로 처리되는 것처럼 만들었다. 즉, 모든 작업이 아예 성공하거나 아예 실패하도록 만들었다. 이로써 MSA 환경에서도 데이터 일관성을 지킬 수 있게 됐다.
notion image
author
JSCODE 박재성
category
MSA
createdAt
Dec 6, 2025
series
비전공자도 이해할 수 있는 MSA 입문/실전
slug
type
series-footer
updatedAt
Dec 6, 2025 05:45 AM
📎
이 글은 비전공자도 이해할 수 있는 MSA 입문/실전 강의의 수업 자료 중 일부입니다.