Spring Data JPA unexpected row count 삭제 오류 해결 방법

Spring Data JPA에서 엔티티를 삭제할 때 Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 오류가 발생하는 경우가 있다. DELETE SQL 자체는 단순하지만, Hibernate가 예상한 삭제 건수와 데이터베이스가 반환한 삭제 건수가 다르면 예외로 처리될 수 있다. 특히 동일한 데이터를 여러 요청이 삭제하거나, 조회한 엔티티가 실제 DELETE 실행 전에 다른 … 더 읽기

Redis 캐싱 전략 완벽 가이드: Look Aside vs Write Back 및 Spring Boot @Cacheable 실무 적용

백엔드 시스템의 성능을 최적화하는 과정에서 가장 가성비가 좋고 즉각적인 효과를 볼 수 있는 기술은 단연 ‘캐싱(Caching)‘입니다. 관계형 데이터베이스(RDBMS)는 디스크 I/O를 기반으로 동작하기 때문에 물리적인 속도의 한계가 명확하며, 트래픽이 몰릴 경우 병목 현상의 주범이 됩니다. 반면 Redis와 같은 인메모리(In-Memory) 저장소는 RAM에 데이터를 저장하고 처리하므로, 디스크보다 수백 배 빠른 접근 속도를 제공합니다. 하지만 “Redis를 도입했다”는 사실만으로 모든 … 더 읽기

Redis 분산 락 완벽 가이드: Redisson 아키텍처 분석 및 동시성 이슈 해결

지난 포스팅에서 우리는 JPA의 낙관적 락과 비관적 락을 통해 데이터베이스 레벨에서 동시성 문제를 해결하는 방법을 배웠습니다. 하지만 서비스의 규모가 커져 서버가 한 대가 아닌 여러 대(Scale-out)가 되는 순간, 자바의 synchronized 키워드나 단일 애플리케이션 내부의 락은 무용지물이 됩니다. 각 서버의 메모리가 독립적이기 때문입니다. 물론 데이터베이스의 비관적 락(Pessimistic Lock)을 사용하면 서버가 여러 대여도 동시성을 제어할 수 있습니다. 하지만 DB … 더 읽기

JPA 동시성 이슈 해결: 낙관적 락 vs 비관적 락 완벽 비교 및 실무 가이드

Spring

백엔드 개발자가 로컬 환경에서 혼자 개발하고 테스트할 때는 절대 마주칠 수 없는, 하지만 운영 환경에 배포되자마자 서비스의 신뢰도를 바닥으로 떨어뜨리는 무서운 문제가 있습니다. 바로 ‘동시성 이슈(Concurrency Issue)‘입니다. 가장 대표적인 예가 ‘재고 관리 시스템‘입니다. 재고가 딱 1개 남은 인기 상품이 있다고 가정해 봅시다. 이 상품을 구매하기 위해 사용자 A와 사용자 B가 0.001초의 차이로 동시에 ‘구매’ 버튼을 … 더 읽기

JPA 벌크 연산(Bulk Operation) 완벽 가이드: @Modifying과 영속성 컨텍스트 동기화 전략

Spring

지난 포스팅에서 우리는 JPA의 꽃이라 불리는 변경 감지(Dirty Checking)에 대해 알아보았습니다. 트랜잭션 안에서 엔티티의 값을 수정하기만 하면, JPA가 알아서 UPDATE 쿼리를 날려주는 편리한 기능이었습니다. 하지만 이 변경 감지에는 치명적인 성능적 한계가 존재합니다. 바로 “대량의 데이터를 수정해야 할 때“입니다. 예를 들어, 쇼핑몰 서비스에서 “모든 상품의 가격을 10% 인상한다”라는 요구사항이 있다고 가정해 봅시다. 상품이 100만 개라면 어떻게 될까요? 변경 … 더 읽기

JPA 영속성 컨텍스트 완벽 해부: 1차 캐시와 변경 감지(Dirty Checking) 원리

Spring

Spring Data JPA를 사용하다 보면 신기한 경험을 하게 됩니다. 데이터베이스에서 객체를 조회한 후, setter 메서드로 값을 변경하기만 했는데 별도로 save()나 update() 메서드를 호출하지 않아도 DB에 변경 사항이 반영되는 현상입니다. 마치 자바 컬렉션에서 객체를 꺼내 필드를 수정한 것처럼 자연스럽게 동작합니다. 또한, 같은 ID를 가진 엔티티를 두 번 조회했는데 쿼리 로그에는 SELECT 문이 한 번만 찍히는 경우도 목격하게 됩니다. 이러한 JPA의 ‘마법’ 같은 기능 … 더 읽기

JPA 성능 최적화의 핵심: Lazy Loading(지연 로딩) vs Eager Loading(즉시 로딩) 완벽 비교와 실무 가이드

Spring

소프트웨어 개발, 특히 데이터베이스를 다루는 백엔드 개발이나 사용자 경험을 중시하는 프론트엔드 개발에서 “성능 최적화”는 영원한 숙제와도 같습니다. 우리는 항상 “어떻게 하면 더 빠르게 데이터를 보여줄 수 있을까?”를 고민합니다. 하지만 아이러니하게도 무조건 빨리, 모든 것을 미리 가져오는 것이 항상 정답은 아닙니다. 때로는 필요한 순간까지 기다렸다가 가져오는 것이 전체 시스템의 리소스를 절약하고 체감 속도를 높이는 지름길이 되기도 … 더 읽기

OEIV : OpenEntityManagerInView

OpenEntityManagerInView (OEIV)는 Spring Framework와 JPA(Java Persistence API)를 함께 사용할 때 발생하는 지연 로딩(Lazy Loading) 문제를 웹 환경에서 해결하기 위해 설계된 패턴이자 Spring에서 제공하는 인터셉터(Interceptor) 1. OEIV의 개념 및 목적 목적 웹 요청 처리 과정 전체에서 JPA의 EntityManager를 열린 상태로 유지하여, View 렌더링 단계에서 발생하는 지연 로딩 예외(Lazy Loading Exception)를 방지 작동 방식 Spring의 DispatcherServlet이 HTTP 요청을 받으면, OpenEntityManagerInViewInterceptor가 트랜잭션과 관계없이 EntityManager를 … 더 읽기