본문 바로가기

전체 글373

Offset Based Pagination 성능 이슈 해결하기 Offset Based Pagination 성능 이슈 해결하기기술 블로그의 게시글을 한번에 볼 수 있는 서비스를 운영하고 있습니다. 현재 많은 사용자가 이용하고 있는 건 아니지만, 앞으로 서비스를 지속적으로 유지하기 위해서는 지출되는 비용을 최대한 절감하는 것이 중요하다고 생각했어요.그 중에서도 데이터베이스 성능 이슈를 발견했었고, 이를 해결하고자 합니다.성능 이슈가 발생했던 시점에는, 아래와 같이 페이지 번호를 보여주고 있습니다.클라이언트가 페이지 번호를 클릭할 때마다, 데이터베이스 쿼리가 실행되는 속도를 확인해봤어요.사용자 경험 혹은 리소스 사용 측면에서 봤을 때, 원인을 찾아서 해결해야 하는 것이 중요하다고 생각했습니다.해당 포스팅에서는 데이터베이스 성능 이슈를 발견하고, 이를 개선하기 위해 시도.. 2024. 8. 30.
Cglib Proxy에 포함되지 않는 Final Method 모든 코드는 github를 참고해주세요.Cglib Proxy에 포함되지 않는 Final Method토이 프로젝트에서 Server Error 발생 시에 Slack으로 알림을 보내주도록 설정했었는데요.해당 설정을 사내에서 진행했던 프로젝트에 적용하려고 했습니다.(궁금하신 분들은 Spring AOP로 Slack 알람 구현 포스팅을 참고해주세요.)토이 프로젝트에서 적용했던 설정을 사내 프로젝트에 그대로 적용했지만,개발 서버에 정상적으로 배포 후, 제보를 받았어요.클라이언트에서 Server Error 응답을 받았지만,슬랙 채널로 알림이 오지 않는데요? 분명, local(로컬) 환경에서 테스트를 진행했었고, dev(개발) 환경에 정상적으로 배포되었는데 말이죠.디버깅을 해보면서 확인해보니, 특정 Exception .. 2024. 6. 29.
강결합된 구조를 이벤트 기반 약결합된 구조로 변경하기(with. Spring Event) 강결합된 구조를 이벤트 기반 구조로 변경하기(with. 트랜잭션 분리)쿠폰(Coupon) 발급 시 해당 회원에게 알림이(Notification) 발송되어야 하는 요구사항으로 인해 기존 프로덕션 코드가 수정되어야 했습니다.* 알림: 서비스 내 알림, 메일, SNS 알림 등을 의미합니다. 해당 요구사항을 파악 후 기존 쿠폰 서비스 객체에 알림 서비스 객체를 추가하는 방향을 고려했습니다. 그렇다면, 쿠폰 발급 시 알림이 발송되는 흐름은 다음과 같습니다. 하나의 트랜잭션으로 진행되다보니, 다음과 같은 문제점을 발견했습니다. 보조 업무인 알림 발송이 실패할 경우, 핵심 업무인 쿠폰 발급이 실패할 수 있다. 핵심 업무(Core Business): 쿠폰을 발급하는 로직보조 업무(Auxiliary Bu.. 2024. 5. 8.
대량 쿠폰 발급 시 Bulk Insert로 처리 시간 70% 단축 대량 쿠폰 발급 시 Bulk Insert로 처리 시간 70% 단축쿠폰 발급과 관련된 프로덕션 코드를 작성하면서,향후 서비스 규모가 커짐에 따라 쿠폰을 발급하는 대상 회원 수가 100명, 1,000명, 혹은 10,000명이 된다면 성능 이슈는 발생하지 않을까? 라는 고민을 하게 되었습니다.결과적으로 쿠폰의 발급 방식을 Single Insert에서 Bulk Insert으로 변경했더니, 아래 그래프와 같이 쿠폰 발급 처리 시간이 약 70% 단축되는 결과를 확인할 수 있었습니다.해당 포스팅에서는 70%라는 시간 단축하기까지의 과정을 소개합니다. 해당 글에서 사용되었던 모든 코드는 gitHub에서 확인하실 수 있습니다.아래 서버 환경은 참고해주시면 좋을 것 같습니다.Spring Boot: 2.7.1Spring .. 2024. 4. 27.
쿠폰 발급 시 동시성 제어를 위해 고려했던 4가지 방법 쿠폰 발급 시 동시성 제어를 위해 고려했던 4가지 방법 쿠폰 Entity에서 잔여 발급 횟수를 관리하고 있었습니다. 쿠폰 발급과 관련된 비즈니스 로직을 구현하면서 문득, 동시 다발적인 쿠폰 발급 요청이 올 경우 어떤 일이 벌어질지 궁금해졌습니다. 실제 운영환경에서 여러 Thread가 동시 다발적으로 쿠폰을 발급하기 위해서 데이터베이스에 접근할텐데, 고려해야할 문제는 없을까? 해당 포스팅에서는 동시성 문제를 해결하려고 고려했던 4가지 방법에 대해서 이야기 해보려고 합니다. 단일 Thread에서 쿠폰을 발급하는 상황 단일 Thread에서 동시성 문제를 고려할 필요가 없지만, 이후에 나올 내용과 연관되어 있기 떄문에 간단하게 쿠폰을 발급하는 상황을 살펴보겠습니다. 1) 트랜잭션 시작 2) 쿠폰을 발급하기 전,.. 2024. 4. 13.
테스트 코드에서 JPA의 dirty checking 모든 코드는 깃허브에 있습니다. 테스트 코드에서의 JPA의 dirty checking Spring Data Jpa를 사용하면서, 테스트 코드 실행 시 update 쿼리가 실행되지 않는 상황이 있었습니다. 결론적으로, dirty checking 기능이 제대로 동작하지 않는 상황에 대해서, 해결했던 내용을 기록했습니다. MemberService와 테스트 코드 JpaRepository 상속받는 MemberRepository 클래스를 선언하고, 이를 협력 객체로 두는 MemberService 클래스를 만들어서 Spring Bean으로 등록했습니다. 이 후 MemberService 레이어에 대한 테스트 코드를 작성하고자 했습니다. 이때, 테스트 환경은 아래와 같이 구성해 주었습니다. @DisplayName("회원.. 2024. 3. 23.
ATDD, 클린 코드 with Spring 과정을 통해 배운 인수 테스트(Acceptance Test) 인수 테스트(Acceptance Test)본 포스팅은 ATDD, 클린 코드 with Spring에서 경험한 E2E(API) 테스트 기반의 인수 테스트에 대한 내용을 소개합니다.독자분들에게 미리 말씀드립니다.인수 테스트가 만능이다?인수 테스트를 무조건 작성해야 한다?절대 아닙니다!!!인수 테스트란?인수 테스트에 대해 이야기하기 전, 먼저 테스트가 무엇인지 스스로 고민해볼 필요가 있을 것 같습니다.어떤 사람은 아래와 같이 생각할 수 있을 것 같습니다. 코드를 작성하고 검증하는 것 인수 테스트를 작성하기 시작한다면, 아래와 같이 생각해볼 수 있을 것 같습니다. 코드를 작성하기 전, 어떤 코드를 작성해야 하는지 TODO 리스트를 작성하는 것 이는 TDD(Test Driven Development)에서 실.. 2024. 3. 8.
아는 것에서 모르는 것으로 아는 것에서 모르는 것으로난관에 부딪혔을 때, Kent Beck 님의 명언을 통해 문제를 해결한 경험이 있습니다. 사실은 상향식, 하향식 둘 다 TDD의 프로세스를 효과적으로 설명해 줄 수 없다. ...만약 어떤 방향성을 가질 필요가 있다면 '아는 것에서 모르는 것으로(Known-to-unknown)' 방향이 유용할 것이다.우리가 어느 정도의 지식과 경험을 가지고 시작한다는 점, 개발하는 중에 새로운 것을 배우게 될 것임을 예상한다는 점 등을 암시한다.Test-Driven Development, Kent Beck TDD의 방향성 결정저는 ATTD, 클린 코드 with Spring 8기에 참여했었고, 미션을 진행했었어요. 미션의 주요 내용으로는 인수 테스트를 작성하고 기능을 구현하기 전에,TDD의.. 2024. 3. 3.
테스트를 위해 정의했던 Public 메서드 테스트를 위해 정의했던 Public 메서드 Service 레이어에 대한 테스트 코드를 작성을 위해 Mockito 라이브러리를 활용했다. 협력 객체인 Repository 레이어에 대한 Stubbing을 진행했는데, 실제 데이터베이스에서 저장된 후 반환되는 것이 아니기 때문에 실제 저장되어 있던 것처럼 구성을 해야했다. 이때, 주로 고민이 된던 것은 'Entity에 id는 어떻게 설정해줘야 하는 것인가?' 였다. 누구나 고민이 되는 내용이지 않을까.. 싶다. 아래는 게시글을 저장할 때, 필수로 포함되어야하는 카테고리 Entity 이다. // Category.java @Entity public class Category { @Id @GeneratedValue(strategy = GenerationType.ID.. 2024. 2. 13.