Spring 8

SQS - 메세지 중복 처리 방지하기

SQS 적용 과정에서 아래와 같은 중복 수신 상황을 다룬 과정을 소개하려고 한다. 아래와 같이 동일한 바디(Message Body)를 가진 메세지를 중복하여 수신할 수 있는 상황이 존재한다. Source Queue 에서 처리 완료되지 못한 메세지를 MaxReceiveCount 만큼 재시도한다. 메세지 처리 불가 상태로 추정되어 DLQ 로 이동된 이후에 재시도된다. 메세지가 Visibility Timeout (가시성 타임아웃) 내에 정상적으로 처리되지 못하여 재시도되는 상황은 다음과 같다. 메세지 처리시간이 Visibility Timeout 을 초과할 경우 메세지 처리 중, 예외가 발생했을 경우 재시도 상황 1 설명에 앞서, Visibility Timeout 이 무엇이고, 어떻게 동작하는 것이며, Visi..

Spring 2023.05.30

RateLimiter 제대로 알고 쓰기

일반적으로 요청받는 서버에서 단시간에 지나치게 높은 호출 빈도를 제어하기 위한 목적으로(throttling) RateLimiter 를 사용하고 있다. RateLimiter 는 Guava 라이브러리에서 제공하는 유틸리티로, 외부 서버로의 API 호출을 제한하기 위해 자주 사용된다. RateLimiter 를 이용해 호출 빈도 제한 방법 의존성 추가 우선, RateLimiter 는 Guava 라이브러리 내에 존재하는 유틸리티기 떄문에 이를 사용하기 위해 Guava 라이브러리 의존성을 추가해야 한다. implementation("com.google.guava:guava:31.0.1-jre") RateLimiter 인스턴스의 생성 // 1초당 2회로 제한하는 케이스이다. // 넘겨 주는 인자는 permitsPer..

Spring 2023.04.12

RunTest에 대해서...

