분류 전체보기 42

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

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

기술적 고민 2025.08.02

MSA 환경에서 왜 Kafka 를 활용하는 걸까?

📕 개요처음 MSA 아키텍처와 Kafka 를 접했을 당시, 관련 문서를 찾아보며 “MSA 아키텍처를 활용하면, Kafka 를 함께 사용해야 한다” 는 느낌의 글을 많이 접하게 되었다.하지만 대부분의 글에서는 Kafka 를 활용하는 이유를 “고가용성” 정도만 설명하고 있어, 기초 지식이 부족했던 당시에는 그 이유를 명확히 이해하기 어려웠던 기억이 있다.때문에 이번 글에서는, 직접 MSA 아키텍처와 Kafka를 활용해본 경험을 바탕으로,왜 Kafka 가 MSA 환경에서 사용되는지에 관해 정리해보고자 한다.🔍 MSA(Microservice Architecture)우선 이를 위해서는, MSA 아키텍처에 관해 알아야할 필요가 있다.MSA 는 간단히 말해, 하나의 어플리케이션을 위해 다수의 서비스가 동작하는 방..

카테고리 없음 2025.07.20

Gateway 없이 서비스 분리

개요기존 운영 중인 매장 관리 서비스는 단일 서버로 운영되고 있었지만, 요구사항이 증가함에 따라 서버의 부담이 점차 커지고 있었다.이러한 상황에서 매장 관리 외에 새로운 도메인에 대한 기획이 추가되었고, 도메인 별 서비스 분리의 필요성을 느끼게 되었다.때문에 본격적인 개발에 앞서, 우선 매장 관리 서비스를 분리하기로 결정하였다. 목표메인 서버 (매장 관리 도메인) 의 부담 경감클라이언트에게 단일 진입점 제공 상황매장 관리 서비스를 운영 중인 기존 서버는 여유 자원이 부족해, 새로운 서버를 추가로 구동할 수밖에 없는 상황이었다.그러나 비용적인 제약으로 인프라 변경이 불가능한, 어플리케이션 하나만 구동할 수 있는 수준의 서버를 임시로 확보하게 되었다.이로 인해 별도의 게이트웨이 서버를 구성할 수 없었고, 결..

Springboot 2025.07.05

Kafka 를 활용한 지연처리 (지연큐)

프로젝트 진행 중, 클라이언트에게 전달 받은 요청을 5분 이후에 처리해야 하는 지연 처리 기능이 필요하게 되었다.이를 위해 다양한 방안을 검토하였고, 최종적으로 Kafka 를 활용해 지연 처리를 구현하게 되었다.해당 글에서는 이러한 지연 처리 구현까지의 접근 방식과 고민 등을 정리하고자 한다. --------------------------------------------------- ⚠️ 상황클라이언트에게 전달 받는 요청을 5분 이후에 처리 해야 함해당 서비스는 다중 서버로 구성기본 메세지 큐로 Kafka 를 사용Redis 는 캐싱, 임시 데이터 저장 등 다용한 용도로 활용 중--------------------------------------------------- 🧪 시도 RabbitMQ , SQ..

Springboot 2025.06.21

(AOP) 메세지 큐 요청/응답 로깅

이전 Filter 를 활용하여 Http 요청과 응답 값에 대한 로깅을 진행했었다.하지만, RabbitMQ 와 Kafka 등을 활용하게 되며 Http 요청 이외의 값에도 로깅이 필요하게 되었고, 최종적으로 AOP 를 활용해 이러한 코드를 구현하게 되었다.( 로깅을 위해서는 Filter ,Interceptor 를 활용할 수도 있으나, 이들은 Http 요청만을 가로챌 수 있다는 문제가 존재해 선택하지 않았다. )AOP 에서는 구현한 코드(메소드)를 어떤 시점에 작동시킬지 아래와 같은 메소드를 활용해 지정할 수 있다.Before 메소드를 실행하기 전 작동After메소드를 실행 후 작동AfterReturn메소드가 [정상] 실행 후 작동 ( 반환 값을 가져올 수 있음 )AfterThrowing메소드가 예외 처리 되..

Log 2025.05.11

(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