[JPA] JPA 소개

오현석·2024년 9월 16일

JPA

목록 보기
1/9

JPA 이전

JPA 이전의 시대와 JPA가 도입된 배경, JPA가 무엇인가부터 알아보자.

기존 과거의 코드들은 개발자가 CRUD를 비롯한 로직에서 DB에 접근, 수정 등의 작업을 수행하려면 직접 SQL문을 작성해서 가져와야 했다.
이런 방식은 Entity를 수정할 때, 해당 Entity 관련 코드들을 모두 수정해주어야 하는 등의 문제가 있었다.

한편, 테이블이나 객체에서 연관 관계를 설정할 때는 객체는 참조(member.getTeam()), 테이블은 외래 키(FK)를 사용해서 연관 관계를 설정하고, 객체를 이런 테이블에 맞추어 모델링할 수 있다.
여기서 객체를 테이블처럼 외래 키를 설정하는 방식이 아니라 객체다운 모델링을 하기 위해 참조를 사용해서 설정하게 된다면, 조회같은 작업에서 인스턴스를 생성하는 과정이 많이 복잡해지게 된다.

또한, 객체는 메소드들을 통해 자유롭게 객체 그래프를 탐색할 수 있어야 하는데, SQL을 사용하는 경우는 처음 SELECT문에서 불러오는 엔트리의 범위에 따라 탐색 범위가 결정되게 된다. 그렇다고 모든 객체를 미리 로딩할 수 없다보니 진정한 의미의 계층 분할은 객체 지향적으로 어렵게 된다.

게다가, 자바 컬렉션에서는 이렇게 같은 객체로 만들 수 있지만,

SQL을 사용하는 방식은 DB에서 데이터를 가져와 새로 만든 데이터만 같은 서로 다른 인스턴스를 만들기 때문에 객체가 다르다.
즉, 객체답게 모델링하려 할 수록 개발자가 수행해야 할 매핑 작업만 늘어나는 결과가 발생한다. 그러면 객체를 자바 컬렉션에 저장하듯 DB에 저장하기 위해 사용하는 것이 Java Persistant API, 즉 JPA이다.

ORM

ORM은 Object-relational mapping의 약자로 객체 관계 매핑이라는 의미를 가지고 있다. 객체는 객체대로 설계하고 RDB는 RDB대로 설계하는 방식이다. 이 사이의 간극은 ORM 프레임워크가 매핑해준다. Java 진영에서는 JPA가 이 ORM 프레임워크이다.

JPA

우리가 DB와 통신하기 위해 지금까지는 JDBC를 직접 사용했지만, JPA는 JDBC를 직접 사용하지 않게 해줄 수 있다.
예를 들어, 엔티티를 조회하기 위해 SELECT SQL을 작성하는 등등의 작업을 지금까지는 해야했다면, JPA를 사용하면 findById(id)로 바로 객체를 조회해서 가져올 수 있다. JPA가 이후의 작업은 알아서 매핑해서 가져다주는 것이다.

JPA는 인터페이스의 모음이다. 즉, 표준 인터페이스라고 할 수 있고, 이를 구현한 3가지 구현체 중에 Hibernate를 주로 사용한다.

사용 이유

생산성

코드가 간결해졌다.

유지보수

기존에는 필드를 변경할 시에는 모든 SQL 코드를 수정해주어야 했다면, JPA에서는 필드만 추가해도 된다.

JPA와 패러다임의 불일치 해결

  • JPA와 상속
    상속 관계가 얽혀있는 엔티티를 저장할 때 기존에는 이 엔티티들을 모두 직접 추가해줘야 했지만, 이제는 개발자는 메인 객체만 저장하면 JPA가 알아서 상속 관계에 있는 객체들을 추가해줄 수 있다.
  • 연관관계, 객체 그래프 탐색
    연관관계를 JPA를 사용해서 저장하면 객체 그래프를 탐색할 때 엔티티 계층을 신뢰할 수 있다.

기존에는 memberDAO 클래스를 확인해봐야 member.getTeam()과 같은 코드들이 동작함을 알 수 있었지만, JPA를 사용하면 그런 불안함 없이 자유롭게 객체 그래프를 탐색할 수 있다.

  • 비교

자바 컬렉션에서 객체를 꺼냈을 때처럼 동일한 트랜잭션에서 조회한 엔티티는 같음을 보장해줄 수 있다.

지원 기능

  • 1차 캐시와 동일성 보장
    위에서 말한 비교 기능처럼 동일한 트랜잭션에서 조회한 엔티티가 같음을 보장해줄 수 있다. 이때, 같은 트랜잭션 안에서의 같은 조회라면 1차 캐시가 사용되어 조회 성능이 향상된다. 즉, 같은 조회에 대한 2번째 시행은 캐시를 사용하여 조회한다는 의미이다.

  • 쓰기 지연
    JPA는 트랜잭션을 지원하는 쓰기 지연을 지원한다. 트랜잭션을 커밋할 때까지 INSERT SQL을 모아놓고 커밋되는 시점에 모아서 한번에 SQL을 전송하게 된다. 이는 INSERT뿐만 아니라 UPDATE, DELETE에서 모두 적용된다. 이 기능의 장점은 쿼리에 의한 ROW Lock 시간을 최소화할 수 있다.

  • 지연 로딩과 즉시 로딩

JPA는 지연 로딩과 즉시 로딩 기능을 모두 지원한다.
지연 로딩이란 객체가 실제 사용될 때마다 객체를 로딩하는 것이고, 즉시 로딩이란 객체를 가져올 때 한번에 연관된 객체까지 미리 조회하는 것을 말한다.

이 두 기능을 필요에 따라 설정하여 코드를 최적화할 수 있다.
• @ManyToOne과 @OneToOne: 기본적으로 즉시 로딩(Eager Loading)을 사용합니다.
• @OneToMany와 @ManyToMany: 기본적으로 지연 로딩(Lazy Loading)을 사용합니다.

profile
Backend Engineer(FastAPI, Spring, ...) / Prompt & Context Engineer / DevOps

0개의 댓글