Spring

[Spring JPA] JPA 소개 (1)

아윤_ 2024. 5. 12. 01:00

 

JPA

 

우리는 애플리케이션 개발 시 주로 객체 지향 언어와 관계형 데이터베이스를 사용하여 개발한다. 과거에 JPA가 등장하기 전에는 개발자들은 SQL에 의존적인 개발을 피할 수 없었다. 하지만 SQL 중심적인 개발을 하게 되면 다음과 같은 문제가 발생한다.

  • 무한 반복, 지루한 코드
  • 객체 하나를 보관하고 꺼내고 삭제하려면 계속해서 쿼리를 작성해야 한다.

 

이러한 문제를 해결하기 위해 JPA가 등장하게 되었다. JPA란 Java Persistence API의 약자로, 자바 진영의 ORM 기술 표준을 말한다.

 

ORM (Object Relational Mapping)

 

ORM은 Object Relational Mapping의 약자로 말 그대로 객체와 관계를 매핑하는 것을 말한다. 즉, Relational은 관계형 DB에서의 관계를 의미하며, 대중적인 언어에는 대부분 ORM 기술이 존재한다.

 

객체는 객체대로 설계하고, 관계형 DB는 관계형 DB대로 설계하면 이를 중간에서 ORM 프레임워크가 알아서 매핑하여 해결해 준다.

 

 

JPA의 동작

 

그렇다면 JPA는 어떻게 동작하는 것일까? JPA는 애플리케이션과 JDBC 사이에서 동작한다. 결과적으로 JAVA 애플리케이션에서 DB와 통신하기 위해서는 JDBC API를 사용해야 하는데, 이를 개발자 대신 JPA가 대신 쓰는 것이다.

 

JPA 동작

 

저장 

 

Member 객체를 DB에 저장한다고 가정해 보자. Member 객체를 MemberDAO에 넘기고, MemberDAO가 JPA에게 Member Entity를 저장해 달라고 JPA에게 던지기만 하면, JPA가 알아서 Member 엔티티를 분석하여 INSERT SQL을 생성한 다음, 
JDBC API를 사용하여 DB에 INSERT 쿼리까지 다 날려주게 된다.

 

JPA 동작 - 저장

 

조회 

 

Member 객체를 조회 시에는 JPA에게 Member의 id만 던져주면 된다. JPA는 SELECT 쿼리를 생성하고, JDBC API를 사용하여 ResultSet을 매핑해 주며, 패러다임의 불일치를 해결한다. SQL을 날려 DB로부터 반환받은 결과를 통해 JPA가 엔티티 객체를 만들어 Member 엔티티를 MemberDAO에게 반환하게 된다. 

 

JPA 동작 - 조회

 

 

JPA 표준 명세 

 

표준 명세란, 인터페이스의 모음을 의미한다. JPA 2.1 기준으로 JPA 표준 명세를 구현한 3가지 구현체에는 Hibernate, EclipseLink, DataNucleus가 있는데, 구현체로는 거의 Hibernate를 사용한다. 

 

JPA 표준 명세

 

 

JPA를 사용해야 하는 이유 

 

객체 중심적인 개발

 

기존에 SQL 중심적인 개발을 피하고 객체 중심으로 개발할 수 있다.

 

생산성

  • 저장: jpa.persist(member)
  • 조회: Member member = jpa.find(memberId)
  • 수정: member.setName("변경할 이름")
  • 삭제: jpa.remove(member)

 

다음과 같이 데이터를 저장, 조회, 수정, 삭제할 때 코드 한 줄만 작성하면 된다.

 

유지보수

 

기존에는 필드 변경 시 모든 SQL을 수정해야 해서 매우 번거로웠지만, JPA를 사용하면 필드 변경 시 필드만 추가하면 된다. SQL은 JPA가 알아서 처리하기 때문이다.

 

즉, JPA를 사용하면 개발자가 유지보수 해야 되는 영역이 정말 많이 줄어든다.

 

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

 

