Saga 디자인 패턴은 분산 시스템에서 롱 트랜잭션(Long Transaction)을 처리할 때 사용되는 패턴입니다.
특히 여러 서비스가 연관된 복잡한 작업을 처리할 때 유용합니다.
이 패턴의 핵심은 트랜잭션을 작은 단위로 나누고, 각 단위가 실패했을 때 롤백하는 방법을 제공하는 것입니다.
왜 Saga 디자인 패턴이 필요한가요?
일반적으로 데이터베이스에서 트랜잭션이 여러 단계를 포함할 때, 모든 단계를 하나의 큰 트랜잭션으로 처리하는 것은 효율적이지 않습니다.
대신 각 단계를 독립적으로 처리하고, 실패한 경우 보상 작업(compensation action)을 통해 롤백하는 방식으로 문제를 해결할 수 있습니다.
이렇게 하면 시스템의 안정성을 높이고, 장애 발생 시 더 쉽게 문제를 해결할 수 있습니다.
Saga 패턴의 기본 개념
Saga 디자인 패턴은 각 트랜잭션을 독립적으로 처리하고, 실패한 경우 그에 대한 보상 작업을 실행하는 방식입니다.
이 패턴은 크게 두 가지 방식으로 구현할 수 있습니다:
- Choreography 방식: 각 서비스가 서로 협력하여 롤백 작업을 수행합니다.
- Orchestration 방식: 중앙 시스템이 모든 작업을 조정하며 롤백을 처리합니다.
이 블로그에서는 Orchestration 방식을 중심으로, Flutter에서 Saga 디자인 패턴을 어떻게 사용할 수 있는지 예제를 통해 설명할 것입니다.
Saga 패턴 예제 - Flutter로 구현하기
예시 상황
우리는 온라인 쇼핑몰 앱을 만들고 있다고 가정합니다. 사용자가 상품을 구매하면, 다음의 과정들이 이루어집니다:
- 결제 서비스에서 결제를 진행합니다.
- 재고 서비스에서 재고를 차감합니다.
- 배송 서비스에서 배송을 시작합니다.
각각의 서비스가 성공적으로 처리되면, 최종적으로 구매가 완료됩니다. 그러나 만약 한 서비스에서 오류가 발생하면, 이전 서비스들에서 수행한 작업들을 롤백해야 합니다.
예시 코드 (Flutter와 Dart)
import 'dart:async';
class PaymentService {
Future<bool> makePayment() async {
print("Making payment...");
// 결제 성공 여부
return Future.delayed(Duration(seconds: 2), () => true); // 결제 성공
}
Future<void> rollbackPayment() async {
print("Rolling back payment...");
}
}
class StockService {
Future<bool> updateStock() async {
print("Updating stock...");
return Future.delayed(Duration(seconds: 2), () => true); // 재고 업데이트 성공
}
Future<void> rollbackStock() async {
print("Rolling back stock update...");
}
}
class ShippingService {
Future<bool> startShipping() async {
print("Starting shipping...");
return Future.delayed(Duration(seconds: 2), () => true); // 배송 시작 성공
}
Future<void> rollbackShipping() async {
print("Rolling back shipping...");
}
}
class SagaOrchestrator {
final PaymentService paymentService = PaymentService();
final StockService stockService = StockService();
final ShippingService shippingService = ShippingService();
Future<void> executeSaga() async {
try {
// 1. 결제 처리
bool paymentSuccess = await paymentService.makePayment();
if (!paymentSuccess) throw Exception("Payment failed!");
// 2. 재고 업데이트
bool stockSuccess = await stockService.updateStock();
if (!stockSuccess) throw Exception("Stock update failed!");
// 3. 배송 시작
bool shippingSuccess = await shippingService.startShipping();
if (!shippingSuccess) throw Exception("Shipping failed!");
print("Order successfully processed!");
} catch (e) {
// 에러 발생 시 롤백
print("Error occurred: $e");
// 롤백 작업 수행
await rollbackSaga();
}
}
Future<void> rollbackSaga() async {
// 각 서비스의 롤백 작업을 호출
await paymentService.rollbackPayment();
await stockService.rollbackStock();
await shippingService.rollbackShipping();
print("Rollback completed!");
}
}
void main() async {
final sagaOrchestrator = SagaOrchestrator();
await sagaOrchestrator.executeSaga();
}
코드 설명
- PaymentService: 결제를 처리하는 서비스입니다. 결제가 성공적으로 이루어지면 true를 반환하고, 실패한 경우에는 롤백 작업을 실행합니다.
- StockService: 재고를 처리하는 서비스입니다. 재고가 성공적으로 업데이트되면 true를 반환하며, 실패 시에는 롤백 작업을 실행합니다.
- ShippingService: 배송을 처리하는 서비스입니다. 배송이 성공적으로 시작되면 true를 반환하며, 실패 시 롤백 작업을 실행합니다.
- SagaOrchestrator: Saga 패턴을 조정하는 클래스입니다. 결제, 재고, 배송을 처리하고, 만약 한 단계에서 실패하면 롤백 작업을 실행합니다.
이 코드에서는 Orchestration 방식으로 각 서비스가 실패했을 때, 롤백 작업을 어떻게 처리하는지 보여주었습니다.
Saga 패턴은 시스템의 안정성을 높이고, 다양한 서비스 간의 복잡한 트랜잭션을 관리하는 데 큰 도움이 됩니다.
"당신의 학습 스타일에 맞춘 효율적인 학습, Study Duck과 함께하세요!"
MBTI에 따라 맞춤형 학습법을 적용하면, 학습 효과가 두 배로! 혼자 학습하면 빠르게 배울 수 있지만, Study Duck은 꾸준히 장기간 학습을 도와줍니다.
학습 타이머로 집중을 유지하고, 리더보드에서 다른 사람들과 경쟁하며 꾸준함을 유지하세요.
지금 바로 Study Duck으로 학습의 새로운 장을 열어보세요!
Study Duck
Study Duck Study smarter with the best learning tool!
www.studyduck.net
'Flutter > Study' 카테고리의 다른 글
플러터 오버플로우 대처법 (0) | 2025.03.20 |
---|---|
[애드센스] 구글 블로거에 ads.txt 파일 설치하기! 초보자도 쉽게 따라할 수 있는 방법 (1) | 2025.03.09 |
플러터에서 screenshot 패키지를 사용하여 이미지 생성 후 share_plus로 공유하기 (0) | 2025.03.09 |
HomeScreen({super.key}); vs HomeScreen({Key? key}) : super(key: key); 무슨 차이? (0) | 2025.02.14 |
플러터 초보자를 위한 Firebase Dynamic Links 사용법: go_router와 함께 딥 링크 구현하기 (1) | 2025.02.14 |