본문 바로가기
Programming/Spring JPA

[자바 ORM 표준 JPA 프로그래밍] JPA 소개

by 깐니 2022. 11. 23.

개요

JPA 도입이 필요한 이유와 JPA가 무엇인지 알아보자.

 

목차

  • SQL을 직접 다룰 때 발생하는 문제점
  • 패러다임의 불일치 해결을 위한 JPA 특징
  • JPA 란?

 

SQL을 직접 다룰 때 발생하는 문제점

SQL mapper 를 사용하여 애플리케이션을 개발할 때의 문제점은 대표적으로 아래와 같다.

- 엔티티를 신뢰할 수 없다.

- SQL에 의존적인 개발을 하게 된다.

프로그램 운영을 하다보면 내부의 복잡성이 커지게 되는데, 그것에 대한 유지보수를 하기 어려워진다.

예를 들어, 회원테이블에 소속학교 필드를 하나 추가하는 단순한 작업만 살펴보아도 그렇다.

실 DB에 컬럼을 추가한 뒤, 해당 필드에 대한 조회,수정을 하는 작업을 하기위해서는

1.회원 클래스에 소속학교 필드 추가

2. select SQL, update, insert SQL 에도 필드를 추가해야하는 추가 작업이 필요한데,

만약 복잡도가 더 높아진다면 DAO단을 모두 뒤져서 누락된 작업을 해주어야하는 경우가 생긴다.

 

자바는 객체지향언어라는 장점이 있는데, SQL mapper (MyBatis, iBatis, .. 와 같은)와 조합하여 사용하면서 위와같은 비생산적인 작업들이 생겨났다.

이를 해결하기 위한 방법으로 자바 진영의 ORM 중 하나인 JPA에 대해 알아보고자 한다.

 

 

 

패러다임의 불일치 해결을 위한 JPA 특징

* 패러다임 불일치란 ?

객체지향 언어와 관계형데이터베이스는 지향하는 목적이 서로 달라서 기능과 표현 방법이 다르다.

 

1. 상속

객체는 상속 기능이 있다.

테이블은 상속 기능이 없다. 

 

JPA와 상속

예를 들어. Item을 상속한 Album 객체가 있는 경우

// 개발자 작성 코드
jpa.persist(album);  

// 실제 JPA 수행 값
INSERT INTO ITEM ...
INSERT INTO ALBUM ...



// 개발자 작성 코드
String albumId = "id100";
Album album = jpa.find(Album.class, albumId);

// 실제 JPA 수행 값
SELECT I.*, A.* 
FROM ITEM I JOIN A
  ON I.ITEM_ID = A.ITEM_ID

 

2. 연관관계

객체는 참조를 통해 연관관계를 가지고, 참조에 접근해서 연관관계를 조회한다.

테이블은 외래키를 통해 연관관계를 가지고, 조인을 사용해서 연관관계를 조회한다.

 

JPA와 연관관계

예를 들어, member와 team 객체가 있고, 특정 member가 소속된 team을 조회하고자 하는 경우

// 개발자 작성 코드
member.setTeam(team); // 회원과 팀 연관관계 설정
jpa.persist(member);  // 회원과 연관관계 함께 저장

// 실제 JPA 수행 값
team의 참조를 외래 키로 변환 -> 해당 Insert SQL을 데이터베이스에 전달함.


// 개발자 작성 코드
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();

// 실제 JPA 수행 값
객체 조회 시 외래 키를 참조로 변환하여 조회함.

 

 

3. 객체 그래프 탐색

객체 Member-Order-Delivery 가 연관관계를 맺고 있다고 하자.

member.getOrder().getOrderItem(); 의 정보를 가지고 오고자 할때,

만약 이전 MemberDAO에서 member 객체 조회를 할 때,

SELECT M.*, T.* 

