본인은 JPA를 깊게는 모르지만, JPA를 사용하는 개발자들에게 인지 부하를 일으키는 JPA를 살펴보려고 한다.
JPA는 1차 캐시라는 이름으로 엔티티매니저가 엔티티들을 자체적으로 관리한다. 엔티티매니저에 변경할 엔티티를 기록하여 flush되는 시점에 효율적인(?) 쿼리를 생산하여 한 번에 처리한다.
분명 EntityManager에서 쿼리를 효과적으로 처리해주는 건 좋다. 하지만 이런 Lazy한 특성때문에 우리는 Service 계층의 코드를 작성하는데 쿼리를 예측할 수 없다. 그래서 개발자가 원하는 대로 비즈니스가 실행되지 않을 수 있다.
추가로 다른 프레임워크와 사용 시, JPA에서 한 작업을 flush를 해야 한다(아직 쿼리가 나가지 않았음) 이런 것도 프레임워크를 이해하지 못하면 알 수 없는 지점이다.
엔티티매니저가 엔티티 객체들의 스냅샷을 체크하고 있어서, flush 시점에 객체들의 상태를 비교하여 값들을 insert/update해준다.
이 부분에서 자연스럽게 엔티티는 가변객체가 된다.
레이지한지, Eager하는지는 왜 알아야 할까? 이런 코드들이 엔티티클래스를 더럽히고 있다.
또 레이지로딩을 구현하려다보니 Entity클래스는 프록시기반으로 설계되어있다. 그래서 Noargument Constructor와 final class를 만들 수 없는 단점이 생긴다.
(Lazy 하게 가져와야 한다는 건 잘못된 설계로 코드를 작성한 게 아닌가? 생각이 든다.)
연관관계 매핑도 너무 어렵다. 일반적으로 알려진(책, 인터넷강의) 지식은 N:1를 지향한다. 도저히 안되겠으면 1:N으로 진행하라고 한다.
객체흐름관점에서는 N:1매핑은 부자연스럽다. 많은 개발자들이 N:1관계로 매핑하여 코드를 생산하고 있다.
특히 1:N 매핑을 할 때는 양방향 매핑을 진행하라고 하는데, 양방향 매핑은... 휴먼에러가 발생할 수밖에 없는 코드를 생산하게 된다.
(toString() 순환참조 관련 롬복 이슈가 있다고 하는데, 롬복 이슈가 아니라 JPA 양방향 매핑이 잘못된 거 아닌가? 싶다)
JPA를 쓰면서 더 객체지향 코드를 생산할 수 있다
❌ 전혀 아니다. 우리는 Spring Data JPA로 RDB에 의존적인 코드를 작성하고 있다.
지금은 아키텍처로 변화하고 있지만, 아직 도메인과 JPA 엔티티가 결합되어 RDB에 의존적인 도메인코드가 생산되고 있다.
만약 RDB에서 NoSQL로 변경하면 도메인코드를 재활용 할 수 있는가? 전혀 아니다.
JPA는 처음 사용하는 개발자들에게 인지부하를 준다. 몇몇 개발자는 '너네 잘못 쓴 거다. JPA가 어려우니까 잘 알고 써야한다'라고 말한다.
하지만 내 의견은 다르다. 프레임워크가 자체적으로 잘못 만들어졌고, 어렵게 만들었다. 득도 있지만 실이 많은 것 같다.
그래서 Spring Data JDBC를 고려해봐도 좋을 것 같고, 도메인로직이 DB에 의존하지 않도록 코드를 작성해도 좋을 것 같다.