JPA(ORM) 기술은 왜 사용하는가?
1. SQL 중심적인 개발을 벗어나게 해 준다.
기존 SQL 중심의 프로젝트는 객체 중심의 코딩이 불가능했다.
예제 코드
public static void main(String[] args) throws Exception {
Class.forName("jdbc");
Connection con = DriverManager.getConnection ("DBURL","username", "password");
Statement stmt = con.createStatement();
String query ="query" // name,age,address
ResultSet rs = stmt.executeQuery(query);
List<Person> persons = new ArrayList<>();
while (rs.next()) {
String name = rs.getString("name");
int age = rs.getInt("age");
String address = rs.getInt("address");
persons.add(new Person(name,age,address));
}
}
해당 예제 코드는 말 그대로 DB에 접근하여 자료를 읽어 가져오는 역할만 한다.
만약 해당 프로젝트에서 name, age , address -> Person이라는 객체로 사용하기 위해서는 일일이 생성해줘야 한다.
여기까지는 객체지향스럽게 코딩이 가능하다고 생각할 수 있다.
하지만 예제 코드는 말 그대로 예제 코드일 뿐 현실은 그렇지 않다.
결국 프로젝트 규모가 커질수록 객체 중심 코딩은 불가능하며 데이터 중심의 코드만 짜게 된다.
2. 객체와 관계형 데이터베이스의 패러다임 불일치를 해소해준다,
- 상속
- 연관관계 - 객체는 참조를 사용 , 테이블은 외래 키를 사용한다
- 데이터 타입
- 데이터 식별 방법
3. 객체 그래프 탐색 Member -> Order -> OrderItem -> Item
- 처음 실행하는 SQL에 따라 탐색 가능 범위가 결정돼버림
Member -> Order -> Item 인 경우에서 Member -> Order 까지만 로딩이 되었다 가정하고 나는 사용했지만 다른 사람이 보았을 때 Item을 접근할 수 있기 때문에 만약 접근한다면 NPE 가 발생한다. - 하지만 JPA 같은 경우 지연 로딩, 즉시 로딩을 설정할 수 있기 때문에 앞서 살펴본 오류를 방지할 수 있다.
- (단 N+1 문제든 예상치 못한 쿼리가 발생할 수 있다. 따라서 잘 알고 쓰자!)
JPA와 hibernate의 관계
JPA를 사용하다 보면 hibernate 이야기는 항상 나오게 된다.
그리고 깊게 공부하지 않는다면 hibernate와 JPA는 똑같다고 생각할 수 있다.
위의 말은 100% 틀린 말은 아니지만 또한 100% 맞는 말도 아니다.
JPA는 단지 자바 진영의 표준 ORM 기술이다.
- 즉 ORM의 기술을 사용하기 위한 표준 인터페이스를 제공한다는 뜻이다.
- 인터페이스를 제공해준다는 뜻은 JPA를 사용한다면 하위 구현체로 hibernate 가 아닌 다른 하위 구현체로 변경할 수 있다는 뜻이다.
- hibernate 이외에도 JPA 지원하는 벤더들도 많이 존재한다.
결과적으로 하위 구현체로 hibernate 가 많이 사용될 뿐이지 JPA == hibernate 인건 아니다.
추 후 hibernate 보다 뛰어난 ORM 프로젝트가 나온다면 미래에는 얼마든지 교체될 수 있다.
하지만 우리가 진행하고 있는 프로젝트의 코드를 변경하지 않아도 새로운 구현체가 (ORM 프로젝트) JPA 인터페이스를 완벽하게 지원한다면 인터페이스의 하위 구현체만 변경하여 더 좋은 성능의 ORM 프로젝트를 사용할 수 있다.
그렇다면 JPA는 단점이 없는가?
(제 생각이 어느 정도 들어간 문단입니다.)
편안함에서 오는 복잡함(무슨 소리야?🤔 )
- 제가 말하고자 하는 것은 예상하지 못한 Query 구문, 발생 횟수뿐이 아닌
- 편리함을 추 구하기 위해 과도하게 연관관계를 맺는 행위를 말하고자 합니다.
객체 그래프 탐색은 매우 매력적이고 개발을 함에 있어 매우 편리하여 양방향 연관관계를 맺어 사용하는 경우가 있습니다.
사실 도메인 로직상 과도한 연관관계가 필요한 경우는 제가 아직까지 만나보지 못한 걸 수도 있지만 대부분 단방향이거나 연관관계를 굳이 맺고 있지 않아도 처리가 가능합니다.
즉 CRUD에서 CUD 로직은 과도한 연관관계가 대부분 필요 없다고 생각합니다.
위의 예제는 제가 프로젝트를 하면서 연관관계에 대해서 다시 생각해본 내용입니다.
(해당 이유가 정답이 아닐 수도 있지만)
Entity 간의 연관관계가 꼭 필요한지 한 번쯤은 생각해보는 것도 좋을 듯합니다.
또한 프로젝트의 연관관계가 너무 복잡하다면
- CRUD의 Read(select)를 편하게 하기 위해서 맺는 경우가 있는지 한번 확인해보시면 좋을 것 같습니다.
높은 학습비용
- 아직까지도 JPA를 사용하다 보면 N+1 문제
- 영속성 콘텍스트 범위 관리를 하지 못하여 update 가 되지 않거나
- 예상하지 못한 쿼리가 발생한다거나
JPA를 주의하면서 쓴다고 해도 100% 해당 문제를 다시 안 만난다는 보장은 없습니다.
성능
- 앞서 말한 것처럼 간단한 Select Query는 JPA로 사용해도 괜찮지만
- 복잡한 통계성 쿼리는 JPA의 JPQL을 이용하기보다는 Native query를 사용하거나 Mybatis를 이용하는 것이 좋다.
'why?' 카테고리의 다른 글
나는 왜 JAVA 를 사용하게되었는가? (0) | 2021.08.11 |
---|---|
왜? EntityManager는 AutoCloseable 구현하고 있지 않은가? (0) | 2021.06.15 |