지금 시대는 객체를 관계형 DB에 저장해 관리하는 것을 매우 중요하게 여기고 있다. 이것을 관리하기 위해 전통적으로 계속 쓰였던 것이 SQL이다. 하지만 SQL 중심으로 개발을 하면 여러 가지 문제점에 직면하게 된다.
SQL 중심적인 개발의 문제점
1. 무한 반복, 지루한 코드
이번에 학교에서 jdctemplete을 공부하면서 느꼈다. 코드가 무한 반복이고 너무 길어 노가다라는 느낌을 많이 받았다.
2. SQL에 의존적인 개발을 피하기 어렵다.
객체를 영구 보관하는 다양한 저장소 중 제일 많이 사용하는 것은 관계형 데이터베이스이다. 관계형 데이터베이스를 사용하게 되면 객체에서 SQL변환 후 SQL이 관계형 데이터베이스에 들어가야 하는 많은 절차를 따르게 된다. 이렇게 되면 SQL을 잘 사용하고 SQL에 대한 모든 것을 알고 있어야 손쉽게 RDB를 관리할 수 있다.
3. 개발자가 SQL 모두 변환
결국 개발자가 SQL 매퍼로써 모든 부분에 대한 코드를 짜야한다.
객체와 관계형 데이터베이스 차이
객체와 관계형 데이터베이스 차이는 상속, 연관관계, 데이터 타입, 데이터 식별 타입 등이 다르다.
1. 상속
객체 지향 프로그래밍에서는 상속 관계가 존재 한다. 관계형 데이터베이스도 상속 관계로 테이블을 만들어 사용할 수 있다. ITEM ID를 주요 키를 두고 밑에 앨범, 영화, 북 테이블에 ITEM ID 주요 키를 주요 키이자, 외래 키로 설정하는 것이다.
하지만 이렇게 하면 큰 단점이 존재한다.
Album을 조회한다고 생각하고 과정을 적어보면 각각의 테이블에 따른 조인 SQL 작성하고 각각의 객체를 생성하고 그에 따른 데이터들을 하나씩 비교해줘야 한다. 과정이 매우 복잡해지므로 상속 관계는 잘 안 쓴다고 한다.
=> 만약 자바 컬렉션에 저장하거나 조회 한다면?
list.add(album);으로 앨범에 대한 객체를 모두 리스트에 저장하고 필요할 때 Album album = list.get(albumId);로 album을 가져올 수 있다. 또, 부모 타입으로 조회 후 다형성 활용을 위해 Item item = list.get(albumId);를 통해 부모 테이블에도 접근 가능해진다.
2. 연관 관계
객체는 참조를 사용 : member.getTeam() VS 테이블은 왜래 키를 사용 : join on m.team_id = t.team_id
이렇게 하면 객체를 테이블에 맞추어 모델링을 한다.
Member테이블에 member_id, team_id, username이 들어 있고, Team에는 team_id, name이 들어 있다. Member를 객체에 맞게 만들기 위해서는 멤버라는 class에 String id; Long teamId, String username이 들어가 있어야 한다. 왜냐하면 멤버를 insert 할 때, team_id가 필요하기 때문이다.
- 하지만 이렇게 하는 것이 객체 대운 모델링일까?
객체는 참조로 연관 관계를 맺는다. 그러므로 class Member에는 위에 내용이 아닌 string id;, Team team, String username이 들어있어야 한다. 이때 insert 할 때 team_id를 얻어올 때 member.getTeam(). getId()로 가져와야 한다.
- 객체 모델링을 조회할 때는 더 큰 문제가 생긴다.
select M.*, T.*
from Member m
join Team t on m.team_id = T.team_id
를 실행한다고 할 때, 데이터베이스에서 조회한 회원 관련 정보를 모두 객체에 저장하고 또 조회한 팀 관련 정보를 모두 입력한 뒤 회원과 팀 관계를 세팅하기 위해 member.stTeam(team);을 통해 set 해줘야 한다.
=> 만약 자바 컬렉션에 관리를 한다면
list.add(member); Member member = list.get(memberId); Team team = member.getTeam();을 통해 쉽게 멤버를 조회하고 관리할 수 있다.
- 객체 그래프 탐색을 할 때도 문제가 생긴다.
위에 코드를 실행한다고 가정해보자. Member 객체 아래에 team과 order가 존재한다고 할 때 저 코드로는 member.getOrder()에 접근할 수가 없다. 이러면 엔티티 신뢰 문제가 발생할 수 있다.
- 모든 객체를 미리 로딩할 수는 없다.
모든 것을 쿼리로 만들어 놔야 한다. ex) memberDao.getMember(); memberDao.getMemberWithTeam(); 등등
계층형 아키테처 진정한 의미의 계층 분할이 어렵다.
물리적으로는 분할이 되어 있으나 논리적으로는 붙어있다.
String memberId = "100";
Member member1 = memberDao.getMember(memberId);
Member member2 = memberDao.getMember(memberId);
를 비교한다면 member1 == member2를 할 경우 false가 리턴될 것이다. 왜냐하면 getMember를 통해 받으면 둘의 인스턴스는 다르기 때문이다.
=> 만약 자바 컬렉션에 관리를 한다면
String memberId = "100";
Member member1 = list.get(memberId);
Member member2 = list.get(memberId);
컬렉션에서 같은 것을 참조하므로 비교하면 True라는 결과가 나온다.
결론적으로 강사님이 말씀하시는 것은 객체답게 모델링할수록 매핑 작업만 늘어난다는 것이다.
그래서 고민한 결과 객체를 자바 컬렉션에 저장하듯이 DB에 저장할 수는 없을까?라는 질문으로부터 JPA가 탄생했다고 한다.
강의 출처 : https://www.inflearn.com/course/ORM-JPA-Basic
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런
www.inflearn.com
'BackEnd > 자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글
JPA 엔티티 매핑(필드와 컬럼 매핑, 기본 키 매핑) (1) | 2022.12.22 |
---|---|
JPA 엔티티 매핑(객체와 테이블 매핑) (0) | 2022.12.22 |
JPA 영속성 관리 - 내부 동작 방식 (0) | 2022.12.22 |
JPA 시작 (1) | 2022.12.22 |
JPA 소개(자바 ORM 표준 JPA 프로그래밍 - 기본편) (0) | 2022.12.21 |