본문 바로가기
Spring JPA

[JPA] JPA 기초

by 에드박 2021. 8. 23.

왜 JPA를 학습해야 할까요?

JDBC API를 사용해서 코딩하다 보면 SQL과 JDBC API를 작성하는데 많은 시간을 투자합니다.

특히 CRUD용 SQL은 뻔한 반복작업이 되고 많은 반복적인 코드인 탓에 재미도 없습니다.

또한 객체와 관계형 데이터베이스의 패러다임 불일치 문제도 존재합니다.

 


객체와 관계형 데이터베이스(RDB)의 패러다임 불일치 문제

  • 상속
    • 객체는 상속이라는 기능을 가지고 있지만 테이블은 상속이라는 기능이 없습니다.
  • 연관관계
    • 객체는 참조를 사용해서 다른 객체와 연관관계를 가지고 참조에 접근해서 연관된 객체를 조회합니다.
    • 관계형 데이터베이스의 테이블은 외래 키를 사용해서 다른 테이블과 연관관계를 가지고 조인을 사용해서 연관된 테이블을 조회할 수 있습니다.
    • 여기서 한쪽의 테이블에서 외래 키를 이용한 연관관계를 가지고 양방향 조인, 즉 A테이블에서 B테이블을 조회해오거나 B테이블에서 A테이블을 조회할 수 있습니다.
    • 하지만 객체는 객체참조로 다른 객체와 연관관계를 맺으면 반대편 객체에서도 객체 참조를 하지않는 이상 양방향 조회가 불가능합니다. 즉 A라는 객체가 B객체를 참조하면 A->B 조회가 가능합니다. 하지만 B객체로 가면 A라는 객체를 참조하고 있지 않다면 B -> A 조회가 불가능합니다.
    • 관계형 데이터베이스의 테이블은 한쪽에서만 참조를 해도 양방향 조회가 가능하지만 객체는 한쪽에서만 참조를 하면 양방향 조회가 불가능하여 패러다임 불일치가 발생합니다.
  • 객체 그래프 탐색
    • 객체는 객체 그래프 탐색이 자유로워야 합니다. 그런데 데이터 베이스에서 조회해올때 객체는 그래프 탐색이 자유롭게 된다는 것을 보장받을 수 있을까요? 
    • SQL을 직접 다루면 처음 실행하는 SQL에 따라 객체 그래프를 어디까지 탐색할 수 있는지 정해집니다. 이것은 객체지향에서 굉장히 큰 제약사항 입니다. 비즈니스 로직에 따라 사용하는 객체 그래프가 다른데 언제 끊어질지 모를 객체 그래프를 함부로 탐색할 수 없기 때문입니다.
    • 예를 들어 Member 객체를 데이터베이스에서 조회해왔지만 탐색을 통해서 Member가 참조하고있는 Team 객체를 가져왔는가? 또한 Team 객체가 가지고 있는 Account 객체까지 그래프 탐색이 가능할까요?
class MemberService {
    public void process() {
        Member member = memberDAO.find(memberId);
        member.getTeam(); // 현재의 코드만 보고 team 객체를 find() 메서드에서 조회해왔는지 보장받을 수 있을까요?
        member.getTeam().getAccount(); // 객체 그래프 탐색을 보장을 하고 있을까요?
    }
}

 

  • 비교
    • 데이터베이스는 기본 키의 값으로 각 Row(열)를 구분합니다.
    • 객체는 동일성(identity, ==)과 동등성(equality, equals() 메서드) 비교라는 두 가지 비교 방법이 있습니다.
    • 이런 데이터베이스의 Row끼리와 객체끼리 구분하는 방법에는 차이가 있습니다.
Long memberId = 100;
Member member1 = memberDAO.getMember(memberId);
Member member2 = memberDAO.getMember(memberId);

member1 == member2 // false, 다르다는 결과가 나옵니다. 같은 데이터지만 객체를 새로 생성된것이므로 주소값이 다릅니다.

JPA란 무엇인가?

JPA(Java Persistence API)는 자바 진영의 ORM 기술 표준입니다.

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

 

즉, Java Application -> JPA -> JDBC -> DB 흐름으로 동작합니다.

 

ORM이란?

ORM(Object-Relational Mapping)은 이름 그대로 객체와 관계형 데이터베이스를 매핑한다는 뜻입니다.

ORM 프레임워크는 객체와 테이블을 매핑해서 패러다임 불일치 문제를 개발자 대신 해결해줍니다.

  • ORM 프레임워크를 사용하면 객체를 데이터베이스에 저장할 때 Insert SQL을 직접 작성하는것이 아니라 객체를 자바 컬렉션에 저장하듯이 ORM 프레임워크가 적절한 INSERT SQL을 생성해서 데이터베이스에 객체를 저장해줍니다.
  • 다음과 같은 코드로 저장을 합니다. jpa.persist(member);
  • 객체를 조회할 때도 마찬가지입니다. jpa.find(memberId);

JPA는 Entity Object에 대해 분석하고, SQL을 생성, 내부적으로 JDBC API를 사용하여 패러다임 불일치를 해결합니다.

때문에 객체 측면에서는 정교한 모델링을 할 수 있고 관계형 데이터베이스는 데이터베이스에 맞도록 모델링하면 됩니다.

객체와 데이터베이스를 어떻게 매핑할지 방법만 ORM 프레임워크에게 알려주면 됩니다.

 

JPA 소개

