nyximos.log

[JPA] JPA 소개 본문

Programming/JPA

[JPA] JPA 소개

nyximos 2022. 2. 14. 22:09

 

자바 ORM 표준 JPA 프로그래밍

김영한

 

 

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

관계형 데이터베이스 = 데이터 저장소

자바로 개발하는 애플리케이션 = 대부분 관계형 데이터베이스 사용

 

SQL  Structured Query Language

데이터베이스의 데이터를 관리할 때 필요

JDBC API와 SQL

 

1. 반복

CRUD 기능을 개발해보자.

1. 자바에서 사용할 회원 객체 생성

2. 데이터베이스를 관리할 목적으로 회원용 DAO(데이터 접근 객체) 생성

3. 회원 조회 기능 개발

    1) 회원 조회용 SQL 작성

    2) SQL 실행 (JDBC API 사용)

    3) 조회결과와 회원 객체를 매핑

4. 회원 등록 기능 개발

    1) 회원 등록용 SQL 작성

    2) 회원 객체의 값을 꺼내서 SQL에 전달

    3) SQL 실행 (JDBC API 사용)

5. 수정/삭제하는 기능도 비슷한 과정 반복

 

정리

  • 개발자가 객체지향 애플리케이션과 데이터베이스 사이에서 SQL과 JDBC API를 사용해 직접 변환작업을 해줘야한다.
  • 너무 많은 SQL과 JDBC API를 코드로 작성해야 함

 

2. SQL에 의존적인 개발

요구사항 추가

  • 회원의 연락처도 함께 저장

1) 등록 코드 변경

1-1) 회원 클래스에 연락처 필드를 추가

1-2) INSERT SQL 수정

1-3) 회원 객체의 연락처 값을 꺼내서 SQL에 전달

1-4) 저장 기능 테스트

1-5) 데이터 베이스에 연락처 데이터 저장된 것 확인

2) 조회 코드 변경

2-1) SELECT SQL 수정

2-2) 결과 Member 객체에 매핑

3) 수정 코드 변경

3-1) UPDATE SQL 수정

3-2) 결과 MEMBER 객체에 매핑

4) 연관된 객체

요구사항 추가

  • 회원은 어떤 한 팀에 필수로 소속
  • 회원정보 출력시 팀 이름도 함께 출력

4-1) Member 객체에 team 필드 추가

4-2) MemberDAO에 findWithTeam() 으로 변경 (DAO를 열어 어떤 SQL이 실행되는지 확인)

 

정리

  • 진정한 의미의 계층 분할이 어렵다.
  • 엔티티를 신뢰할 수 없다.
  • SQL에 의존적인 개발을 피하기 어렵다.

 

3. JPA와 문제 해결

👎 개발자가 직접 SQL 작성

👍 JPA가 제공하는 API 사용 → JPA가 개발자 대신에 적절한 SQL을 생성해서 DB에 전달

 

1) 저장 기능

jpa.persist(member);

persist()

  • 객체를 데이터베이스에 저장
  • 메소드 호출시 JPA가 객체와 매핑정보를 보고 적절한 INSERT SQL을 생성해서 DB에 전달

2) 조회 기능

jpa.find(Member.class, memberId);

find()

  • 객체 하나를 데이터베이스에서 조회
  • 메소드 호출시 JPA가 객체와 매핑정보를 보고 적절한 SELECT SQL을 생성해서 DB에 전달
  • 결과로 Member 객체를 생성해서 반환

3) 수정 기능

  • JPA는 별도의 수정 메소드를 제공하지 않는다.
  • 객체를 조회해서 값을 변경만 하면 트랜잭션을 커밋할 때 데이터베이스에 적절한 UPDATE SQL이 전달

4) 연관된 객체 조회

  • 연관된 객체를 사용하는 시점에 적절한 SELECT SQL을 실행
  • 연관된 객체 마음껏 조회

 

🕵️‍♀️ 패러다임의 불일치

애플리케이션 발전 → 내부의 복잡성 증가

 

객체지향 프로그래밍

  • 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공
  • 추상화, 캡슐화, 정보은닉, 상속, 다형성 등
  • 도메인 모델 (비즈니스 요구사항 정의)도 객체로 모델링하면 객체의 장점을 활용할 수 있다.

관계형 데이터베이스

  • 데이터 중심으로 구조화
  • 집합적인 사고요구
  • 추상화, 상속, 다형성 같은 개념이 없다.

 

문제는 저장할때!!

  • 객체 구조를 테이블 구조에 저장하는 데는 한계가 있다.
  • 지향하는 목적, 기능, 표현 방법이 다르다. → 패러다임의 불일치
  • 애플리케이션 = 객체지향 언어로 개발
  • 데이터 = 관계형 데이터베이스에 저장
  • → 개발자가 중간에서 해결해야 한다.
  • 많은 시간과 코드 소비

 

