[Spring] JPA 소개

easyone·2024년 9월 18일
0

Spring

목록 보기
6/11

이 글은 김영한님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편' 강의 수강 후 정리한 글입니다.

JPA 소개

jpa에 대해 공부해보기 전에 기존에 사용하던 방식인 sql 중심 개발의 문제점, ORM, JPA의 장점 등에 대해 알아보려고 한다.

sql 중심적 개발의 문제점

1. 객체를 SQL로 하나하나 다 변환해야 한다.

2. 관계 표현이 어렵다.

관계형 데이터베이스에서는 상속 개념이 없기 때문에 슈퍼타입, 서브타입 관계로 상속 관계를 표현해야 한다. 즉 각각의 테이블에 join 관계를 작성해야 한다.
반면에 자바로 테이블을 설계할 경우에는,
- 자바 컬렉션에 저장할 경우, 부모 타입으로 조회해서 다형성 활용이 가능하다.
- 객체 연관관계의 경우, 참조로 연관관계를 맺기 때문에 객체다운 모델링이 가능하며, 외래키 시 해당 클래스 타입을 가져오면 된다.
(ex member.getTeam().getId();) → 멤버 객체

3. 객체 그래프 탐색이 어렵다.

4. 엔티티 신뢰 문제

  • 처음 실행하는 SQL에 따라 탐색 범위가 결정된다. 즉 계층형 아키텍쳐의 경우 그다음 계층을 믿고 사용할 수 있어야 하는데 ,
    class MemberService {
    	public void process() {
    
    	Member member = memberDAO.find(memberId); 
    
    	member.getTeam(); 
    
    	member.getOrder().getDelivery(); 

여기서 member.getTeam()을 호출하려면 객체 그래프를 자유롭게 탐색할 수 있어야 하는데, 계층 구조가 어떤지 모르기 때문에 로직을 짤 때 구조를 전체적으로 살펴봐야 Team을 조회하도록 할 수 있어서 번거로워진다. getOrder()와 getDelivery 또한 어떤 관계이며, 전체적으로 구조가 어떻게 되어 있는지 해당 코드만으로는 알 수 없으므로 문제가 생길 수 있다.

  • 모든 객체를 미리 로딩할 수 없다.

상황에 따라 동일한 회원 조회 메서드를 여러벌 생성해야 하고, SQL의 테이블은 물리적으로는 분할되어 있지만 논리적으로는 서로 엮여있으므로 join 횟수가 늘어나기 때문에 계층 분할이 어려워진다.

  • 객체답게 모델링할수록 매핑 작업만 늘어나고, SQL로 전환할 경우에 비용이 많이 들게 된다. ( 상속, 연관관계 , 데이터삽입 등의 작업이 복잡함 )

-> jpa(java persistence api)의 경우, 객체를 자바 컬렉션에 저장하듯이 DB에 저장하기 때문에 이러한 번거로운 문제들을 해결해준다.

ORM은 데이터베이스마다 차이가 있는 경우 생기는 문제점들을 해결하기 위해 객체 관계를 매핑해주는 역할을 한다.

ORM( object - relational mapping) : 객체 관계 매핑

- 객체는 객체대로 설계하고, 관계형 데이터베이스는 관계형 데이터베이스대로 설계한다. 
- ORM 프레임워크가 중간에서 차이점들을 매핑해서 해결하고, 패러다임의 불일치 등을 해결해준다. 
- 객체랑 관계형 데이터베이스를 매핑해준다. 

JPA

- jpa는 애플리케이션과 jdbc 사이에서 동작한다. 
- sql을 자동생성해준다. 
- JPA는 인터페이스의 모음이며, 표준 명세를 구현한 구현체는 세 종류 정도가 있지만 보통 Hibernate를 사용한다. 

JPA를 사용해야 하는 이유

객체 중심 개발 가능이 가능하다. 생산성,유지보수, 성능 관리 측면에서 이득이다.

  1. 생산성
    jpa.persist(member)를 통해 자바 컬렉션에 저장,조회,수정,삭제 하듯이 DB와의 CRUD가 가능하다.

  2. 유지보수
    기존에는 필드 변경 시에 모든 SQL을 수정해야하는데, 자동으로 수정해주기 때문에 유지보수가 용이해진다.

  3. 상속

    jpa는 상속 처리 시 jpa.persist 사용 시 sql에서는 insert 쿼리를 두번 실행해야 하지만 JPA에서는 자동으로 처리해서 매핑해준다. 자바 컬렉션사용하는 것처럼 하면 해주며, 조회의 경우에도 상속 관계의 경우 성능 최적화를 고려해서 JPA가 처리해준다.

  4. 객체 그래프 탐색 용이, jpa 연관관계 참조 사용 가능

    테이블은 외래 키를 사용해서 조인해서 매핑해야 하는데, 객체의 경우 참조를 통해 간단하게 매핑이 가능하다.

  5. 신뢰할 수 있는 엔티티, 계층

    지연 로딩을 통해 데이터를 조회한다는 점에서 객체 그래프 탐색이 자유롭게 가능하다는 장점이 있다.

  6. 1차 캐시와 동일성 보장

    String memberId = "100";
    Member m1 = jpa.find(Member.class, memberId); // SQL 실행 
    Member m2 = jpa.find(Member.class, memberId); // 캐시 
   같은 트랜젝션 안에서는 내부적으로 여러번 조회하는 로직이어도 sql문을 한번만 실행하고 그 이후에는 메모리 상에서 JPA가 이미 조회했었던 데이터를 가져와서 반환하게 되므로, 조회 성능이 약간 향상된다. 
    
   7. 트렌젝션을 지원하는 쓰기 지연
   
   트렌잭션 커밋할 때까지 insert sql을 버퍼에 작성해두고, 커밋할 때 JDBC BATCH SQL 기능을 사용해서 한번에 SQL을 전송한다. 
   
   8. 지연 로딩과 즉시 로딩
  
  Member member = memberDAO.find(memberId); 
  Team team = member.getTeam();
  String teamName = team.getName(); 
  • 지연 로딩 : 객체가 실제 사용될 때 로딩한다. 즉 find했을 때 member 만 가져오게 하고, getTeam()을 호출했어도 team의 name을 사용할 때까지 로딩하지 않고 있다가, team 데이터를 가져올 때 그 객체에 대해 select query를 날리는 것이다.
  • 즉시 로딩: JOIN SQL로 한번에 연관된 객체까지 미리 조회하므로, 멤버를 조회할 때 팀까지 같이 가져오고 싶으면 설정이 가능하다.
profile
백엔드 개발자 지망 대학생

0개의 댓글