기술적 고민 7

RabbitMQ 다중 서버에서, 특정 컨슈머에게 메세지 큐 우선 전달하기

📕 개요기존 단일 도메인만 구동하던 서비스에서, 서버의 부담을 줄이기 위해 비동기로 처리 되는 부분을 보조 서버에서 처리하도록 변경하려 하였다.때문에, RabbitMQ 의 메세지를 보조 서버가 우선적으로 수신할 필요가 있었다. 🔍 RabbitMQRabbitMQ 는 기본적으로 메세지가 쌓이면, 해당 큐를 구독 하고 있는 어플리케이션에게 메세지를 전달(Push) 하는 방식으로 구성되어 있다.이때, 기본적으로는 라운드 로빈 방식으로 메세지를 균등하게 배분하도록 설정 되어 있으며 이러한 방식을 직접 커스텀 하기에는 많은 제약이 있었다.( ex. 특정 서버의 CPU/Memory 사용량이 많을 시 메세지를 배분하지 않도록 한다던가.. ) 또한, 인프라 자체의 설정을 변경하게 되면 모든 서비스에 이러한 영향이 전..

기술적 고민 2025.08.02

(MSA) 주문 및 결제에 이벤트 기반 SAGA 패턴을 활용한 이유

== 상황 ==현재 배달 서비스는 MSA 아키텍처로 아래와 같이 도메인이 구분 되어 있다.고객 도메인장바구니 도메인상품 도메인매장 도메인결제 도메인그리고 결제는 외부 PG 사의 API 를 활용하기에 주문 요청과 결제 성공이라는 요청을 구분해 전달 받아야하며 전체적인 순서는 아래와 같다.[ 주문 요청 ]주문 요청요청 검증결제 요청외부 PG사에서 결제 URL 및 TID 반환결제 성공시 결제 승인을 위한 Token 반환[ 결제 성공 ]결제 후 PG사에서 발급 받은 TID, Token 과 함께 결제 승인 요청결제 완료주문 데이터 저장 및 주문 성공== 문제 ==위와 같은 과정 중 외부PG 사의 정보는 직접적으로 관리할 수 없는 만큼 결제 완료 이전 과정에서 모든 검증이 마무리 되어야 하는 문제가 발생하였다.또한..

기술적 고민 2025.04.26

동시성 제어에 캐시와 분산락 Redisson 을 도입한 이유

= 상황 =이전 게시글에서 유효성 검증과 예약을 DB에 저장하는 예약 추가 로직을 RabbitMQ 를 도입하며 이를 아래와 같이 분리하게 되었다.유효성 검증 및 메세지 큐 전송 (Sender)메세지 큐 수신 후 DB에 저장 (Listener)( 이해를 위해 임의로 두 로직을 Sender, Listener 로 명하였음 )이러한 구조 변경을 통해 예약 순서 보장 , 처리량 증가, 데이터 유실 방지라는 이점을 얻었다.하지만 이후 서버가 증설되며 동시성 문제와, RabbitMQ의 메세지 처리 방식으로 인한 문제가 발생하였다.= 문제 =해당 서비스는 동일 시간대의 예약 가능 좌석이 제한되어 있기에, 메세지를 큐에 전송하기 전 DB 에서 해당 시간대에 예약이 가능한지 확인하는 과정을 거쳤다.그러나 이 과정에서 아래..

기술적 고민 2025.04.09

예약 관리 서비스에 RabbitMQ 를 도입하게 된 이유

