[JPA] JPA 개념

Gajun Choi·2022년 9월 16일
0

JPA

목록 보기
1/4

요약

  1. ORM
  2. JPA
  3. 결론

JPA(Java Persistence API) : Java 에서 ORM(Object-Relational Mapping) 기술 표준으로 사용되는 인터페이스 모음

1. ORM(Object-Relational Mapping)

애플리케이션의 Class 와 RDB(Relational DB)의 테이블을 매핑한다는 뜻이다.
= 기술적으로 애플리케이션의 객체를 RDB 테이블에 영속화 해줌

장점

  • SQL문이 아닌 Method를 통해 DB를 조작할 수 있어, 개발자는 객체 모델을 이용하여 비즈니스 로직을 구성하는데만 집중할 수 있음.
    (내부적으로는 쿼리를 생성하여 DB를 조작함. 하지만 개발자가 이를 신경 쓰지 않아도됨)
  • Query와 같이 필요한 선언문, 할당 등의 부수적인 코드가 줄어들어, 각종 객체에 대한 코드를 별도로 작성하여 코드의 가독성을 높임
    객체지향적인 코드 작성이 가능하다. 오직 객체지향적 접근만 고려하면 되기때문에 생산성 증가
    매핑하는 정보가 Class로 명시 되었기 때문에 ERD를 보는 의존도를 낮출 수 있고 유지보수 및 리팩토링에 유리
  • 예를들어 기존 방식에서 MySQL 데이터베이스를 사용하다가 PostgreSQL로 변환한다고 가정해보면, 새로 쿼리를 짜야하는 경우가 생김. 이런 경우에 ORM을 사용한다면 쿼리를 수정할 필요가 없음

단점

  • 프로젝트의 규모가 크고 복잡하여 설계가 잘못된 경우, 속도 저하 및 일관성을 무너뜨리는 문제점이 생길 수 있음
  • 복잡하고 무거운 Query는 속도를 위해 별도의 튜닝이 필요하기 때문에 결국 SQL문을 써야할 수도 있음

2. JPA(Java Persistence API)

Java 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용하는 인터페이스 모음
자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스
인터페이스 이기 때문에 Hibernate, OpenJPA 등이 JPA를 구현함

왜 JPA 를 쓰는가?

  • JPA와 모던 자바 데이터 저장기술
    애플리케이션 객체 지향 언어 + 관계형 DB 에서 객체를 영구 보관하는
    다양한 저장소(RDB, _NoSQL, File 등)가 존재하지만 현실적인 대안은 관계형 DB이다.

  • 객체를 관계형 DB에 저장해 관리하는 것이 중요해짐
    관계형 DB를 사용하려면 SQL을 짤 수 밖에 없다 = SQL에 의존적인 개발

  • But!!! SQL 중심 개발에는 여러 문제가 있음

SQL 중심 개발의 문제점

2.1. 코드 반복

  • CRUD 의 반복

  • 자바 객체와 SQL 의 변환하는 과정의 반복
    Ex)
    회원에 이름 정보를 추가해보자
    Member 클래스에 private int name 을 선언하고
    INSERT, SELECT, UPDATE 등 관련된 쿼리에 name 정보를 추가
    호출도 반대의 과정이 필요

2.2. 객체지향과 관계형 DB 간의 패러다임 불일치'

  • 객체지향
    추상화, 캡슐화, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 서비스 제공

  • RDB
    데이터를 잘 정규화해서 보관, 관리하는 것이 목표

결국 패러다임이 다른 두 가지를 가지고 억지로 매핑하기 때문에 여러 문제가 생김

JPA를 사용하여 얻을 수 있는 가장 큰 것은 SQL아닌 객체 중심으로 개발할 수 있다는 것이다. 이에 따라 당연히 생산성이 좋아지고 유지보수도 수월하다. 또한 JPA는 패러다임의 불일치도해결하였다. 예를 들면 JAVA에서는 부모클래스와 자식클래스의 관계 즉, 상속관계가 존재하는데 데이터베이스에서는 이러한 객체의 상속관계를 지원하지 않는다(상속 기능을 지원하는 DB도 있지만 객체 상속과는 다름). 이런 상속관계를 JPA는 아래와 같은 방식으로 해결하였다.

2.3. 객체와 RDB의 차이

