집돌이 공대남 IT

JPA 프로그래밍 마스터하기! 초급부터 전문가까지 실습을 통한 학습(5) 본문

IT/웹개발

JPA 프로그래밍 마스터하기! 초급부터 전문가까지 실습을 통한 학습(5)

집공이 2023. 8. 18. 12:00

실무에서의 JPA 사용 팁과 주의사항

안녕하세요, 공대남입니다.

이전 글에서는 JPA의 고급 기능과 성능 최적화에 대해 알아보았습니다.

이번 글에서는 실무에서 JPA를 사용하면서 알아두면 좋은 팁과 주의사항에 대해 보다 상세하게 다루도록 하겠습니다.

1. 트랜잭션 관리

JPA에서 트랜잭션 관리는 중요한 부분입니다. 일반적으로 데이터베이스 작업은 트랜잭션 안에서 이루어집니다. 트랜잭션은 일련의 작업이 전부 성공하거나 전부 실패하도록 보장해주는 메커니즘입니다. JPA를 사용하면서는 EntityManager를 이용하여 트랜잭션을 관리합니다.

트랜잭션의 시작은 EntityManager 인스턴스를 생성하는 것으로, EntityManagerFactorycreateEntityManager() 메소드를 통해 생성합니다. 이렇게 생성된 EntityManager는 단일 스레드에서 사용되어야 하며, 여러 스레드가 동시에 같은 EntityManager를 사용하게 되면 동시성 문제가 발생할 수 있습니다.

이후 실제로 데이터베이스 작업을 수행하기 위해서는 트랜잭션을 시작해야 합니다. EntityManagergetTransaction().begin() 메소드를 통해 트랜잭션을 시작합니다. 트랜잭션 안에서는 필요한 모든 데이터베이스 작업을 수행한 후, getTransaction().commit() 메소드를 통해 트랜잭션을 커밋하게 됩니다.

만약 트랜잭션 도중에 예외가 발생하게 된다면, 트랜잭션을 롤백해야 합니다. 롤백은 getTransaction().rollback() 메소드를 통해 수행하게 됩니다.

이렇게 JPA를 통해 트랜잭션을 관리하면, 애플리케이션과 데이터베이스 간의 일관성을 유지할 수 있으며, 예외 발생 시에도 데이터의 안전성을 보장할 수 있습니다.

 

2. 엔티티 생명주기 관리

JPA에서는 엔티티의 생명주기를 명확히 관리해야 합니다. 엔티티의 생명주기란, 엔티티가 생성되고, 영속성 컨텍스트에 의해 관리되며, 최종적으로 삭제되는 과정을 의미합니다. 이 과정에서 엔티티는 비영속, 영속, 준영속, 삭제 네 가지 상태를 거치게 됩니다.

  • 비영속 (New): 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태를 의미합니다. 즉, 새로운 엔티티를 만들었지만 아직 저장하지 않은 상태입니다.
  • 영속 (Persistent): 엔티티를 영속성 컨텍스트에 저장한 상태를 의미합니다. 영속성 컨텍스트가 엔티티를 관리하게 되면, 엔티티의 모든 변경사항은 데이터베이스와 동기화됩니다.
  • 준영속 (Detached): 영속성 컨텍스트가 관리하던 엔티티를 관리하지 않는 상태를 의미합니다. 준영속 상태가 된 엔티티는 변경이 발생해도 데이터베이스와 동기화되지 않

습니다.

  • 삭제 (Removed): 엔티티를 영속성 컨텍스트와 데이터베이스에서 모두 삭제한 상태를 의미합니다.

이러한 상태에 따라 JPA는 어떻게 엔티티를 관리할지를 결정하게 되므로, 엔티티의 생명주기를 잘 관리하는 것이 중요합니다.

 

3. FetchType

FetchType은 JPA에서 엔티티의 연관된 엔티티를 언제 로딩할지 결정하는 방식을 의미합니다. JPA에서는 EAGER 로딩과 LAZY 로딩 두 가지 방식을 제공합니다.

  • EAGER 로딩: 엔티티를 조회할 때 연관된 엔티티를 함께 조회하는 방식입니다. 예를 들어, 부모 엔티티를 조회할 때 연관된 자식 엔티티들을 같이 조회하게 됩니다. 이 경우, 필요하지 않은 자식 엔티티까지도 모두 조회하게 되므로, 성능상의 문제가 발생할 수 있습니다.
  • LAZY 로딩: 연관된 엔티티를 실제로 사용할 때만 조회하는 방식입니다. 따라서, 필요한 데이터만 조회하게 되어 성능상의 이점이 있습니다. 하지만, 연관된 엔티티를 조회하기 위해서는 영속성 컨텍스트가 활성 상태여야 하므로, 이 점을 주의해야 합니다.

따라서, FetchType은 상황에 따라 적절하게 선택하여 사용해야 합니다.

 

4. N+1 문제

N+1 문제는 JPA를 사용하면서 흔히 발생하는 성능 문제 중 하나입니다. 이 문제는 한 번의 쿼리로 해결할 수 있는 문제를 N+1번의 쿼리로 해결하는 경우를 말합니다. 예를 들어, 부모 엔티티와 연관된 자식 엔티티들을 조회할 때, 먼저 부모 엔티티들을 조회한 후(1번의 쿼리), 각 부모 엔티티에 대해 자식 엔티티들을 따로 조회하게 되면(N번의 쿼리), 총 N+1번의 쿼리가 발생하게 됩니다.

이 문제를 해결하기 위해서는 JPQL의 JOIN FETCH, 엔티티 그래프 기능 등을 활용할 수 있습니다. JOIN FETCH를 이용하면, 부모 엔티티와 자식 엔티티를 한 번의 쿼리로 함께 조회할 수 있습니다. 엔티티 그래프를 이용하면, 조회하고자 하는 엔티티와 그 연관된 엔티티들을 지정하여 한 번의 쿼리로 조회할 수 있습니다.

 

5. 불필요한 쓰기 지연 사용

JPA는 쓰기 지연이라는 기능을 제공합니다. 이 기능은 트랜잭션을 커밋할 때까지 SQL을 데이터베이스에 보내지 않고, 대신 1차 캐시에 쌓아두는 기능입니다. 이 기능은 성능 최적화에 유용하지만, 항상 필요한 것은 아닙니다. 불필요한 경우 이를 비활성화하여 리소스를 절약할 수 있습니다.

 

JPA를 사용하면서 이러한 팁과 주의사항을 기억해두면 좀 더 효과적이고 안전한 코드를 작성할 수 있습니다. 다음 글에서는 JPA와 Spring Data JPA를 사용하여 실제 애플리케이션을 구축하는 방법에 대해 알아보도록 하겠습니다. 그럼, 즐겁게 코딩하세요!