본문 바로가기

Lecture32

Spring 배치 사용 이유와 기본 아키텍처에 대해 알아보자 1. 배치 프로그램 왜 사용하고 언제 사용할까 배치란 정해진 시간에 일괄적으로 작업을 처리하는 것을 의미한다. 대체로 대용량 데이터를 다룬다. 서비스를 운영하는 관점에서 주기적으로 작업을 처리하려면 배치 프로그램을 사용해야 한다. 데이터 처리 - 필요한 데이터를 모아서 처리해야 할 때 - ETL 작업 (Extract-Transform-Load) - 데이터 모델을 만들 때 (연관 상품을 추천하기) -> 헤비한 데이터 처리 - 마케팅 참고를 위한 데이터 지표 집계 서비스 - 일부러 지연시켜 처리할 때 (주문한 상품을 바로 배송하지 않고 일정 시간 뒤 보낼 때) - 메시지, 이메일, 푸시 등의 발송 - 데이터 마이그레이션 - 실패한 트랜잭션 처리 - 쿠폰, 포인트 소진 처리 - 월말 월초 특정 데이터 생성(월.. 2023. 7. 11.
선착순 이벤트 시스템에서 발생가능한 동시성 문제와 해결 방안 탐구(redis, kafka) 선착순으로 쿠폰을 발급해 주는 시스템에서 발생할 수 있는 문제와 해결 방안을 살펴본다. 요구사항 선착순 100명에게 할인쿠폰을 제공하는 이벤트를 진행하고자 한다. - 선착순 100명에게만 지급되어야 한다. - 101개 이상이 지급되면 안 된다. - 순간적으로 몰리는 트래픽을 버틸 수 있어야 한다. 구현 코드는 다음과 같다. 먼저 쿠폰 도메인이다. @Entity @Getter public class Coupon { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private Long userId; public Coupon() { } public Coupon(Long id, Long userId) { this.id = id;.. 2023. 7. 11.
동시성 이슈 사례와 해결 방안 탐구 (Synchronized, database, redis) 문제점 다음과 같은 재고 감소 로직을 가진 엔티티와 이를 검증하는 테스트 코드를 살펴보자. @Entity @Getter @NoArgsConstructor @AllArgsConstructor public class Stock { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private Long productId; private Long quantity; public void decrease(Long quantity) { if (this.quantity - quantity < 0) { throw new RuntimeException("foo"); } this.quantity -= quantity; } public Sto.. 2023. 7. 11.
자바 코드 리팩토링: 스프링 AplicationEventPublisher를 이용해 시스템 강결합을 해결해보자 시스템 강결합 문제와 이에 대한 해결 방안으로서 Event Publisher를 통한 해결 법을 살펴본다. 문제점 회원가입을 수행하는 서비스 로직을 생각해보자. 다음과 같은 요구사항을 만족해야 한다. 1) Member entity 영속화 2) 외부 시스템에 이메일 전송 3) 회원가입 쿠폰 발급 @Service @RequiredArgsConstructor public class MemberSignUpService { private final MemberRepository memberRepository; private final CouponIssueService couponIssueService; private final EmailSenderService emailSenderService; @Transacti.. 2023. 7. 9.
자바 코드 리팩토링: 객체에게 꼬치꼬치 묻지 말고 시켜라 - 종속적인 관계가 아닌 자율적인 관계 유지하기 문제점 다음과 같은 Coupon Legacy 코드가 있다고 치자. @Getter @Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class CouponLegacy { private long id; private boolean used; private double amount; private LocalDate expirationDate; public CouponLegacy(double amount, LocalDate expirationDate) { this.amount = amount; this.expirationDate = expirationDate; this.used = false; } } 해당 객체는 실제로 엔티티지만 별도의 로직을.. 2023. 7. 9.