Back-End/JPA

[북스터디] 자바 ORM 표준 JPA 프로그래밍 : JPA 소개

newny 2024. 5. 12. 20:04
반응형

Intro


JPA 사용 방법에 대해서는 잘 알고 있지만, 정확한 핵심 원리 개념이 부족한 것 같아서 이제부터 주말마다 김영한 저자의 책 '자바 ORM 표준 JPA 프로그래밍'에 대해서 읽고 정리한 것을 블로그에 남길 예정이다.
오늘은 그 시작인 '제1장 : JPA 소개'에 대한 글을 써보겠다.
 
 
 
 

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


반복적인 CRUD SQL & JAVA 코드

어떠한 서비스를 만들었다고 가정할 경우, 그 값을 데이터베이스에 저장할 때를 생각해 보자. 서비스에 해당하는 SQL작성, 객체의 값을 꺼내서 해당 SQL에 전달, JDBC API를 사용해서 SQL을 실행 과정들을 거칠 것이다. 그리고 서비스가 여러 개 생성될 경우 위의 과정을 계속해서 반복해야 한다.
만약 데이터베이스가 아닌 컬렉션에 보관한다면 코드 한 줄로 객체 저장이 가능하다. (예 : list.add(member);)
 

SQL에 의존적인 개발

예를 들어 요구 사항이 추가된다면 DDL 수정 → 조회(Read) 코드 변경 → 수정(Update) 코드 변경 등 관련된 모든 SQL & JAVA 코드를 수정해야 한다. 
또한 A 테이블과 연관 관계가 있는 B 테이블이 있을 경우 A 테이블을 조회하는 메서드만으로는 B 테이블까지 조회할 수 없다. 그렇기에 A 테이블과 B 테이블의 조인으로 조회되는 메서드가 따로 존재해야 한다.
결론적으로 SQL에 모든 것을 의존하다 보니 엔티티를 신뢰할 수 없게 된다. 따라서 수시로 DAO를 열어 SQL을 확인해야 하는 불편함이 발생하게 되고, 이것은 완전한 계층분할이 되지 않았다는 것을 의미한다.

- 진정한 의미의 계층 분할이 어려움
- 엔티티를 신뢰할 수 없음
- SQL에 의존적인 개발을 피하기 어려움

 
 
 
 

패러다임의 불일치


애플리케이션은 발전하면서 그 내부의 복잡성도 점점 커진다. 객체 지향 프로그래밍은 캡슐화, 상속, 추상화, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다. 따라서 현대의 복잡한 애플리케이션은 대부 부분 객체 지향 언어로 개발된다.
따라서 객체로 도메인 모델을 저장하게 되면 객체지향 언어가 가진 장점을 활용할 수 있게 된다. 하지만 이 객체를 메모리가 아닌 어딘가에 영구 보관해야 하는 문제가 발생된다.
 
데이터베이스에 객체를 저장하는 방법?
데이터 베이스는 데이터 중심으로 구조화되어 있다. 따라서 객체지향의 추상화, 상속, 다형성 같은 개념이 없다. 그러므로 객체를 데이터베이스에 저장하는 데에는 한계가 있다.
 
패러다임의 불일치
객체와 관계형 데이터베이스는 지향하는 목적이 서로 다르므로 둘의 기능과 표현 방법이 다르다. 그러므로 패러다임의 불일치가 발생될 수밖에 없다. 그러므로 객체를 관계형 데이터베이스에 저장하려면 패러다임 불일치 문제를 개발자가 중간에서 해결해야 한다.
 

상속

B 테이블이 A 테이블을 상속받는 관계를 만들었다고 가정하자.
B 테이블은 A 테이블을 상속받았으므로 그 저장 과정에서 A 테이블에 해당되는 값을 저장하는 쿼리, B 테이블에 해당되는 값을 저장하는 쿼리, 총 두 개의 쿼리를 사용해야 B테이블의 값을 저장할 수 있다.
또한 B 테이블을 조회하는 방법으로는 상속관계에 있는 A 테이블과 B 테이블을 조인한 결과로 B 객체를 생성하여 조회하여야 한다.
결론적으로 위의 과정을 통해 패러다임 불일치를 해결했지만 그에 따른 비용이 많이 든다.
JPA는 위의 과정들을 알아서 해결해 줄 수 있다.
 

연관관계

객체의 경우 참조를 통해 연관 테이블의 조회가 가능하고, 테이블의 경우에는 외래키를 통한 연관 테이블의 조회가 가능하다. 여기서 패러다임 불일치가 발생한다.
객체는 참조가 있는 방향으로만 조회가 가능하다. (예 : member.getTeam() 참조가 있을 경우 조회 가능, team.getMember는 참조가 없다면 조회 불가능)
테이블은 외래키 하나로 양방향 조회가 가능하다. (MEMBER JOIN TEAM, TEAM JOIN MEMBER)
 
객체를 테이블에 맞추어 모델링한다면?
외래키가 객체 내부의 속성으로 저장되므로 관계형 데이터베이스 입장에서는 편리할 수 있으나, 참조로 연관된 객체를 찾아야 하는 경우에는 조회할 수 없게 된다. 또한 객체지향의 특징을 잃어버리게 된다.
 
데이터 베이스를 객체지향으로 모델링한다면?
위의 예시를 통해 알 수 있듯 객체를 통한 참조관계의 객체를 조회하려면 결국 참조를 이용해야 한다. 하지만 객체지향 모델링을 이용하고 싶어도 객체를 테이블에 저장하거나 조회하기란 쉽지 않다.
 
