본문 바로가기
  • 개발공부 및 일상적인 내용을 작성하는 블로그 입니다.
JPA

JPA 가 뭐지?

by 방구석 대학생 2020. 9. 1.

"인프런 - 자바 ORM 표준 JPA 프로그래밍 강의를 듣고 추가로 더 공부하여 정리한 글입니다."

www.inflearn.com/course/ORM-JPA-Basic#

 

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

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

www.inflearn.com

JPA 란 자바 진영의 ORM(Object - Relational Mapping) 의 기술 표준으로서

객체와 관계형 데이터베이스 간의 차이를 중간에서 해결해주는 프레임워크 이다.

 

JPA 의 구조도

 

JPA 는 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스 인데,

여기서 중요하게 생각해야 할 것이 바로 위에서 말한대로 JPA 는 인터페이스 라는 점이다.

 

여기서 인터페이스(interface) 란 특정한 메소드의 구현체가 존재하지 않는 하나의 규약을 말한다.

즉, JPA 는 특정한 기능을 사용할 수 있는 라이브러리가 아니라, 자바 어플리케이션 에서 관계형 데이터베이스를 어떻게 사용하면 되는지에 대해 정의해놓은 인터페이스 이자 규칙인 것이다.

 

때문에 JPA 는 직접 구현되어 있는 메소드가 없으므로 JPA 를 통해 선언되어 있는 구현체를 통해 직접 개발을 진행해야 한다.

- 대표적인 구현체의 예시가 바로 Hibernate 이다.(인터페이스를 직접 구현한 라이브러리)

 

 

그렇다면 JPA 를 활용하면 어떤 장점이 있을까?

1. 우선 객체와 데이터베이스 간에 데이터를 매핑하는데 있어 SQL 문을 직접 작성하지 않아도 된다.

- SQL 중심적으로 개발을 진행할 경우 실무에 있어 관리해야 할 데이터베이스 테이블이 한 두개가 아닌데, 그 테이블 들 하나하나에 객체의 데이터를 매핑해줘야 한다.

결국 똑같은 SQL 코드를 반복적으로 작성하게 되므로 개발 작업이 굉장히 지루해진다.

 

그러나 JPA 를 사용하면 JPA 측에서 JDBC API 를 호출하여 필요한 SQL 문을 따로 데이터베이스 측에 생성하여 전달해주므로 개발자는 SQL 작업에서 해방되어 좀 더 객체 지향 적인 코딩에 집중할 수 있게 된다.

 

 

2. 객체와 관계형 데이터베이스 간의 패러다임 불일치 문제를 해결해준다.

   - 객체와 관계형 데이터베이스는 지향하는 목적이 서로 다르므로 둘의 기능과 표현 방법도 다르다.

   

객체는 상속이라는 기능을 가지고 있지만 테이블은 상속이라는 기능이 없다.

그러나 JPA 는 상속과 관련된 패러다임의 불일치 문제를 개발자 대신 해결해준다. 마차 자바 컬렉션에 객체를 저장하듯이 JPA 에게 객체를 저장하면 된다.  

 

객체는 참조를 사용해서 다른 객체와 연관관계를 가지고 참조에 접근해서 연관된 객체를 조회한다.

반면에 테이블은 외래 키를 사용해서 다른 테이블과 연관관계를 가지고 JOIN 을 사용해서 연관된 테이블을 조회한다.

여기서 JPA 는 연관관계와 관련된 패러다임의 불일치 문제를 해결해준다.

 

 

정리하자면.....

객체는 객체대로 설계하고 관계형 데이터베이스는 관계형 데이터베이스 대로 설계한 후 ORM 을 이용해 중간에서 둘을 매핑한다.

객체지향 개발자는 객체지향 스럽게 개발하고, 관계형 데이터베이스는 관계형 데이터베이스 답게 설계를 한 다음

둘 사이의 차이는 ORM 프레임워크로 해결한다.

* JPA 가 JDBC API 를 사용해서 SQL 을 호출하고 결과를 반환받아 동작을 하게 된다.

 

JPA 를 이용한 데이터 저장의 경우....

JPA 에게 객체를 넘겨주면 해당 객체(Entity) 를 분석한 후 적절한 insert query 를 생성한 다음 JDBC API 를 활용하여 해당 쿼리를 DB 에 보낸다.

여기서 중요한 것은 쿼리를 개발자가 작성하는 것이 아니라 JPA 가 해준다는 것과 패러다임의 불일치 문제를 해결해 준다는 것이다.

 

JPA 를 이용한 데이터 조회의 경우

애플리케이션에서 find(id) 메소드를 통해 JPA 에게 찾고자 하는 객체의 id 값을 넘겨주면 JPA 는 SELECT SQL 을 생성하여 JDBC API 를 활용해 해당 쿼리를 DB 로 보낸다.

이후 SELECT query 의 결과를 ResultSet 객체에 저장하여  해당 데이터를 애플리케이션 측에 반환해준다.

 

 

JPA 에 의한 성능 최적화

애플리케이션과 DB 사이의 중간 계층으로서 JPA 는 버퍼링 과 캐싱 기능을 제공한다.

 

- 캐싱의 경우 첫번째 반환에서 SQL 을 통해 반환을 해주었을 때 연속으로 같은 데이터가 조회 되었을 경우 캐싱을 통해 메모리에 있던 첫번째 데이터를 그대로 다시 반환해준다.

   -> 결과적으로 SQL 이 한번만 실행된다.

 

- 버퍼링의 경우 비슷한 query 가 발견되었을 때 트랜잭션을 지원하는 '쓰기 지연' JDBC BATCH SQL 기능을 사용해서 한번에 SQL 을 전송해준다.

데이터베이스는 트랜잭션이 정말 중요하다, 쿼리를 따로따로 보내든 한번에 보내든 한 트랜잭션 안에서만 수행되면 된다.

JPA 는 메모리에 SQL 을 쌓아 두었다가 transaction.commit 시 비슷한 쿼리가 발견되면 JDBC BATCH SQL 을 통해 한번에 네트워크를 통해 DB 로 쿼리를 보내준다. 

 

 

지연 로딩과 즉시 로딩

- 지연 로딩 : 객체가 실제로 사용될 때 로딩 된다. 문제점으로 쿼리가 많이 나갈 수 있다.

Memeber member = memberDAO.find(memberId); // SELECT * FROM MEMBER
Team team = member.getTeam();
String teamName = team.getName(); // SELECT * FROM TEAM

 

- 즉시 로딩 : JOIN SQL 로 한번에 연관된 객체까지 모두 미리 조회해서 가져온다.

Member member = memberDAO.find(memberId); // SELECT M.*, T.* FROM MEMBER JOIN TEAM
Team team = member.getTeam();
String teamName = team.getName();