Spring Boot와 JPA(HIbernate)를 사용하면서 Entity 에 Set이나 Map 같은 컬렉션을 사용하시나요?오늘은 JPA 사용 시 Set 을 사용하면서 발생한 ClassCastException에 대해서 정리하고자 합니다.1. 문제상황오늘 Spring Data JPA를 사용하는 환경에서 @OneToMany로 Set 컬렉션을 사용하다가 다음과 같은 에러를 만나게 되었습니다.java.lang.ClassCastException: class java.util.HashSet cannot be cast to class org.hibernate.collection.spi.PersistentCollection Hashset은 Hibernate의 PersistentCollection으로 전환 될 수 없음..
해당 내용에 대한 예시코드는 [깃허브 예시코드] 에서 확인 하실 수 있습니다.확장함수란코틀린의 확장 함수(Extension Function)는 기존 클래스의 소스 코드를 수정하거나 상속받지 않고, 마치 그 클래스의 멤버 메소드인 것처럼 새로운 함수를 추가할 수 있는 기능입니다.주요 특징기존 클래스 확장: 외부 라이브러리나 수정 불가능한 클래스에도 새로운 기능 추가 가능정적 바인딩: 컴파일 시점에 호출되는 함수가 결정됨접근 제한: 클래스의 public 멤버에만 접근 가능구현 방법fun 클래스명.함수명(파라미터): 반환타입 { // 함수 본문}활용 예시외부 라이브러리 클래스에 추가 기능 제공기본 클래스에 자주 쓰는 유틸리티 함수 정의코드의 재사용성과 가독성 향상리팩토링과 확장 함수 도입 배경프로젝트를..
안녕하세요. 이번 글에서는 비동기 메시지 전송 시 데이터 일관성을 유지하기 위한 효과적인 접근법인 Outbox Pattern에 대해서 알아보겠습니다.해당 내용에 대한 예시코드는 [깃허브 예시코드] 에서 확인 하실 수 있습니다.Outbox Pattern이란?Outbox Pattern(아웃박스 패턴)은 데이터베이스 트랜잭션과 메시지 브로커 간의 데이터 일관성을 보장하기 위해 사용하는 설계 패턴입니다. 특히 마이크로서비스 아키텍처(MSA)에서 데이터 변경 이벤트를 안전하게 외부 시스템에 안정적으로 전달하거나, 응답 여부가 크게 중요하지 않은 HTTP 비동기 호출 작업의 기록 추적에도 활용할 수 있습니다.Outbox Pattern의 필요성먼저, 분산 시스템에서는 데이터베이스의 상태 변경과 메시지 브로커로의 이벤..
배경MySQL에서 복합 인덱스를 지정하면 Where 절에는 복합 인덱스에 순서에 맞게 조건 절을 지정을 해주어야 의도한대로 동작하는 것으로 이해를 하고 있었습니다. 그런데, 어느 날 오랜만에 만난 개발자 지인분께서 갑자기 이런 말을 해주시는겁니다."형, 그거 알아? 복합 인덱스를 지정하고 MySQL 컬럼 순서를 순서대로 지정하지 않아도 알아서 조건 절을 최적화해서 인덱스를 태울 수 있도록 바꿔준다?"진짜. 이 말이 나올 수 밖에 없다. "그게 진짜에요?" 나도 모르는 사이에 놓쳤을 수 있고, 만약에 진짜 된다면 정말 좋은 기능이기에 얘기를 듣고 넘어가는 것이 아닌 직접 테스트를 진행해봤습니다. 환경 준비먼저, 테스트를 진행하기 위한 적절한 데이터 양을 가진 테이블이 필요하기때문에 TEST용 mysql s..
배경최근 사내 OpenAPI에 Rate Limiter를 적용하면서, 분산 환경에서 가장 구현이 간편한 Fixed Window Rate Limiter를 설계하고 도입하였습니다. Rate Limiter에는 여러 방식이 존재하는데, 이번 기회를 통해 각 방식의 개념과 특징을 정리하고자 합니다.Rate Limiter AlgorithmToken BucketToken Bucket은 일정 개수의 토큰을 저장하는 버킷(Bucket)을 이용하여 요청을 제어하는 알고리즘입니다. API 요청을 처리하려면 버킷에 남아 있는 토큰이 필요하며, 토큰이 모두 소진되면 추가 요청은 제한됩니다.동작 방식토큰 생성 방식토큰은 1 / 제한 요청량을 단위로 생성됩니다. 예를 들어서, 1분당 10개를 제한한다고 하면 6초에 1개씩 생성합니다..
배경사내 OpenAPI에 RateLimiter를 추가하면서 테스트를 강화하고 회귀 오류를 방지하기 위해 철저한 검증을 진행했습니다. 그럼에도 불구하고 예상치 못한 장애가 발생했습니다.회귀 오류를 방지하기 위해서 테스트 코드를 강화했음에도 불구하고 테스트에서 장애가 검출되지 않는 이유는 무엇이었을까요?결론부터 말씀을 드리자면, 사내에서는 OpenAPI 요청 서버와 인증 서버를 분리하여 운영하고 있는데, 테스트 환경에서 네트워크 I/O 발생 부분을 Mocking 처리한 것이 원인이었습니다. 그리고, 실제 디버깅을 하면서 문제를 추적하는 과정에서 FeignClient의 @SpringQueryMap을 사용한 특정 요청이 실패한다는 사실을 발견했습니다.개발 환경Java Version : 14Spring Boot ..
서론데이터 통신 비용 절감의 필요성안녕하세요. 최근에 환율이 올라가게 되면서 자연스럽게 서버의 지출 비용이 늘어나게 되었습니다. 아래 사진은 최근 6개월간의 환율 변동입니다.회사에서는 불필요한 비용 지출이 없는지 점검하는 시간을 가졌습니다. 이 과정에서 데이터 전송 비용에서 이상치 데이터가 발견되었고, 해당 원인을 분석하고 개선하는 업무를 맡게 되었습니다. 이번 글에서는 그 과정과 해결 방안을 공유하고자 합니다.비용이 발생하는 주요 원인클라우드 비용을 추적하기 위해 메가존에서 제공하는 Hyperbilling 서비스를 사용하고 있습니다. 해당 서비스에서 특정 리소스의 Out 대비 비용이 유독 높게 발생하고 있음을 확인했습니다.특히 비용이 발생하는 카테고리는 APN2-DataTransfer-Out-Bytes..
트렌비에서는 대부분의 서버가 분산된 EKS 환경에서 운영되고 있습니다. 하지만, 새로운 프로젝트를 만들 때에 분산 환경을 위한 분산 락 설정을 매 번 추가해주어야 하는 번거로움과 레거시 시스템에서는 분산 환경을 충분히 고려하지 못한 경우가 있어 동시성 문제가 발생하는 경우가 종종 있었습니다. 이를 해결하기 위해, 사내 공통 분산 락 라이브러리를 개발하자는 아이디어를 팀장님에게 제안하였고 자유롭게 만들어 볼 수 있는 기회를 주어서 제작해보게 되었습니다. 분산 락Java와 Kotlin에서는 Monitor 인터페이스로 ReentrantLock, synchronized 키워드 등을 통해 락을 관리할 수 있습니다. 하지만 이러한 방식은 인메모리에서만 작동하여 분산 환경에서는 적용하기 어렵습니다. 예를 들어, 클라..