결론적으로 객체에서는 참조관계의 객체를 조회하려면 참조가 필요하고, 테이블에서는 참조관계 테이블의 조회에는 외래키가 필요한데, 그 중간에서 변환 역할을 개발자가 해주어야 한다. 
JPA는 중간 변환자의 역할까지 도맡아서 처리해 준다.
 

객체 그래프 탐색

객체는 참조를 통해 연관 객체를 찾을 수 있으므로 메서드 체이닝을 통해 객체 그래프 탐색이 가능하다. 하지만 테이블의 경우 조인에 사용된 테이블로만 조회가 한정되므로 객체 그래프 탐색이 불가능하다. 결국 SQL을 이용하게 되면 조회가 한정될 수밖에 없다. 또한 객체 그래프 탐색이 가능한지 살펴보려면 DAO를 열어서 SQL을 직접 확인해봐야 한다. 결국 SQL에 의존적이게 된다.
JPA를 이용하게 되면 지연 로딩*을 통해 객체 그래프를 마음껏 탐색할 수 있게 된다.
 
*지연로딩 : 객체와 매핑정보를 보고 적절한 SELECT SQL을 생성함 → 실제 객체를 사용하는 시점까지 데이터베이스 조회를 미룸
 

비교

객체의 경우 같은 아이디를 넣어 회원을 두 번 조회할 경우 반환되는 객체의 인스턴스 주소 값이 서로 다르다. 하지만 데이터베이스 조회의 경우 같은 아이디로 두 번 조회할 경우 같은 row가 반환되어야 한다.
JPA를 사용하면 동일성 비교(인스턴스 주소값 비교)에 성공할 수 있다. (자세한 이론은 추후에 나옴)
 
 
 
 

JPA란 무엇일까?


출처 - https://ultrakain.gitbooks.io/jpa/content/chapter1/chapter1.3.html
  • Java Persistence API (자바 영속 API)
  • 하이버네이트는 거의 대부분의 패러다임 불일치 문제를 해결해 주는 ORM이다.

 

JPA 소개

출처 - https://ultrakain.gitbooks.io/jpa/content/chapter1/chapter1.3.html

JPA는 자바 ORM 기술에 대한 API 표준 명세이다. 특정 구현 기술에 대한 의존도를 줄일 수 있고 다른 구현 기술로 손쉽게 이동할 수 있는 장점이 있다.
 

왜 JPA를 사용해야 하는가?

생산성

  • 반복적인 코드와 CRUD용 SQL을 개발자가 직접 작성하지 않아도 된다. 더 나아가서 DDL 문을 자동으로 생성해 주는 기능도 있다.

 
유지보수

  • JPA를 사용함으로써 개발자가 해야 했던 유지보수를 JPA가 대신 처리해 준다. 또한 JPA의 패러다임 불일치 해결로 인해 유지보수하기 좋은 도메인 모델을 편리하게 설계할 수 있다.

 
패러다임 불일치 해결

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

 
성능

  • JPA는 다양한 성능 최적화 기회를 제공한다. 예를 들어 JPA는 같은 회원을 여러 번 조회할 경우 첫 번째 조회에는 JDBC API를 사용해서 해당 코드를 직접 작성했다면, 두 번째 조회부터는 조회한 회원 객체를 재사용하여 중복되는 통신의 횟수를 줄일 수 있다.

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

출처 - https://ultrakain.gitbooks.io/jpa/content/chapter1/chapter1.3.html
  • 같은 기능도 벤더마다 사용법이 다르다.(예: 페이징 방법) JPA는 애플리케이션과 데이터베이스 사이에 추상화된 데이터 접근 계층을 제공하여 애플리케이션이 특정 데이터베이스 기술에 종속되지 않도록 한다.

 
 
 
 

ORM에 대한 궁금증과 오해


책에 'ORM에 대한 궁금증과 오해'라는 부분이 잘 정리되어 있고, 실제 궁금했던 부분이 있어서 그 부분만 요약해 본다.
 

마이바티스와 JPA의 차이

마이바티스나 스프링 Jdbc Template를 보통 SQL 매퍼라 한다. SQL 매퍼의 경우 이름 그대로 객체와 SQL을 매핑해주기는 하나 결국 SQL을 개발자가 직접 작성해야 하므로 SQL에 의존하는 개발을 피할 수 없다. 반면 ORM은 객체와 테이블을 매핑만 하면 ORM 프레임워크가 데이터베이스와 관련된 처리를 해주므로 SQL에 의존하는 개발을 피할 수 있다.
 

JPA의 학습곡선

JPA의 학습 곡선이 높은 이유는 ORM이 객체 지향과 관계형 데이터 베이스라는 두 기둥 위에 있기 때문이다. 이 둘의 기초가 부족하면 어려울 수밖에 없다.
 
 
 
 

결론


JPA는 객체지향의 특성을 너무나도 잘 활용한 예시로 보인다. 그러면서도 데이터베이스와의 패러다임 불일치까지 해결해 주는 굉장히 똑똑한 녀석이다. JPA가 객체와 데이터베이스와의 패러다임 불일치를 해결해 준다는 것은 알고 있었지만, 어떤 부분으로 인해 패러다임 불일치가 생기고 어떻게 해결하는지 까지는 잘 몰랐는데 이번 북 스터디를 통해 알게 되었다. 결국 JPA가 어떻게 패러다임 불일치를 해결했느냐가 이 책을 관통하는 가장 큰 주제인 것 같다.
 

 
 

출처

자바 ORM 표준 JPA 프로그래밍 - 김영한 지음 (에이콘 출판)
https://ultrakain.gitbooks.io/jpa/content/chapter1/chapter1.3.html

반응형