티스토리 뷰
개요
SQL을 직접 다룰 때 발생하는 문제, 이를 해결해주는 JPA의 기능에 대해 알아보자
SQL을 직접 다룰 때 발생하는 문제
비슷한 코드의 반복 작업
JDBC API를 사용하여 하나의 회원 조회 기능을 만든다고 가정할 때
- 회원 조회 SQL 작성
- JDBC API를 사용하여 SQL 실행
- 데이터를 회원 객체와 매핑
이러한 작업을 매 SQL 요청마다 반복해야 한다.
SQL에 의존적인 개발
회원 테이블에 이메일 필드를 추가할 경우에 변경해야 하는 코드
- 등록 코드
- 조회 코드
- 수정 코드
개발자가 직접 일일히 수정해야 한다.
엔티티 신뢰의 어려움
엔티티는 비즈니스 요구사항을 모델링한 객체이다.
Member 엔티티가 Team 엔티티를 참조하고 있고 Member에서 Team 값을 조회하는 비즈니스 로직이 있을 때 DAO에 Member 엔티티만을 가져오는 SQL문이 있는지 조인한 SQL문이 있는지에 따라 결과가 달라지므로 논리적으로는 계층이 분할되어있지만 강한 의존 관계를 지니게 되어 엔티티 자체만을 신뢰하기는 어려워진다.
패러다임의 불일치
객체지향 프로그램과 관계형 데이터베이스는 애초에 탄생 이유가 다르므로 둘의 기능과 표현 방법이 다르다. 그렇기 때문에 패러다임 불일치 문제가 발생하게 되고 개발자가 직접 이를 해결해야 하는데 그렇게 되면 개발자는 너무 많은 코드를 작성하게 되는 어려움이 생긴다.
이러한 패러다임 불일치를 개발자 대신 해결해주기 위해 나온 것이 JPA이다.
JPA란 무엇인가
: Java Persistence Api의 약어로 인터페이스이며 자바 ORM 기술 표준
ORM? Object Relational Mapping의 약어로 객체와 테이블을 매핑해서 패러다임의 불일치를 개발자 대신 해결해주는 개념
Spring Data JPA
JPA의 구현체로는 대표적으로 Hibernate, Eclipse, Link 등이 있고 개발자들은 이러한 구현체를 더욱 쉽게 사용하고자 추상화시킨 Spring Data JPA라는 라이브러리를 사용하여 JPA기술을 사용한다. (JPA > Hibernate > Spring Data JPA)
JPA의 패러다임 불일치 해결
: JPA를 사용하게 되면 개발자가 직접 SQL을 작성하는 것이 아니라 JPA가 객체 지향 적인 코드를 보고 패러다임 불일치를 해결할 적절한 SQL을 생성해서 데이터베이스에 전달하게 된다.
1. 상속
: 객체는 상속이라는 개념이 있지만 관계형 데이터베이스는 상속이라는 개념이 없기 때문에 나타나는 패러다임의 불일치이다.
아래의 코드처럼 Album이 Item을 상속받고 있고 데이터베이스는 서브타입 관계로 모델링이 되어있다고 가정을 하였을 때
class Item {
private int id;
private String name;
private int price;
}
class Album extends Item {
private String actor;
}
JPA를 사용하여 Ablum 객체를 저장하게 된다면 저장 시엔 Ablum, Item을 두 테이블에 나눠 저장해주고 - persist()
INSERT INTO ITEM ...
INSERT INTO ALBUM ...
조회 시엔 Item, Ablum 테이블을 조인하여 필요한 데이터를 조회한다 - find()
SELECT I.*, A.*
FROM Item I
JOIN Album A ON I.ITEM_ID = A.ALBUM_ID
-> 원래는 이러한 SQL 문을 직접 작성해야 했지만 컬렉션을 사용하는 것 처럼 JPA API를 사용하면 자동으로 이러한 SQL문을 생성하여 실행하여준다.
2. 연관 관계
: 객체는 참조를 사용하여 단방향 참조만 가능하지만 테이블은 외래키를 사용한 양방향 참조가 가능하기 때문에 나타나는 패러다임 불일치이다.
-> 객체는 참조를 통해 다른 객체와 연관 관계를 맺고 참조에 접근하여 연관된 객체를 조회(단방향)
-> 테이블은 외래 키를 통해 다른 테이블과 연관 관계를 맺고 조인을 통해 연관된 테이블을 조회(양방향)
아래의 코드처럼 Member가 Item 객체를 참조하고 데이터베이스는 외래 키를 통해 연관 관계를 맺고 있다고 가정하자
class Member {
private Long id;
private Team team;
private String username;
}
class Team {
private Long id;
private String teamName;
}
JPA는 데이터 저장 시 team 필드를 외래 키로 변환하여 INSERT SQL을 실행하게 되고 조회 시에는 조인을 통해 테이블의 외래 키를 참조로 변환해준다.
jpa.persist(member); //Member 테이블 저장 + Team 테이블 저장 + 연관관계 설정
jpa.find(Memberlcass, memberId); //외래 키를 사용한 조인을 통해 Team 참조 객체까지 조회
3. 객체 그래프 탐색
: 참조를 통해 참조 객체를 조회하는 행위를 객체 그래프 탐색이라고 한다.
아래의 코드와 같이 객체들의 연관관계가 설정되어있다면
class Member {
private Long id;
private String userName;
private Team team;
}
class Team {
private Long id;
private String teamName;
private Order order;
}
class Order {
private Long id;
private String orderName;
}
객체지향 프로그램에서는 객체 그래프 탐색을 통해 참조를 할 수 있지만 SQL을 직접 다루게 되면 참조를 할 때마다 SQL문을 새로 생성해야한다.
member.getTeam().getOrder(); //객체지향 프로그램에서는 이렇게 객체의 탐색이 가능하다/
memberDAO.getMember(); //Member 테이블의 필드 값들만 조회가 가능하다. 여기서 더 파고 들어갈 수 없다.
memberDAO.getMemberWithTeam(); //멤버와 팀까지의 값들만 조회 가능. Order까지 파고 들 수 없다.
JPA는 객체 그래프 탐색을 해야하는 시점에 적절한 SELECT SQL을 실행하여 객체지향 프로그램처럼 자유로운 객체 그래프 탐색을 지원한다. 이는 실제 객체를 사용할 때 SQL을 실행하는 지연 로딩 기법을 사용한다.
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam(); //아직 사용되지 않았으므로 SELECT 문 실행 이전
team.getTeamName(); // Team의 데이터를 사용하는 시점이므로 SELECT 실행
4. 비교
: 데이터베이스는 각 행을 프라이머리 키로 비교한다. 반면 객체는 동일성, 동등성 두가지 방법으로 비교한다.
- 동일성 비교 : == 연산 (객체의 주소값 비교)
- 동등성 비교: .equals 연상 (객체 내부의 값 비교)
기존에 직접 SQL문을 사용할 경우에는 새로운 객체를 생성하여 매핑해주었으므로 같은 행의 값을 조회해도 다른 객체로 인식했지만 JPA는 같은 트랜잭션일 때는 같은 객체가 조회되는 것을 보장한다.
String memberId ="1";
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.class, memberId);
member1 == member2;
JPA를 사용해야 하는 이유
- 생산성 : 중복되는 코드를 JPA가 대신 처리하여 생산성이 증가
- 유지보수 : 테이블에 필드 추가 시 해당 테이블에 매핑되는 코드에 대하여 (등록, 수정, 조회) 수정해야 하는 번거로움이 있었지만 JPA는 이러한 과정을 대신 처리
- 패러다임 불일치 해결 : 상속, 연관관계, 비교, 객체 그래프 탐색과 같은 패러다임 불일치 문제를 해결
- 성능 : 다양한 성능 최적화 기능을 제공, 애플리케이션과 디비 그 사이에 존재함으로 여러 최적화 기능이 있음
- 데이터 접근 추상화 : RDB는 종류마다 같은 기능도 사용법이 다르지만 이러한 차이를 추상화된 데이터 접근 계층을 제공해 특정 DB에 종속되지 않게 해줌
- 표준 : 자바 진영의 표준 ORM
'BackEnd > JPA 스터디' 카테고리의 다른 글
[JPA 스터디 3주차] - 프록시와 연관관계 정리 (0) | 2021.07.14 |
---|---|
[JPA 스터디 3주차] - 다양한 연관관계 매핑 (0) | 2021.07.12 |
[JPA 스터디 2주차] - 엔티티 매핑 (0) | 2021.07.05 |
[JPA 스터디 1주차] - 영속성 관리 (0) | 2021.06.26 |
[JPA 스터디 1주차] - JPA 시작 (0) | 2021.06.24 |