1. 상속

  • 객체는 상속이라는 기능을 가지고 있다.
  • 테이블은 상속 기능이 없다.
  • 그나마 슈퍼타입 서브타입 관계를 이용하면 유사한 형태로 테이블 설계가 가능

 

JPA 사용해서 해결

  • 개발자는 자바 컬렉션에 객체를 저장하듯이 JPA에 객체를 저장하면 된다.
jpa.persist(album);
  • JPA는 SQL문을 실행하여 객체를 ITEM, ALBUM 두 테이블에 나누어 저장한다.
INSERT INTO ITEM ...
INSERT INTO ALBUM ...
  • find() 메소드를 사용해 객체를 조회한다.
String albumId = "id100";
Album album = jpa.find(Album.class, albumId);
  • JPA는 ITEM, ALBUM 두 테이블을 조인해서 필요한 데이터를 조회하고 그 결과를 반환한다.
SELECT I.*, A.*
	FROM ITEM I
    JOIN ALBUM A ON I.ITEM_ID = A.ITEM.ID

 

2. 연관관계

  • 객체는 참조를 사용해서 다른 객체와 연관관계를 가지고 참조에 접근해서 연관된 객체를 조회
  • 테이블은 외래키를 사용해서 다른 테이블과 연관관계를 가지고 조인을 사용해서 연관된 테이블을 조회

 

JPA 사용해서 해결

  • 개발자는 회원과 팀의 관계를 설정하고 회원객체를 저장한다.
  • JPA는 team의 참조를 외래키로 변환해서 적절한 INSERT SQL을 데이터베이스에 전달한다.
member.setTeam(team);
jpa.persist(member);
  • 객체를 조회할 때 외래 키를 참조로 변환하는 일도 JPA가 처리해준다.

 

3. 객체 그래프 탐색

  • SQL을 직접 다루면 처음 실행하는 SQL에 따라 객체 그래프를 어디까지 탐색할 수 있는지 정해진다.
  • 어디까지 객체 그래프 탐색이 가능한지 알아보려면 DAO(데이터 접근 계층)을 열어서 SQL을 직접 확인해야 한다.
  • 엔티티가 SQL에 논리적으로 종속적

 

JPA 사용해서 해결

  • 객체 그래프를 마음껏 탐색 가능
  • JPA는 지연 로딩을 투명 Transparent하게 처리
  • 연관된 객체를 즉시 함께 조회할지, 실제 사용되는 시점에 지연해서 조회할지를 간단한 설정으로 조회

지연 로딩

  • 실제 객체를 사용하는 시점까지 데이터 베이스 조회를 미룬다.

 

4. 비교

  • 데이터베이스는 기본 키의 값으로 각 row를 구분한다.
  • 객체는 동일성 identity 비교와 동등성 equality 비교라는 두 가지 비교 방법이 있다.
    • 동일성 비교 == : 객체 인스턴스의 주소 값 비교
    • 동등성 비교 equals() : 메소드를 사용해 객체 내부의 값 비교
  • 패러다임의 불일치를 해결하기 위해 DB의 같은 row를 조회할 때마다 같은 인스턴스를 반환하도록 구현하는 것은 쉽지 않다.
  • 여러 트랜잭션이 동시에 실행되는 상황까지 고려하면 더 어렵다.

 

JPA 사용해서 해결

  • JPA는 같은 트랜잭션일 때 같은 객체가 조회되는 것을 보장한다.
String memberId = "100";
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.calss, memberId);

member1 == member2;  // 같다.

 

5. 정리

  • 객체 모델과 관계형 데이터베이스 모델은 지향하는 패러다임이 서로 다르다.
  • 정교한 객체 모델링을 할수록 패러다임의 불일치 문제가 더 커진다.
  • 소모 비용이 더 커진다. → 객체 모델 중심에서 데이터 중심의 모델로 변해간다.
  • JPA는 패러다임의 불일치를 해결해주고 정교한 객체 모델링을 유지하게 도와준다.

 

👩‍🏫 JPA란 무엇일까?

JPA Java Persistence API

  • 자바진영의 ORM 기술
  • 애플리케이션과 JDBC 사이에서 동작

JPA

 

ORM Object-Relational Mapping

  • 객체와 관계형 데이터베이스를 매핑한다는 뜻
  • 패러다임의 불일치 문제를 개발자 대신 해결해줌
  • SQL을 일일이 직접 작성할 필요 🙅‍♀️
  • 개발자가 객체를 자바 컬렉션에 저장하듯이 ORM 프레임워크에 저장하면,
  • 적절한 SQL을 생성해서 데이터베이스에 객체를 저장해준다.
  • 데이터 중심인 관계형 데이터베이스를 사용해도 객체지향 애플리케이션 개발에 집중할 수 있다.
  • 하이버네이트 프레임워크가 가장 많이 사용된다.

 

