JPA의 등장 배경

jyKim·2023년 1월 31일
0

JPA

목록 보기
1/7

JPA란 무엇인가?
먼저 JPA가 왜 등장하게 되었는지 그 환경부터 알아보자.

기존 개발 방식(SQL 중심적)

  • 기존 개발 방식에서 객체를 관계형 데이터베이스(RDB)에 저장하기 위해서는 아래 그림과 같은 절차가 필요하다.
    model
    1. 객체 -> SQL 변환
    2. SQL을 사용하여 DB 저장

그렇다면 이때, 객체를 SQL로 변환하여 SQL을 작성하는 역할을 누가 하는가??
정답은 개발자이다. 개발자가 객체를 RDB에 저장할 수 있도록 SQL을 작성해주는 SQL Mapper 업무를 하였다.
즉 SQL 의존적 개발을 피할 수 없었다. 하지만 이는 유지보수가 너무 어려웠다.

예를들어 User라는 테이블이 있고 필드로 id, pwd 2개의 값만을 가진다고 생각해보자.

public class User {
	private String userId;
    private String password;
}

User 클래스를 코드로 위와 같이 나타낼 수 있다. 이를 조작하는 간단한 SQL을 작성하면 아래와 같다.

  • INSERT INTO USER(USER_ID, PASSWORD) VALUES ...
  • SELECT USER_ID, PASSWORD FROM USER ...
  • UPDATE USER SET PASSWORD = ...

근대 만약 User 테이블에 TEL이 추가되어 아래와 같이 바뀌었다고 생각해보자

public class User {
	private String userId;
    private String password;
    private Stirng tel;
}

그렇다면 기존 사용하던 SQL에 모두 TEL 항목이 추가되어야한다.

  • INSERT INTO USER(USER_ID, PASSWORD, TEL) VALUES ...
  • SELECT USER_ID, PASSWORD, TEL FROM USER ...
  • UPDATE USER SET PASSWORD, TEL = ...

실무에서 사용되는 SQL은 훨씬 복잡하고 다양할 것이며 이를 모두 수정하는 것은 매우 어렵다.
동시에 객체와 RDB의 패러다임이 불일치에 따른 문제도 존재한다.

객체 vs RDB 패러다임 불일치

객체와 RDB 패러다임 불일치란 무엇일까??
크게 4개의 항목으로 알아볼 수 있다.

  • 상속
  • 연관관계
  • 데이터 식별 방법
  • 데이터 타입

상속

  • 객체에는 상속 관계가 존재하지만 RDB에는 상속관계가 존재하지 않는다.
  • 동시에 RDB에는 상속 관계를 저장할 수 없다.
  • 대신 부모, 자식 역할을 하는 테이블로 나누어 설계하고 필요할 때 조인하여 가져오도록 할 수 있다.
  • 이를 슈퍼-서브 타입 관계라고 하며, 이를 사용하여 상속 관계를 나타내게 된다.

하지만 위와 같이 설계를 하더라도 문제가 있다.

  1. INSERT -> ITEM, ALBUM에 대한 2개의 INSERT문이 필요
  2. SELECT -> 각각의 테이블에 대한 JOIN SQL이 필요
  3. 이에 따른 각각의 객체를 생성 및 데이터 입력
  4. 이후에도 추가로 복잡한 작업이 필요하게 됨

상상만해도 머리가 아픈 작업이 필요함 -> DB 저장할 객체에는 상속 관계를 사용하지 않음

연관관계

  • 객체는 참조를 사용 -> ex) member.getTeam()
  • 테이블은 외래키(FK)를 사용 -> JOIN ON M.TEAM_ID = T.TEAM_ID

이를 테이블에 맞춰 모델링하면 아래와 같아진다.

class Member {
	String id;
    Long teamId;		// TEAM_ID FK
    String username;
}
class Team {
    Long id;			// TEAM_ID PK
    String name;
}

테이블에 맞춰 객체를 설계할 경우 데이터베이스에 저장(INSERT)하는 것이 편리하다.
하지만 이것이 객체다운 모델링은 아니다. -> 객체는 참조로 연관관계를 맺는다.

객체에 맞춰 모델링하면 아래와 같다.

class Member {
	String id;
    Team team;		// 참조로 연관관계를 맺음
    String username;
    
    Team getTeam() {
    	return team;
    }
}
class Team {
	Long id;
    String name;
}

하지만 이 경우 데이터베이스에 저장(INSERT)하기가 어려워진다.
예시의 Member객체는 Team 객체를 참조하고 있을 뿐, Team의 PK를 직접적으로 가지고 있진 않다.
member.getTeam().getId()와 같이 가져올 수 있으나 번잡해진다.

심지어 조회를 할 경우에는 Member, Team을 Join을 통해 모두 가져온 후 각각의 Member, Team 객체에 세팅해 주어야 하기때문에 매우 복잡해진다.

객체 그래프 탐색

SQL 중심적 개발은 처음 실행하는 SQL에 따라 탐색 범위가 결정된다.
-> 엔티티 신뢰 문제 발생 및 객체 그래프 탐색이 자유롭지 않음

객체 그래프 탐색?
객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다.
member.getTeam()과 같이 .을 통해 참조로 따라갈 수 있어야한다.

최종적으로 진정한 의미의 계층 분할이 어렵다.

비교하기(데이터 식별)

String memberId = "10";
Member m1 = memberDAO.getMember(memberID);
Member m2 = memberDAO.getMember(memberID);

m1 == m2 // false! -> 각각의 새로운 객체를 생성하기 때문.

-> 결과적으로 객체답게 모델링 할 수록 매핑 작업만 늘어나게된다.
-> 같은 SQL을 통해 조회해 오더라도 서로 다른 객체에 저장하기 때문에 둘은 다른 객체이기 때문이다.
-> SQL을 작성하는 과정에 비용이 너무 들어가게 되기 때문에 이러한 설계를 결국 포기하게 됨

데이터 타입

객체와 DB 사이의 데이터 타입간의 충돌이 존재한다.
Java 코드상에서 사용하는 데이터 타입을 DB에서 그래도 사용하기에 제약사항이 존재한다.

만약 이들을 java 객체 처럼 사용 가능하다면? 컬렉션으로 관리 가능하다면?

복잡한 변환과정 없이 간단한 코드로 위의 문제가 되었던 작업들을 처리 가능하다.

상속

// INSERT
list.add(album);
// SELECT
Album album = list.get(albumId);
Item item = list.get(albumId); // 다형성 활용

연관관계

list.add(member);

Member member = list.get(memberId);
Team team = member.getTeam();
}

비교

String memberId = "10";
Member m1 = list.get(memberId);
Member m2 = list.get(memberID);

m1 == m2 // true -> list가 같은 객체를 반환해줌

이와 같이 객체를 마치 java 컬렉션에 저장하듯 DB에 저장하는 방법을 계속 연구해온 결과 JPA가 등장하였다.

profile
백엔드애옹

0개의 댓글