Spring Batch로 대용량 데이터 처리하기: 학습 정리
·
Spring
목차TL;DR문제 상황: 대용량 데이터 처리의 필요성Spring Batch 핵심 개념Job, Step, Chunk 이해하기실제 배치 프로세스 설계실패 처리와 재시작 전략성능 최적화 방안실무 적용 시 고려사항마무리: 학습 후 느낀 점TL;DRSpring Batch를 학습하며 정리한 내용입니다. Spring Batch는 대용량 데이터를 안정적으로 처리하기 위한 프레임워크로, Job-Step-Chunk 구조를 통해 데이터를 읽고, 가공하고, 쓰는 과정을 체계적으로 관리합니다. 실패 시 재시작, 트랜잭션 관리, 병렬 처리 등의 기능을 제공하여 엔터프라이즈 환경에서 배치 처리를 효율적으로 구현할 수 있습니다.문제 상황: 대용량 데이터 처리의 필요성일반적인 처리 방식의 한계// 문제가 되는 접근List allOrd..
Redis ZSET으로 실시간 랭킹 시스템 구축하기
·
Spring
TL;DRKafka 기반 이벤트 파이프라인 위에 Redis ZSET을 활용한 실시간 랭킹 시스템을 구축했습니다. 단순한 집계 테이블에서 벗어나 실시간 가중치 조절, 콜드 스타트 문제 해결, 그리고 배치 처리를 통한 성능 최적화까지 - 운영 환경에서 실제로 마주할 수 있는 문제들을 어떻게 해결했는지 공유합니다.문제 정의: 단순한 집계에서 실시간 랭킹으로지난 주차에서 Kafka 기반 이벤트 파이프라인을 구축하면서 product_metrics 테이블에 상품별 집계 데이터를 쌓고 있었습니다:-- 기존: 단순한 집계 테이블SELECT product_id, view_count, like_count, sales_countFROM product_metrics WHERE metric_date = CURRENT_DATEO..
Kafka와 아웃박스 패턴으로 이벤트 파이프라인 구축하기
·
Spring
TL;DRKafka 기반 이벤트 파이프라인을 구축하면서 겪었던 현실적인 고민들을 공유합니다. "At Least Once" 보장을 위한 아웃박스 패턴, 컨슈머에서의 멱등성 처리, 그리고 동시성 제어까지 - 완벽한 설계는 아니지만, 마주한 문제들을 어떻게 해결했는지 솔직하게 담았습니다.문제 정의: 왜 Kafka가 필요했을까?기존에 Spring ApplicationEvent를 활용한 이벤트 기반 아키텍처를 구축했지만, 새로운 요구사항이 생겼습니다:상품별 유저 이벤트 집계: 일별 좋아요 수, 조회 수, 주문 수 추적감사 로그: 모든 비즈니스 이벤트의 완전한 기록캐시 관리: 상품 상세에 대한 캐시관리기존 방식의 한계가 명확했습니다:// 기존: 애플리케이션 내부 이벤트만 처리 가능@EventListenerpubli..
ApplicationEvent로 비즈니스 경계 나누기: 고민과 선택
·
Spring
오늘은 Spring ApplicationEvent를 활용해 비즈니스 로직을 분리하면서 겪었던 고민과 선택 과정을 공유해보려고 합니다."무조건 이벤트로 분리하는 게 좋은 걸까?"라는 질문에서 시작해서, 트랜잭션 경계와 비즈니스 요구사항에 따른 판단을 어떻게 내렸는지 담아보았습니다.정답이 있는 것은 아니지만, 고민했던 과정들을 기록해보려고 합니다.1. 문제 정의 커머스 시스템을 개발하면서 자연스럽게 다음과 같은 고민에 직면했습니다."주문-결제가 성공하면 데이터 플랫폼에도 전송해야 하고, 좋아요를 누르면 집계도 업데이트해야 하는데... 이걸 어떻게 처리하지?"처음에는 모든 로직을 하나의 메서드에서 순차적으로 처리했습니다:// 처음 구현 - 모든 로직이 한 곳에public PaymentInfo processPa..
결제 시스템에 Circuit Breaker를 도입하며 – 계층별 책임 분리와 안정성 확보 전략
·
Spring
안녕하세요! 오늘은 결제 시스템 연동 개발 중 겪었던 고민과 해결 과정을 공유해보려고 합니다.외부 PG 시스템과 연동하면서 "장애 전파를 어떻게 막을까?" 라는 문제에 직면했고, Resilience4j를 활용한 Circuit Breaker 패턴을 활용한 경험을 담았습니다.문제 정의결제 시스템을 운영하다 보면 자연스럽게 다음과 같은 고민에 직면하게 됩니다."외부 PG 시스템 장애 시, 우리 서비스는 어떻게 대응해야 할까?" 겪을수 있는 문제들PG 서비스가 일시적으로 다운되면 우리 서비스도 함께 멈춰버림결제 실패 시 사용자에게 명확한 안내 부족콜백 데이터 동기화 실패로 인한 데이터 불일치장애 전파로 인한 전체 서비스 영향이런 문제들을 해결하기 위해 Resilience4j를 활용한 안정성 확보 전략을 도입하게..
DB 인덱스 설계와 Redis 캐싱(Port-Adapter) 적용기
·
Spring
TL;DR조회 시나리오(브랜드/카테고리/정렬)에 맞춰 복합 인덱스 4종을 설계·적용.커버링 인덱스 개념을 이해하고 적용 가능성 검토(이번 과제에선 부분 적용).캐시 계층은 Port-Adapter 구조로 설계: GenericCachePort(공통) + 도메인 전용 포트(ProductCache 등).빈 값 미캐싱 + 분산락(SETNX) 으로 캐시 스탬피드 최소화.기본 필터의 상품목록 1–3페이지만 캐싱하는 부분 캐싱 정책으로 메모리/일관성 균형.1) 문제 정의상품 목록/상세 조회 트래픽이 증가하면서 정렬 + 필터 조합의 쿼리 비용이 커짐.Redis 캐시를 적용하려는데, 서비스마다 유사한 캐시 로직이 중복될 우려.캐시 스탬피드, 빈 값 캐싱, 직렬화 문제 등 운영 이슈를 예방할 구조가 필요.2) 접근 방법데이..
Spring 트랜잭션 핵심 정리
·
Spring
정리 배경@Transactional은 처음에는 단순해 보이지만, 실제로 사용해보면 예상과 다른 동작을 겪게 됩니다. 전파 옵션(REQUIRED, REQUIRES_NEW), rollback-only, 프록시, ThreadLocal 같은 개념들이 얽혀 있기 때문입니다.이번 정리의 목표는 다음 세 가지입니다.트랜잭션 전파 방식 이해 (REQUIRED vs REQUIRES_NEW)rollback-only가 언제 설정되고, 어떻게 동작하는지트랜잭션 매니저가 싱글톤인데 상태 충돌이 발생하지 않는 이유1. 트랜잭션 전파 (Propagation)REQUIRED (기본값)@Transactionalpublic void outer() { inner();}outer()에서 트랜잭션이 시작되면, inner()는 동일한 트..
도메인 검증 책임은 어디에 둘까요? – Service vs Facade, 저는 이렇게 선택했습니다
·
Spring
문제 정의DDD 스타일로 계층을 분리하여 개발을 진행하다 보면 자연스럽게 다음과 같은 고민을 하게 됩니다. “도메인 객체의 유효성 검증은 어느 계층에서 수행하는 것이 좋을까?”도메인을 Service에서 조회하고 검증까지 할 것인지,혹은 Facade에서 검증 책임까지 맡을 것인지에 대한 결정입니다. 예를 들어, ProductOption이 현재 판매 중인지 확인해야 하는 상황에서는 다음 두 가지 접근 방식이 존재합니다.두 가지 방식: Service vs Facade✅ 방식 A – Service에서 도메인 조회 및 검증// ProductOptionServicepublic ProductOption isOnSales(Long productOptionId) { ProductOption productOption..