1. JPA 소개

EJB Enterprise Java Beans

  • 과거 자바 진영에서 만든 기술 표준
  • ORM 기술 포함 - 엔티티 빈
    • 복잡하고 기술 성숙도도 떨어졌다.
    • 자바 엔터프라이즈(J2EE) 애플리케이션 서버에서만 동작

하이버네이트 hibernate.org

  • 오픈소스 ORM 프레임워크 등장
  • EJB의 ORM 기술에 비해 가볍고 실용적, 기술성숙도도 높음

JPA Java Persistence API

  • EJB 3.0에서 하이버네이트를 기반으로 만든 새로운 자바 ORM 기술 표준
  • 자바 ORM 기술에 대한 API 표준 명세
  • 인터페이스를 모아둔 것
  • JPA를 사용하려면 JPA를 구현한 ORM 프레임워크를 선택해야 한다.
  • 특정 구현 기술에 대한 의존도를 줄일 수 있다.
  • 다른 구현 기술로 손쉽게 이동 가능

ORM 프레임워크

JPA 버전별 특징

  • JPA 1.0 (JSR 220) 2006년 : 초기버전, 복합키와 연관관계 기능 부족  
  • JPA 2.0 (JSR 317) 2009년 : 대부분의 ORM 기능 포함, JPA Criteria 추가
  • JPA 2.1 (JSR 338) 2013년 : 스토어드 프로시저 접근, Converter, 엔티티 그래프 기능 추가

 

2. 왜 JPA를 사용해야 하는가?

1) 생산성

  • JPA가 SQL을 작성하고 JDBC API를 사용하는 지루하고 반복적인 일을 대신 해준다.
  • 개발자는 자바 컬렉션에 객체를 저장하듯이 JPA에게 저장할 객체를 전달만 하면 된다.
  • DDL문을 자동으로 생성해주는 기능이 있다.
  • 데이터베이스 설계 중심의 패러다임을 객체 설계 중심으로 역전시킬 수 있다.

2) 유지보수

  • SQL 직접 다룰시 엔티티에 필드 하나만 추가해도 SQL문과 JDBC API 코드를 모두 변경해야 했다.
  • JPA 사용시 이런과정을 대신 처리해주므로 유지보수해야 하는 코드 수가 줄어든다.

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

  • 상속, 연관관계, 객체 그래프 탐색, 비교하기와 같은 패러다임의 불일치 문제를 해결해준다.

4) 성능

  • JPA는 애플리케이션과 데이터베이스 사이에서 다양한 성능 최적화 기회를 제공한다.
  • 애플리케이션과 데이터베이스 사이에 계층이 하나 더 있으면 최적화 관점에서 시도해 볼 수 있는 것들이 많다.
  • 하이버네이트는 SQL 힌트를 넣을 수 있는 기능도 제공한다.

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

  • 관계형 데이터베이스는 같은 기능도 벤더마다 사용법이 다른 경우가 많다. (페이징 처리)
  • 따라서 애플리케이션은 처음 선택한 데이터베이스 기술에 종속되고 다른 데이터베이스로 변경하기는 매우 어렵다.
  • JPA는 애플리케이션과 데이터베이스 사이에 추상화된 접근 계층을 제공해서
  • 특정 데이터베이스 기술에 종속되지 않도록 한다.

6) 표준

  • JPA는 자바 진영의 ORM 기술 표준이다.
  • 표준을 사용하면 다른 구현 기술로 손쉽게 변경할 수 있다.

 

정리

ORM에 대한 궁금증과 오해

Q. 통계 쿼리처럼 매우 복잡한 SQL은 어떻게 하나요?

A. JPA는 실시간 처리용 쿼리에 더 최적화되어 있습니다.

   1) JPA가 제공하는 네이티브 SQL 사용

   2) SQL 매퍼 형태(마이바티스나 스프링의 JdbcTemplate)의 프레임워크를 혼용

 

Q. 마이바티스와 어떤 차이가 있나요?

A. 마이바티스나 스프링의 JdbcTemplate를 SQL 매퍼라고 합니다.

     이것은 객체와 SQL을 매핑합니다.

     SQL 매퍼는 JDBC API 사용과 응답결과를 객체로 매핑해줍니다.

    개발자는 SQL을 직접 작성해야 하므로 SQL에 의존하는 개발을 피할 수 없습니다.

 

    ORM은 객체와 테이블을 매핑만 하면 ORM 프레임워크가 SQL을 만들어서 DB와 관련된 처리를 해줍니다.

    따라서 SQL에 의존하는 개발을 피할 수 있습니다. 

 

 

 

참조

김영한,  자바 ORM 표준 JPA 프로그래밍, 에이콘출판주식회사, 2015

자바 ORM 표준 JPA 프로그래밍 - 기본편

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com