JPA는 관계형 DB와 객체 사이의 패러다임 불일치 문제를 해결한다.

 

1. JPA와 상속

 

다음과 같은 상속 관계가 있다고 가정하고 예시를 살펴보자.

 

  • 상속 관계에 있는 앨범을 저장하려 할 때, 개발자는 앨범 객체를 넣어주기만 하면 된다.
  • jpa.persist를 통해 앨범 객체를 넣어주면 JPA가 알아서 INSERT 쿼리를 날려준다.
  • 많은 매핑 과정을 JPA가 해준다.

 

  • 데이터를 조회할 때는 jpa.find를 통해 앨범의 타입과 아이디를 넣어주면 알아서 앨범 객체를 반환해 준다.
  • 기존에는 아이템과 앨범을 조회해서 가져와야 했던 일을 JPA가 알아서 해준다.

 

 

2. JPA와 연관관계, 객체 그래프 탐색

  • JPA에서는 연관관계 저장 시 참조를 사용할 수 있다.
  • 또한, jpa.find를 통해 멤버를 꺼낼 때에도 연관관계에 있는 팀을 조회할 수 있다.

 

 

3. 신뢰할 수 있는 엔티티, 계층

  •  SQL을 직접 다룰 때에는 엔티티 계층을 신뢰하지 어려웠지만, JPA를 사용하면 엔티티 계층을 신뢰할 수 있다.

 

JPA가 관리하는 객체를 엔티티라 한다.

 

 

4. JPA와 비교하기

  •  JPA를 통해 memberId가 100인 멤버를 2번 조회하여 비교할 때, 두 객체는 같다.
  • 전제: 동일한 트랜잭션에서 조회한 엔티티는 같음을 보장한다.

 

 

5. JPA의 성능 최적화 기능

 

JPA는 다음과 같은 성능 최적화 기능을 보장한다.

  • 1차 캐시와 동일성(identity) 보장
  • 트랜잭션을 지원하는 쓰기 지연
  • 지연 로딩

 

1차 캐시와 동일성(identity) 보장

  • 같은 트랜잭션 안에서는 같은 엔티티를 반환 - 약간의 조회 성능 향상
    • 예를 들어, 첫 번째로 find 메서드를 호출할 때에는 JPA가 SQL을 날리지만, 두 번째로 같은 엔티티에 대해 find를 호출할 경우 JPA가 메모리 상에서 가지고 있다가 반환해 주는 캐싱 기능을 제공한다. 따라서 SQL이 1번만 실행된다.
  • DB Isolation Level이 Read Commit이어도 애플리케이션의 Repeatable Read 보장

 

트랜잭션을 지원하는 쓰기 지연

  • 트랜잭션을 커밋할 때까지 INSERT SQL을 모은 다음 JDBC BATCH SQL 기능을 사용해서 한번에 SQL을 전송한다.
  • UPDATE, DELETE로 인한 로우(ROW) 시간을 최소화하고, 트랜잭션 커밋 시 UPDATE, DELETE SQL을 실행하고 바로 커밋한다.

 

지연 로딩과 즉시 로딩

  • 지연 로딩: 객체가 실제 사용될 때 로딩
  • 즉시 로딩: JOIN SQL로 한번에 연관된 객체까지 미리 조회

 

 

Member와 Team이 있고, Member와 Team이 연관관계가 있을 때 즉시 로딩의 경우 Member를 조회할 때 항상 Team이 같이 사용되는 경우 즉시 로딩을 사용하고, 반대로 Member를 조회할 때 Team을 같이 잘 사용하지 않는 경우 성능을 위해 지연 로딩을 사용하는 게 좋다.

 

 

정리

 

결국 JPA라는 기술은 ORM이라는 기술로, 객체와 관계형 데이터베이스를 중간에서 매핑해 주는 기술이다. 즉 JPA를 잘 알기 위해서는 객체 지향이라는 개념과 관계형 데이터베이스라는 두 가지 개념을 잘 알아야 JPA를 잘 사용할 수 있다.