과거 자바 진영은 엔터프라이즈 자바 빈즈(EJB)라는 기술 표준을 만들었는데 그 안에는 엔티티 빈이라는 ORM기술 표준도 표함되어 있었습니다. 하지만 너무 복잡하고 기술 성숙도도 떨어졌으며 자바 엔터프라이즈(J2EE) 애플리케이션 서버에서만 동작했습니다.

하이버네이트(hibernate.org)라는 오픈소스 ORM 프레임워크가 등장했는데 EJB의 ORM 기술과 비교해서 가볍고 실용적인 데다 기술 성숙도도 높았습니다. 또한 자바 엔터프라이즈(J2EE) 애플리케이션 서버 없이도 동작해서 많은 개발자가 사용하기 시작했습니다. 

 

결국 EJB 3.0에서 하이버네이트를 기반으로 새로운 자바 ORM 기술 표준이 만들어졌는데 이것이 바로 JPA 입니다.

 

요약

  • EJB 기술 표준을 만들었지만 너무 복잡하고 기술 성숙도가 낮았습니다.
  • EJB는 자바 엔터프라이즈(J2EE) 애플리케이션 서버에서만 동작했습니다.
  • 하이버네이트라는 ORM 프레임워크는 EJB와 비교해서 실용적이고 기술 성숙도가 높았습니다.
  • 하이버네이트는 J2EE 애플리케이션 서버 없이도 동작했습니다.
  • 자바 ORM 기술 표준이 JPA입니다.

 

JPA는 자바 ORM 기술에 대한 API 표준 명세입니다. 즉, 인터페이스를 모아둔 것입니다.

JPA 2.1을 구현한 ORM 프레임워크는 하이버네이트(hibernate), EclipseLink, DataNucleus가 있습니다. 이 중 하이버네이트가 가장 대중적인 ORM 프레임워크 입니다.

 

JPA 버전별 특징

(참고자료 - 위키피디아, JPA책 - 김영한님)

JPA 1.0(JSR 220) : 초기 버전. 복합키와 연관관계 기능이 부족했습니다.

JPA 2.0(JSR 317) : 대부분의 ORM 기능을 포함하고 JPA Criteria가 추가됐습니다.

JPA 2.1(JSR 338) : 스토어드 프로시저 접근, 컨버터, 엔티티 그래프 기능이 추가됐습니다.

JPA 2.2(JSR 338) 

  • 관련된 모든 주석에 @Repeatable 추가
  • 모든 JPA 주석이 메타 주석에서 사용되도록 허용합니다.
  • 쿼리 결과를 스트리밍하는 기능 추가
  • AttributeConverters가 CDI 주입 가능하도록 허용
  • Java 8 날짜 및 시간 유형 지원

Jakarta Persistence 3.0

  • JPA API의 이름을 Jakarta Persistence로 변경한 후 2020년에 v3.0을 출시했습니다.
  • 모든 패키지의 이름을 javax.persistence -> jakarta.persistence로 바꿉니다.
  • 모든 속성 접두어의 이름을 javax.persistence -> jakarta.persistence로 바꿉니다.

왜 JPA를 사용해야 하는가?

  • 도메인 주도 개발이 가능합니다.
  • 그리고 개발 생산성에 좋으며, 데이터베이스에 독립적인 프로그래밍이 가능하고, 타입 세이프한 쿼리 작성 그리고 Persistent Context가 제공하는 캐시 기능으로 성능 최적화까지 가능합니다.
  • 생산성
    • 지루하고 뻔한 CRUD용 SQL을 직접 작성하지 않아도 됩니다.
    • 데이터베이스 설계 중심의 패러다임을 객체 설계 중심으로 역전시킬 수 있습니다.
  • 유지보수
    • 기존에 JDBC API를 사용하면 엔티티에 필드 하나만 추가해도 JDBC API의 CRUD 코드를 모두 변경해야 했습니다.
    • JPA를 사용하면 이런 과정을 JPA가 대신 처리해줍니다.
    • 개발자가 작성해야 했던 JDBC API코드를 JPA가 대신 처리해주므로 유지보수해야 하는 코드 수가 줄어듭니다.
    • JPA가 패러다임 불일치도 해결해주므로 객체지향 언어가 가진 장점들을 활용해서 유연하고 유지보수하기 좋은 도메인 모델을 편리하게 설계할 수 있습니다.
  • 패러다임 불일치 해결
    • 상속, 연관관계, 객체 그래프 탐색, 비교하기 같은 패러다임 불일치 문제를 해결해줍니다.
  • 성능
    • JPA는 애플리케이션과 데이터베이스 사이에서 다양한 성능 최적화 기회를 제공합니다.
    • 애플리케이션과 데이터베이스 사이에 있다는 것은 최적화 관점에서 시도해볼 수 있는 것들이 많습니다.
  • 데이터 접근 추상화와 벤더 독립성
    • 관계형 데이터베이스들 끼리도 같은 기능을 벤더마다 사용법이 다른 경우가 많습니다. 이는 처음 선택한 데이터베이스 기술에 종속되고 다른 데이터베이스로 변경하기 어렵게 만듭니다.
    • JPA는 애플리케이션과 데이터베이스 사이에 추상화된 데이터 접근계층을 제공해서 애플리케이션이 특정 데이터베이스 기술에 종속되지 않도록 합니다.
    • 다양한 Dialect를 사용할 수 있습니다. (MySQLDialect, OracleDialect, H2Dialect)
  • 표준
    • JPA는 자바 진영의 ORM 기술 표준입니다.
    • 표준을 사용하면 다른 구현 기술로 손쉽게 변경할 수 있습니다.

댓글