1) 상속

  • Object : 상속 있음

  • RDB : 상속 없음 - 유사한 물리 모델로, 슈퍼-서브 타입 관계가 존재

    출처 : 자바 ORM 표준 프로그래밍

  • Album 객체를 DB에 저장해보자
    a. 객체 분해 (Album 객체는 Item의 속성을 모두 가짐)
    b. 각각 다른 테이블에 대한 INSERT 쿼리 두 번 작성

    		INSERT INTO ITEM ...
     		INSERT INTO ALBUM ...
  • Album 을 조회하는 과정 (얘가 에바임)
    a. 각각의 테이블에 따른 Join SQL 작성 -> Item 과 Album 을 Join 해서 데이터를 가져옴
    b. 각각의 객체를 생성하고 모든 필드 값을 세팅 -> Item 과 Album 각각 모든 필드값을 세팅
    c. Movie, Book 을 조회하고 싶으면 위의 과정을 다시 반복 -> DB에 저장할 객체에는 상속을 이용하지 않아서 발생하는 문제

  • 자바 컬렉션에 저장하기
    a. 저장 : list.add(album);
    b. 조회 : Album album = list.get(albumId);
    c. 다형성 활용 : Item item = list.get(albumId);

  • 자바의 컬렉션에 저장하면 단순한 작업이 RDB를 거치는 순간 번거로운 매핑 작업을 해야함

2) 연관 관계

  • Object
    a. Reference 를 사용하여 연관 관계를 찾음 - member.getTeam();
    b. 단방향으로만 관계가 존재 - Member -> Team 은 가능하지만 반대는 불가능

  • RDB
    a. 외래키, join 쿼리를 통해 연관 관계를 찾음 - JOIN ON M.TEAM_ID = T.TEAM_ID
    b. 양방향으로 모두 조회 -> 단방향 존재 x

3) 데이터타입

4) 데이터 식별 방법

2.4. 모델링 과정에서의 문제

class Member { 
    String id;       // MEMBER_ID 컬럼 사용
    Long teamId;     // TEAM_ID FK 컬럼 사용
    String username; // USERNAME 컬럼 사용
}
class Team { 
    Long id;         // TEAM_ID PK 사용
    String name;     // NAME 컬럼 사용
}
  • 객체를 테이블에 맞추어 모델링
    조인이나 FK 를 통해 MEMBER.TEAM_ID 값이 TEAM에 추가 되면서 객체지향스럽지 않은 상황이 발생
class Member { 
    String id;        // MEMBER_ID 컬럼 사용 
    Team team;        // 참조로 연관관계를 맺는다. //** 
    String username;  // USERNAME 컬럼 사용 
                     
    Team getTeam() { 
        return team; 
    } 
}
class Team { 
    Long id;         // TEAM_ID PK 사용 
    String name;     // NAME 컬럼 사용 
}

ㄴ 객체지향 모델링

  • Team 객체의 참조값 자체를 필드에 넣음
  • 이렇게 설계된 객체를 DB에 저장하려면 member.getTeam().getId() 로 값을 얻어와 TEAM_ID에 넣는다.
	INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES ...        
  • Member 객체를 조회하기 위해서는
    a. MEMBER 와 TEAM 을 JOIN 해서 데이터를 한 번에 모두 가져온다.
    b. MEMBER 와 TEAM 에 개한 값을 각각 세팅한다.
    c. member.setTeam(team); rhk rkxdl wlrwjq dusrhks rhksrPfmf aowdjwnsek.
    d. 해당 member 객체를 반환한다.
    => 데이터 조회의 복잡성

  • 자바컬렉션에서 관리하면 조회의 복잡성을 사라지지만 관리의 효율이 떨어지게 된다.

2.5 객체 그래프 탐색에서의 문제

  • 객체는 자유롭게 객체 그래프를 탐색할 수 있어야 하지만 서비스 로직에서 RDB와 연결된 데이터를 탐색할 때 객체 그래프를 탐색할 수 없다.
    Cuz - SQL 탐색은 범위가 결정되어있기 때문
    ex) MEMBER 테이블을 가져왔다면 TEAM 테이블을 가져오지 않았기에 TEAM 데이터는 NULL 이다.

  • 위 현상은 Entity 신뢰의 문제로 이어지는데 예를 들어 내가 만든 서비스 로직에 다른 사람이 사용하고자 하면 DAO에서 반환한 엔티티가 어떤 값인지 직관적으로 알 수 없다.

  • 이와 같이 계층형 아키텍쳐(Layered 아키텍처)에서는 계층간의 신뢰가 필요한데 엔티티를 신뢰할 수 없는 문제가 발생하기 때문에 문제가 생길 수 있다.

3. 결론

  • RDB를 객체답게 모델링 할 수록 매핑 작업이 늘어나기 때문에 객체를 자바 컬렉션에 저장하고 불러오는 방법처럼 DB에 저장하는 방법을 고안해 낸것이 JPA(Java Persistence API) 이다.
profile
개발하는헬창

0개의 댓글