FROM MEMBER M JOIN TEAM T

  ON T.TEAD_ID = M.TEAD_ID 쿼리로 조회했다면 getOrderItem()은 해당 데이터가 없으므로 탐색할 수 없어서 NULL을 반환할 것이다.

이처럼 SQL을 직접 다루면 처음 실행하는 SQL에 따라 객체 그래프를 어디까지 탐색할지 정해져버린다.

비지니스 로직에 따라 사용하는 쿼리가 다를텐데, 함부로 객체 그래프를 탐색할 수 없기 때문이다.

 

JPA와 객체 그래프 탐색

JPA를 사용하면 객체 그래프 탐색에 대한 제약이 없다.

왜냐하면 실제 객체를 사용하는 시점까지 데이터베이스 조회를 미루는 지연 로딩을 정의하여 사용할 수 있기 때문이다.

 // 처음 조회 시점에 SELECT MEMBER SQL
Memeber member = jpa.find(Member.class, memberId);

Order order = member.getOrder();
order.getOrderDate(); // Order 사용 시점에 SELECT ORDER SQL

연관된 객체를 즉시조회할지, 실제 사용시점에 지연조회할지 정의할 수 있다.

만약 즉시조회로 설정하면, JPA는 아래와 같이, 처음 Member를 조회할 때 연관된 Order도 함께 조회한다.

SELECT M.*, O.*
FROM MEMBER M JOIN ORDER O
  ON O.MEMBER_ID = M.MEMBER_ID

 

 

4. 비교

객체는 동일성비교, 동등성 비교로 구분한다.

동일성비교: == 비교로, 객체 인스턴스 주소 값을 비교함.

동등성비교: equals() 메소드를 사용한 객체 내부 값을 비교함.

데이터베이스는 PK로 각 row를 구분한다.

 

JPA와 비교

JPA는 같은 트랜잭션일 때 같은 객체가 조회되는 것을 보장한다.

String memberId = "helloId";
Member m1 = jpa.find(memberId);
Member m2 = jpa.find(memberId);

JPA를 사용하면 회원을 조회하는 SELECT SQL를 한번만 데이터베이스에 전달하고,

두번째는 조회한 회원 객체를 재사용한다.

 

 

 

 

JPA 란? 

JPA는 자바 ORM 기술에 대한 API 표준 인터페이스이다.

JPA는 애플리케이션과 JDBC 사이에서 동작한다.

애플리케이션에서 JPA를 사용하면, JPA는 JDBC API를 사용해서 SQL을 만들어서 DB에 명령한다.

또한, 단순히 SQL을 생성해서 전달해주는 것뿐만 아니라 다양한 패러다임 불일치 문제들도 해결해준다.

 

자바의 다양한 ORM 프레임워크의 종류에는 Hibernate, EclipseLink, DataNucleus .. 등이 있다.

그 중 오픈소스 ORM 프레임워크인 하이버네이트를 기반으로 만들어진 자바 ORM 기술 표준이 JPA이다.

즉, 하이버네이트는 JPA의 구현체로, JPA 인터페이스를 구현하며, 내부적으로 JDBC API를 사용한다.

 

 

JPA 를 사용하는 이유

1. 생산성

2. 유지보수

3. 패러다임의 불일치 해결

4. 성능 
: JPA는 애플리케이션과 데이터베이스 사이에서 동작한다. 두 계층 사이에 계층이 하나 더 있기 때문에, 최적화 관점에서 시도할 수 있는 것들이 많다.

5. 데이터 접근 추상화와 벤더 독립성

: JPA는 애플리케이션과 데이터베이스 사이에 추상화된 데이터 접근 계층을 제공한다. (Dialect)

그렇기 때문에, 특정 데이터베이스 기술에 종속되지 않아도 되며, 데이터베이스 변경 시, 환경 설정만 바꿔주면 된다.

6. 표준

: JPA는 자바 진영의 ORM 기술 표준이기 떄문에, 다른 구현체로 쉽게 변경할 수 있다.