SearchM
Backend Engineer서비스명 : SmPay
smpay는 광고 캠페인 데이터 수집·통합, 운영 심사, 비용 정산 및 리포팅 기능을 포함한 마케팅 대행사 전용 백오피스 플랫폼입니다.
다양한 광고 매체와 연동하여 데이터 정합성 유지 및 업무 자동화를 목표로 구축된 시스템입니다.
담당 업무
- 네이버, 카카오, 구글 등 주요 광고 매체 API 연동 및 데이터 수집 파이프라인 구축
- ROAS 기반 광고주 추천 시스템 및 충전/회수 미수 광고주 관리 로직 개발
- 외부 결제 시스템 연동 및 광고비 충전/회수 프로세스 자동화
- 광고주별 리포팅 데이터 가공 및 일 1회 갱신되는 대시보드 백엔드 API 개발
- 멀티 모듈 아키텍처 설계로 서비스별 독립 배포 환경 구축
- 서버별 로그 모니터링 대시보드 구축
TroubleShooting
문제 상황: 광고주 데이터 대량 적재 요구가 있었고, 해당 데이터는 delete → insert 방식으로 처리해야 했습니다. JPA 메소드로 saveAll(), deleteAll()을 사용하더라도 단건씩 처리되어 성능 병목이 발생했으며, 외부 광고 매체 API 호출 시 블로킹 방식으로 인한 스레드 효율성 저하 문제가 있었습니다. 또한 MSA 환경에서 서비스 간 호출 시 트랜잭션 경계가 달라 데이터 불일치 문제가 발생했고, 무한정 요청이 들어올 경우 스레드 고갈로 인한 서버 다운 위험도 존재했습니다.
접근 및 해결:
1. 대용량 데이터 처리 최적화
JDBC Template을 이용한 Bulk Delete/Insert 전략을 도입하여 삭제/적재 작업을 Queue에 넣고 chunk size 단위로 묶어 일괄 처리하도록 변경했습니다. JPA Hibernate를 우회하여 OOM을 방지하고 다건 처리로 속도를 대폭 향상시켰습니다.
2. 가상 스레드 기반 병렬 처리
Java 21에서 도입된 가상 스레드(Virtual Thread)를 활용하여 비싼 Application Level의 플랫폼 스레드 대신 경량 가상 스레드로 외부 API 통신을 병렬 처리했습니다. 외부 광고 매체 API 호출이 가장 많은 부분에서 가상 스레드를 통한 병렬 호출로 I/O 대기 시간을 효율적으로 활용했습니다.
3. RabbitMQ 메시지 브로커 도입
스레드 풀을 직접 관리하는 대신 RabbitMQ 메시지 브로커를 도입하여 Transaction OutBox 패턴으로 메시지를 안정적으로 발행했습니다. 메시지가 Queue에 쌓이면 Consumer가 설정된 개수만큼만 병렬로 처리하도록 구성하여, 무한정 요청이 들어오더라도 스레드 고갈이 발생하지 않고 최종적으로는 모두 처리될 수 있도록 보장했습니다.
4. SAGA 패턴 + 보상 트랜잭션
MSA 환경에서 서비스 간 트랜잭션 경계가 다른 문제를 해결하기 위해 SAGA 패턴을 적용했습니다. 외부 서비스 호출이 성공했으나 이후 처리에서 실패할 경우, 단계별로 보상 트랜잭션을 실행하여 데이터 일관성을 유지했습니다. 보상 트랜잭션 또한 실패할 수 있다고 판단하여 지수 백오프 기반 3회 재시도를 적용하고, 최종 실패 시 Slack Webhook으로 알림을 발송하여 데이터 일관성을 최대한 보장했습니다.
성과: 1000만 건의 대용량 데이터 기준 처리 속도가 4시간 30분에서 1시간으로 단축되어 78% 성능 개선을 달성했습니다. RabbitMQ와 가상 스레드 도입으로 서버 부하를 분산시키고 스레드 고갈 문제를 원천 차단했으며, SAGA 패턴을 통해 분산 환경에서의 데이터 일관성을 99% 이상 유지하여 서비스의 안정성과 가용성을 크게 향상시켰습니다.