전체 글 37

(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

Content-Type 'application/octet-stream' is not supported 원인 및 해결 방법

[2025-02-03 22:48:44.371] [http-nio-8080-exec-8] [8706cf15-ff91-49be-98c7-236cb49d64c6] ERROR [.error.GlobalExceptionHandler.handleException:25 ] - Content-Type 'application/octet-stream' is not supported[2025-02-03 22:48:44.372] [http-nio-8080-exec-8] [8706cf15-ff91-49be-98c7-236cb49d64c6] ERROR [.error.GlobalExceptionHandler.handleException:26 ] - Exception : org.springframework.web.HttpMediaT..

Springboot 2025.02.05

스프링부트 통합 테스트 코드 작성법 및 예시( TestRestTemplate , MockMVC , WebTestClient 차이점 및 선택 방법) given-when-then

당연하겠지만, 모든 코드는 작성 후 의도에 맞게 정상 작동하는지 확인하는 과정을 거쳐야만 한다.정말 간단한 코드라도 예상치 못 한 부분에서 문제가 발생할 수 있기에 이를 확인해주는 것이 정말 중요한데Swagger 나, Postman 등을 활용하여 직접 값을 입력해 확인해보는 과정을 거쳐도 되지만 가능하면 테스트 코드를 통해 확인하는 것이 효율적이다.테스트 코드를 작성하기 전, 어떠한 환경에서 어떠한 목적을 갖고 이를 작성할지 정해야만 한다.기본적으로 코드의 전체적인 테스트를 한다는 목적은 변하지 않지만, 예를 들어빠른 시간 내에 최소한의 테스트만을 위해 , 시간이 소요되더라도 완벽한 테스트를 위해 등상세한 목적에 맞춰 작성법이 달라지기에 이를 확실히 하고 작성을 시작하면 되겠다.이번 통합 테스트는,하나의..

Springboot 2025.01.28

embedded redis 의존성 및 사용법 ( 맥 환경에서 오류 나는 이유 ) springboot

테스트 코드를 작성하던 중, 하나의 Redis로 테스트 코드와 개발을 함께 진행하고 있다는 것을 뒤늦게 발견하였다.테스트 환경에서는 mysql이 아닌 h2를 이용하기에 redis 또한 분리해야 된다는 것을 잊고 있었고 현재까지 큰 문제는 없었지만, 이후 정확한 테스트를 위해 DB를 분리하기로 하였다.현재는 아래와 같은 순서로 서버에 배포되기에, 서버와 로컬 환경에서는 내부적으로 redis를 띄워 사용할 수 있으나, gitAction 환경에서는 별도로 처리해주어야했기에 어떤 환경에서든 사용할 수 있도록 스프링부트 내부에서 redis를 띄우기로 하였다.로컬 → gitAction → server 처음 떠올렸던 방법은 3가지였는데,gitAction 환경에서 테스트 전용 redis를 구동embedded redis..

Redis 2025.01.07

gitAction springboot build 실패 오류 메세지 ( index.html ) github 에서 로그로 띄워 확인 하기

github를 이용하는 개발자들이라면 gitAction이라는 단어를 들어본 적이 있을 것이고 , 아마 많은 분들이 CI/CD 등을 위해 실제 사용해본 경험 또한 있을 것이라 생각한다.gitAction은 jenkins와 같이 직접 서버를 띄워 설정 하지 않아도 간편하게 이를 활용할 수 있기에 더욱 접근성이 좋고 편리하다는 강점이 있는데, 이러한 장점이 단점으로 다가오는 경우도 분명 존재한다.현재 진행 중인 프로젝트에서는 gitAction을 이용해 ./gradlew build 명령어를 실행하고 이를 성공하면 서버에 배포하는 과정을 거치고 있는데, 이상하게 local에서는 성공하는 케이스가 gitAction에서는 실패하는 문제가 발생하였다.때문에 무엇이 문제인지 파악하기 위해 로그를 확인하려 했으나, gitA..

GitAction 2024.12.23

서버(AWS) ssh 접근 키 .pem 분실시 서버 접근 및 복구 방법

특별한 상황이 아닌 이상, 보안을 위해 서버에 접근하기 위한 .pem 을 생성하곤 한다.이러한 Key는 분실시 더이상 ssh 로 서버에 접근할 수가 없기에 많은 이들이 모든 데이터를 버리고 새롭게 서버를 생성하거나, 혹은 기존 서버의 볼륨 (디스크) 만을 추출하여 새로운 서버에 적용하는 등의 방법을 선택한다.다만, 어떠한 방식으로든 서버에 접근할 수만 있다면 이러한 과정을 거치지 않고도 간편하게 키를 복구할 수 있는데 ( 정확하게는 새로 생성하는 과정이다 )정말 다행히도 AWS 에서는 이러한 서버를 ssh 이외의 방법으로 접근할 수 있도록 지원하고 있다.  위와 같은 과정을 거쳐 서버에 접근하였다면, 기존 분실한 Key 를 삭제하고 새로운 Key로 교체하는 과정을 거치기 위해 우선 로컬 환경으로 돌아와 ..

등등 2024.12.03