현재 진행 중인 프로젝트에서는 하나의 매장에서 여러 고객을 관리하고, 고객 별 예약을 관리 해야만 한다. 예약은 등록 되어 있는 고객만이 가능하고, 동일 시간에 최대 예약 가능 갯수가 제한 되어 있다.이외에도 여러 부가적인 기능이 존재하지만, 가장 중요하게 바라봐야할 포인트는고객 등록예약 등록이라고 생각을 했다.한 명의 고객에 대한 등록은 단 한 번만 진행을 하며, 해당 데이터가 유실이 되면 예약을 포함한 다른 서비스를 이용할 수 없었고, 결국 동일한 고객의 정보를 재입력 하는 과정이 부정적인 사용자 경험으로 이어질 것이라 예상됐다.예약 등록은 데이터 유실 방지는 물론, 최대 갯수가 제한되어 있는 만큼 예약 순서를 보장해야 했고 잘못된 데이터가 입력될 경우 서비스에도 장애가 발생할 것이라 예상이 되었다...

기술적 고민 2025.03.26

데이터 유실 방지 - 외부 저장소(S3) 장애 대응

프로젝트를 진행하던 중, 외부 저장소 ( S3 ) 를 변경해야 하는 상황이 발생하였고 변경까지 오랜 시간이 소요되는 것이 아니었기에 서버를 실행 시켜둔 상태로 기존 S3 를 종료하고 새로운 S3를 반영하던 중, 회원 등록 API가 호출되며 사진 데이터가 유실되는 문제가 발생하였다.모든 프로젝트가 그러하겠지만, 해당 프로젝트는 실제 운영 중인 매장에서 사용하기 위해 개발 중인 만큼 데이터가 유실 되지 않는 것이 중요한 포인트였기에 대안을 생각하기로 하였다.현재 회원 등록 API의 요청 값은, 이름/성별/나이 그리고 이미지 URL 의 Json 데이터를 담은 req와 이미지 파일을 담은MultipartFile 형식의 file을 함께 전달 받고 있다. public ApiResult addCustomer( ..

기술적 고민 2025.03.04

무한스크롤에서 Offset 방식의 문제와 Keyset Pagination 사용 이유

프로젝트를 진행하던 중, 기존 페이징 처리가 되어있던 부분이 무한스크롤 방식으로 변경이 되었다.때문에 사용자에게 페이지 번호를 전달 받을 필요가 없었고 Jpa의 Pageable을 사용할 이유가 없었기에 다른 방법을 모색하게 되었다.Jpa Pageable 의 가장 큰 문제는 페이지 번호가 증가함에 따라 반환 시간이 증가한다는 점이다.이는 Pageable이 Offset 방식으로 동작하기 때문인데, 페이지 번호가 증가할 수록 앞선 페이지의 데이터를 스캔하고 버려야하기에 일정한 반환 시간을 보장할 수 없게 된다.아래는 Mysql 8.0 환경에 저장된 1100만 개의 데이터를 활용해 페이지 별 반환 시간을 테스트 해본 결과이다.데이터는 페이지당 10개 씩 읽어오도록 하였다.// 테스트 엔티티@Entity@Gett..

기술적 고민 2025.02.20

메타데이터를 이용한 객체 값 자동 생성 ( DatabaseMetaData )

테스트 코드 작성 중 객체 내부의 값을 랜덤으로 생성해주는 과정이 반복되어 이를 해결하고자 FixtureMonkey를 사용하게 되었다.다만 FixtureMonkey를 사용하기 위해서는 엔티티 내부에 어노테이션으로 @Size 등의 제약사항을 작성해주어야 했는데, 작성 중인 프로젝트에서는 Mybatis를 사용해 코드를 작성하는 만큼 @Size와 같은 어노테이션을 오직 FixtureMonkey 만을 위해 엔티티에 작성해야할 이유가 없다고 느껴졌다.또한 테스트 코드를 작성을 위해 기존 코드에 영향을 주는 것은 좋지 않다 판단하였기에, Mybatis에서 별도의 설정 없이 랜덤한 값을 생성할 수 있도록 직접 코드를 작성하기로 하였다.코드를 작성하기 전 중요하게 생각한 포인트는 아래와 같았다.기존 코드에 영향이 가지..

기술적 고민 2024.10.08