목록분류 전체보기 (100)
영호
PR 링크: 링크들어가면서진행했던 프로젝트에서 이벤트를 기반으로 핵심 도메인 로직과 이에 따른 부가로직을 이벤트로 분리하였습니다. 그러나 기존의 구조에선 도메인 완료 이벤트에 따른 부가로직의 수행까진 보장하지 못합니다. 핵심 도메인 로직: 쿠폰에 스탬프 적립부가 로직: 스탬프 적립 시 방문 기록 저장기존 구조2번 과정(방문 기록 저장)이 실패하면 스탬프는 적립 되었지만 이에 해당하는 방문 기록이 없어져 데이터 정합성이 틀어집니다. 즉, 스탬프 적립 이벤트가 유실됩니다.문제 상황[도메인 로직 완료 이벤트 유실]위에서 설명했듯이 스탬프 적립 이벤트에 따른 부가기능을 수행하는 로직 실패 시 데이터 정합이 틀어지는 문제가 존재합니다. 스탬프 적립 시 부가로직은 스탬프 적립 알림, 방문 기록 추가 등이 있습니다..
멀티모듈로 분리한 이유 기존 프로젝트는 단일모듈로 구성되어 있어 코드 변경 시 전체 코드가 컴파일, 배포되는 구조입니다. 현재 프로젝트에서는 크게 2가지 영역이 있습니다. 주기적으로 외부 api 를 호출해 주차장 잔여 좌석을 갱신하는 스케줄러 spring mvc 를 활용한 어플리케이션 코드 스케줄러의 코드 변경은 어플리케이션 코드에 전혀 영향이 없습니다. 그러나 단일 모듈 구조에서는 스케줄러 코드가 변경되어도 전체 코드가 컴파일, 배포 됩니다. 현재 단일 모듈의 단점 스케줄러 코드의 변경으로 전혀 영향이 없는 어플리케이션 코드도 재배포 됩니다. 변경 주기가 다른 스케줄러, 어플리케이션 코드가 항상 같이 재배포되는 구조입니다. CI 속도가 불필요하게 오래 걸린다. 스케줄러 코드 변경으로 인해 전체 코드 테..
들어가면서 프로젝트를 진행하면서 인증코드를 redis 로 관리했습니다. 인증코드는 3분이란 유효시간이 있고 유효시간이 지난 인증코드로 인증 요청을 하면 실패해야 합니다. redis 는 메모리 기반이기 때문에 유효하지 않은 데이터는 제거하여 유효한 데이터만 저장하고 싶었기 때문에 만료된 인증코드를 어떻게 바로바로 제거할지 고민한 과정을 포스팅 할 예정입니다. redis 의 Set ex 파라미터 활용 redis 에는 다양한 command 가 있고, 그 중 key 를 저장하면서 만료시간을 설정할 수 있습니다. redis 의 ttl 만료된 키 삭제 메커니즘 redis 는 만료된 키를 삭제하는 2가지의 메커니즘이 있습니다. 만료된 key 접근 시 삭제 일정 주기로 ttl 이 설정된 키를 선정해 만료된 key 를 ..
들어가며, 전에 참여했던 카페 쿠폰 서비스의 쿠폰에 스탬프를 적립하는 로직에서 동시성 이슈를 발견하여 이를 해결하기 위해 고민한 과정을 정리하려고 합니다. 현재 문제점 방어로직이 없다 스탬프 적립 요청 시 {어느 쿠폰}에 {몇 개의 스탬프}를 적립 할지, 인증 토큰에 대한 인자만 받고 있습니다. 이로 인해, 네트워크 지연 등에 대한 재시도로 인해 동일한 쿠폰에 대한 스탬프 적립 요청이 2번 들어오면 2배의 스탬프가 적립됩니다. 즉, 중복 적립 문제가 발생합니다. 기존 API 대략적인 구조 POST coupon/{couponId} BODY int: stampCount 원하는 결과 흔히 말하는 동시성, 따닥 이슈 발생 시 하나의 요청만 유효하게 처리하길 원했습니다. 이를 만족하기 위해 어떤 고민을 했는지 작..
들어가면서 이전 포스팅에서 구현한 namedLock 에 이어서 multi-datasource 와 AOP 를 적용하는 과정에 대해 적어보겠습니다. 전체 코드 github입니다. Multi-datasource 가 필요한 이유 namedLock 을 얻는 datasource 와 다른 비즈니스 로직을 수행하기 위한 datasource가 동일한 경우 커넥션이 부족할 수 있습니다. 만약, namedLock 을 얻으려는 요청이 갑자기 몰린다고 생각해봅시다. 그러면 해당 요청에 할당된 커넥션은namedLock 을 얻기 위해 기다릴 것입니다. 물론 timeout 을 설정해서 대기 시간을 조절할 수 있지만, 해당 시간 동안 비즈니스 로직 수행에 필요한 커넥션을 사용한다는 사실은 변하지 않습니다. 이러한 이유로 namedLo..
들어가면서 분산서버에서 발생하는 동시성 문제를 어떻게 해결할 수 있을까 고민하다가 namedLock 이란 개념에 대해 알게되어 이를 간단하게 구현해본 과정을 정리하려고 합니다. 혹시 잘못된 부분 있으면 언제든지 댓글 달아주시면 감사하겠습니다~ 전체코드 주소입니다. 다음 포스팅 (AOP, multi-datasource 적용) 예제 상황 수강신청 상황을 예제로 사용할 예정입니다. 정원이 있는 강의에 여러 명의 사용자가 수강신청 요청을 보낼 때, 강의 정원 만큼만 수강신청이 가능한 상황입니다. 물론 수강신청은 순서도 중요하지만 이번 포스팅에선 동시성 제어에만 초점을 맞춰주시면 감사하겠습니다. Lecture 는 강의 엔티티이고 강의 정원 (restCount) 필드를 가지고 있습니다. LectureStudent ..
들어가면서 평소 길어진 빌드 시간을 개선하기 위해 방법을 찾아보다가 Junit 병렬 실행에 대해 알게됐고 이를 적용해봤습니다. 이 글에서는 Junit 병렬 실행 설정을 통해 테스트 실행 시간을 줄인 방법에 대해서 작성해보려고 합니다. 설정 방법 junit-platform.properties 파일을 생성해서 병렬 실행 설정을 해주면 됩니다. junit.jupiter.execution.parallel.enabled=true junit.jupiter.execution.parallel.mode.classes.default = concurrent junit.jupiter.execution.parallel.config.strategy=fixed junit.jupiter.execution.parallel.config..
들어가면서 이번 글에서는 프로젝트를 진행하며 엔티티 구조를 변경해 로직 복잡성을 낮추고, 쿼리를 개선한 경험을 작성하려고 합니다. 상황 및 엔티티 구조 설명 상황 설명 저희 프로젝트는 개인 카페의 쿠폰을 한 곳에서 관리해주는 서비스 입니다. 여기에 더불어 카페 사장님은 쿠폰의 디자인, 쿠폰에 찍히는 스탬프의 위치를 모두 커스텀 할 수 있습니다. 그리고 발급된 쿠폰은 발급 당시의 이미지 정보를 토대로 보여지게 됩니다. A쿠폰 발급 후 사장님이 카페의 쿠폰 이미지를 변경해도 A쿠폰은 발급 당시의 이미지로 보여집니다. 즉, 쿠폰은 발급 당시 이미지, 스탬프 위치 정보를 적용합니다. 엔티티 구조 설명 위 요구사항을 만족하기 위해 카페 별 쿠폰 정보를 저장하는 복사 테이블을 만들었습니다. 그 이유는 당시 저희는 ..