본문 바로가기

JPA15

OSIV JPA를 쓰면서 어디선가 많이 들어봤는데.. OSIV가 뭐지? 이번글은 OSIV에 대해 알아보겠습니다. OSIVOSIV(Open Session in View)는 영속성 컨텍스트를 뷰까지 유지하는 기능입니다.즉, 영속성 컨텍스트가 닫히기 전에 컨트롤러나 뷰에서도 엔티티를 영속 상태로 유지할 수 있어, 지연 로딩이 가능해집니다. OSIV는 과거에 지원했던 방식과 현재 Spring에서 지원하는 방식에 차이점이 존재합니다.먼저, 과거에 사용되었던 OSIV 방식에 대해서 살펴보겠습니다.  과거에 사용된 OSIV 과거에 사용되었던 OSIV 방식은 요청 단위 트랜잭션을 유지하는 방식이였습니다.즉, HTTP 요청이 시작될 때 트랜잭션을 열고, 응답이 완료되는 경우 트랜잭션을 닫는 구조였습니다. 흐름을 이미지로 나타내면.. 2025. 2. 21.
프록시 객체 JPA는 어떻게 지연 로딩(Lazy Loading)을 사용할 수 있을까요? 이번 글은 JPA의 프록시에 대해 알아보겠습니다. 프록시가 무엇일까요? 프록시프록시는 실제 엔티티 객체 대신 데이터베이스 조회를 지연시킬 수 있는 가짜 객체입니다.  데이터베이스 조회를 지연시켜야 하는 이유가 뭘까요? 데이터베이스 조회를 지연시키지 않은 경우엔 하나의 엔티티를 조회할때, 그 엔티티와 연관된 다른 엔티티들의 데이터도 함께 조회하게 됩니다. 만약, 조회한 엔티티만 사용되고 연관된 다른 엔티티들은 필요하지 않은 경우, 실제로 사용되지 않는 데이터까지 불필요하게 조회하게 됩니다. 이능 성능 저하로 이어질 수 있고, 불필요한 리소스 낭비를 초래할 수 있습니다. 이 상황을 코드를 통해 알아보겠습니다.Member엔티티와 Tea.. 2025. 2. 20.
영속성 전이 & 고아 객체 매번 연관된 엔티티를 영속 상태로 만들어야 할까? 이번 글은 영속성 전이와 고아 객체에 대해 알아보겠습니다. 연관된 엔티티를 영속화하고 싶을때, 어떻게 해야 할까요? 코드를 통해 살펴보겠습니다.Team 엔티티와 Member엔티티가 아래 코드와 같이 일대다 관계를 맺고 있습니다.(Team 엔티티를 부모 엔티티, Member 엔티티를 자식 엔티티를 의미합니다.) Team 엔티티와 Member엔티티를 저장하는 테스트 코드는 아래와 같습니다.(참고, member엔티티의 setTeam 메서드는 연관관계 편의 메서드입니다.)@SpringBootTestpublic class PersistencePropagationTest { @PersistenceContext private EntityManager em;.. 2025. 2. 19.
N+1 문제 해결 전략 @BatchSize편 "N+1문제를 해결하는 전략엔 어떤 것이 있을까요?" 이번글은 N+1 문제에 대한 소개와 이 문제를 해결할 수 있는 방법 중 하나인 @BatchSize 어노테이션을 활용하는 방법에 대해 알아보겠습니다. N+1 문제란 무엇일까요? N+1 문제N+1 문제는 데이터베이스에서 연관된 엔티티를 조회할 때, 의도하지 않게 추가적인 쿼리가 발생하는 성능 이슈를 의미합니다.하나의 엔티티를 조회하는 단일 쿼리에 대해, 추가로 N개의 쿼리가 실행되는 현상을 의미합니다. 의도하지 않게 추가적인 쿼리가 다량 발생한다는게 무슨 의미일까요? JPA에서는 연관된 엔티티를 지연 로딩(Lazy Loading)으로 설정하는 경우 프록시 객체를 활용해서 해당 엔티티가 실제로 필요할 때 조회하도록 합니다.하지만 이를 반복문에서 사용할 경우.. 2025. 2. 10.
JPA 비관적 락 데이터베이스 READ COMMITE 격리 수준에서 발생하는NON-REPEATABLE READ와 PHANTOM READ 문제는 어떻게 해결할까?  이번글은 데이터베이스 READ COMMITED 격리 수준에서 발생하는 NON-REPEATABLE 문제와, 이를 해결하는 방법중 하나인 JPA에서 제공하는 비관적 락에 대해 알아보겠습니다. "NON-REPEATABLE READ 문제는 뭔가요?" 한 트랜잭션 내에서 같은 쿼리를 두 번 실행했을 때 결과가 다르게 오는 문제입니다. "PHANTOM READ 문제는 뭔가요?" 한 트랜잭션이 같은 쿼리를 두 번 실행할 때, 첫 번째 쿼리에는 없던 유령 레코드가 두 번째 쿼리에서 나타는 문제입니다. "NON-REPEATABLE READ & PHANTOM READ 문제가 발생.. 2025. 2. 7.
JPA 낙관적 락 데이터베이스 READ COMMITED 격리 수준에서동시에 같은 데이터를 조회하고 수정하는 경우 어떻게 되나요?  이번글은 데이터베이스 READ COMMITED 격리 수준에서 발생하는 갱신 손실(Lost Update) 문제와, 이를 해결하는 방법중 하나인 JPA에서 제공하는 낙관적 락에 대해 알아보겠습니다. READ COMMITED 격리 수준에서 동시에 같은 데이터를 조회하고 수정하는 경우 어떻게 될까요? 예를 들어, 두 트랜잭션 A와 B가 있다고 가정해 보겠습니다.두 트랜잭션이 동시에 동일한 데이터를 조회한 후, 먼저 A가 데이터를 수정하고 커밋합니다. 이후에 B가 기존에 조회한 데이터를 기반으로 수정하고 커밋하면, A의 수정 내용은 B의 수정 내용으로 덮여씌워집니다. 이처럼 A의 변경 사항이 사라지는 .. 2025. 2. 6.
JPA와 읽기 전용 쿼리 "딱 한번만 조회하는 데이터에 JPA의 변경 감지 기능이 필요할까?"  이번 글은 JPA와 일회성 읽기 전용 쿼리의 관계에 대해서 소개하고, Spring에서 사용되는 @Transactional(readonly = true)를 알아보겠습니다. JPA의 변경 감지 기능은 어떻게 동작하나요? JPA 변경 감지 동작 원리JPA의 변경 감지(dirty checking) 동작 원리는 영속성 컨텍스트가 관리하는 엔티티의 변경을 감지하는 메커니즘입니다.이를 위해 초기 상태의 스냅샷(snapshot) 을 유지하며, 트랜잭션이 커밋되기 전에 현재 엔티티 상태와 비교하여 변경된 필드가 있는 경우 자동으로 update 쿼리를 생성하므로, 개발자가 직접 update 쿼리를 실행할 필요가 없습니다. 변경 감지 기능 너무 편리한데.. 2025. 2. 5.
find 메서드와 1차 캐시의 관계 "find() 메서드는 언제 select 쿼리문이 나가는걸까?" 이번 글에서는 JPA에서 데이터를 조회할 때 사용되는 find() 메서드와 1차 캐시(영속성 컨텍스트)의 관계에 대해 알아보겠습니다. find() 메서드는 어떤 원리로 실행될까요? find() 메서드 동작 원리JPA의 find()메서드는 기본적으로 1차 캐시(영속성 컨텍스트)를 먼저 확인한 후, 데이터가 있으면 1차 캐시에서 데이터를 바로 가져오고,  1차 캐시에 데이터가 없는 경우 DB에 select 쿼리를 사용해 데이터를 조회하는 방식으로 동작합니다. 그림으로 표현 1차 캐시는 무엇인가요? 1차 캐시는 영속성 컨텍스트(Persistence Context) 내부에 존재하는 메모리 캐시입니다. JPA의 EntityManager는 조회된 엔티.. 2025. 2. 4.
IDENTITY 식별자 생성 전략과 persist()의 관계 "IDENTITY전략을 사용하면 persist()시 왜 즉시 INSERT 쿼리문이 나갈까?" 이번글은 식별자 생성 전략인 IDENTITY와 영속성 컨텍스트에 엔티티를 영속화하는데 사용되는 persist()메서드와의 관계에 대해 알아보겠습니다. IDENTITY 식별자 생성 전략이란 무엇일까요? IDENTITY 식별자 생성 전략JPA에서 엔티티의 기본키를 자동으로 생성하는 방식 중 하나입니다.엔티티 생성시 기본키를 직접 할당하지 않아도, 데이터베이스에서 자동으로 생성할 수 있도록 책임을 위임하는 방식입니다.또한, IDENTITY전략은 MySql사용시 자주 선택되는 전략입니다.IDENTITY 식별자를 사용하면 DB에선 어떠한 일이 발생될까요? IDENTITY 전략을 사용하면 데이터베이스가 자동으로 기본 키 값.. 2025. 2. 3.