코루틴을 프로젝트에서 사용하다보면, 일시 중단 함수를 테스트하거나 테스트 코드 내부적으로 호출해야할 일이 빈번하게 발생한다. 하지만, 테스트를 진행하는 JUnit 환경에선 테스트 함수가 일시 중단 함수가 아니기 때문에 의무적으로 최상위 코루틴 스코프를 생성해 해당 스코프 내에서 일시 중단 함수를 호출해야 했다. @Test fun test() { runBlocking { // 일시 중단 함수 호출 // 일시 중단 함수 호출 } } 문제 - 테스트 코드 내에서 delay() 함수를 사용 이런 처리를 일일이 해야하는 것에 번거로움을 느낄때쯤, 기대한 처리가 완료될 때까지 대기하는 delay(1000) 함수를 테스트 코드 내에서 사용해야할 일이 발생했다. 사내에서 제공하고 있는 구매 서비스는 기본적으로 구매 요..

Spring 2023.03.26

Redis 분산락을 이용해서 한 번에 한 번씩 결제하기

문제 상황 3/9 일 경, PM 분들에게 네이버페이 이용건 중 결제 후 바로 결제 취소 처리되는 이슈를 넘겨받게 되었습니다. 해당 케이스를 조금 살펴 보니 카셰어링(쏘카) + KTX 상품을 묶음으로 구매할 때, 네이버 페이 포인트를 포함한 결제를 진행하는 경우 포인트 작액 부족에 의해서 결제 실패가 되었고, 이에 따라 결제 취소 API 가 바로 호출되고 있었습니다. 해당 케이스에 경우, 내부 로직 상 묶음 상품(카셰어링 + KTX 상품1 + KTX 상품2) 에 의해 총 3번의 결제가 이루어져야 했는데, 카셰어링 + KTX 상품1 에 대해서만 결제가 성공하고, KTX 상품2 는 결제가 실패한 상태였기 때문에 한건에 결제 실패에 의해 나머지 결제가 성공한 건들 모두 결제가 취소되어야 하는 상태였습니다. 이에..

Spring 2023.03.20

I/O 작업 비동기로 처리하기(w. 코루틴)

이번에 php 코드로 동작하고 있던 만료 예정 크레딧 발송 코드를 kotlin 으로 리팩토링하는 작업을 진행했다. 리팩토링이 필요한 코드는 총 1일, 7일, 30일 후에 만료되는 크레딧을 보유하고 있는 사용자에게 크레딧 만료 예정 알림톡을 보내주는 코드로 11000 ~ 14000건 정도를 매일 11시에 발송하는 코드이다. 1일 후 만료(5000 ~ 6000건) 7일 후 만료(5000 ~ 6000건) 30일 후 만료(1000 ~ 2000건) 코드를 확인해보니 만료 예정 크레딧을 받아오는 코드가 페이징 처리되어 있었고, 조회해온 Page 사이즈만큼의 크레딧에 대해 만료 예정 알림톡을 순차적으로 보내준 뒤, 반복적으로 다음 Page 리스트에 대해서도 동일 처리를 진행하는 코드로 파악이 되었다. 하지만, 100..

Spring 2023.03.12

Spring Batch - Job은 정말 실패한 시점부터 재실행될 수 있을까?

이번에는 Spring Batch 가 정말 실패한 시점부터 재실행되는지, 어떻게 실패한 지점부터 재실행될 수 있는지에 대해 알아보자. Spring Batch 가 아닌 주기적인 작업이 필요한 API 를 호출해 주는 방식의 스케줄러가 구현이 되어 있다고 가정해 보자. 만약, 스케줄러가 API 를 호출한 후 모종의 이유(에러 발생)에 의해 실행이 중단된 경우, 해당 처리를 성공적으로 완료시키기 위해선 동일한 호출을 다시 호출해야 하는 상황이 생긴다. 요청이 처리됨과 동시에 중단이 된거라면 반복 호출해도 크게 문제가 없을 수 있겠으나, 만약 처리해야 하는 10개의 데이터 중 5개만 처리하고, 중단된 거라면 반복 호출 시 불필요한 작업을 반복한다. 뿐만 아니라, 최상위가 아닌 Dao의 단위로 트랜잭션까지 걸어준 상..

Spring 2023.03.05

Spring Batch - JobParameters

JobParameters를 사용하기 위해선 반드시 @JobScope, @StepScope와 같은 어노테이션을 지정해 주어야 한다. @JobScope, @StepScope 각각의 어노테이션이 무엇인지 알아보기에 앞서. 저 Scope가 의미하는 것에 대해서 먼저 알아보도록 하자. Bean Scope Scope는 범위란 의미를 지니고 있다. 즉, bean 이 생성하고, 소멸하는 시점까지의 활동 영역으로 재해석될 수 있는데, Spring 에서는 아래와 같은 5가지의 기본 Bean Scope 가 제공된다. Singleton Scope: 가장 기본 유형으로 스프링 컨테이너 내에 하나의 인스턴스만 존재하며, 항상 동일한 인스턴스를 반환한다. Prototype Scope: 스프링 컨테이너 내에서 빈의 새로운 인스턴스가..

Spring 2023.02.26

Spring Batch를 적용해 보기에 앞서

Spring Batch가 무엇인가? 스프링 배치는 대용량 데이터의 처리를 돕는 배치 애플리케이션이다. 왜 Spring Batch를 사용해야 하는가? 사실 스스로도 Spring Batch(배치 애플리케이션)의 역할 및 기능을 알아보기 이전까지는 스케줄러 + 배치의 조합과 특정 스케줄러를 이용해 주기적으로 특정 API를 호출하도록 하는 것과의 차이에 대해 궁금해했었다. 이는 전적으로 배치에 대한 개념적인 이해의 부족이 초래한 결과이었는데, 사실 생각해 보면 어떤 반복 작업을 처리하기 위해 단순히 만들어 놓은 비즈니스 로직을 실행하기 위한 API 호출을 하는 것과 달리 배치 애플리케이션을 이용하는 것은 분명히 필요한 서비스 로직 외에 어떤 책임을 가지고 있을 거라 예상할 수 있다. 위에서도 거론했듯이 Spri..

Spring 2023.02.19