

JPA에 대해서 친구가 이런 질문을 던졌다.
- 어차피 복잡한 쿼리는 Native Query를 쓰게 된다
- Join도 연관관계가 없으면 결국 Native Query다
- 그렇다면 JDBC나 MyBatis가 더 낫지 않나?
- 영속화는 리소스 낭비가 아닌가 ?
이 질문들은 결국 다음 지점으로 수렴한다.
- 영속성 컨텍스트를 굳이 써야 할 이유가 있을까?
이 질문은 굉장히 합리적으로 보인다. 동시에, JPA를 바라보는 관점이 살짝 어긋나 있다는 신호이기도 하다.
논의의 출발점: 패러다임의 불일치
이 논쟁은 결국 패러다임의 불일치에서 시작된다.
데이터베이스의 목표
- 데이터를 안전하게 저장한다
- 정합성과 무결성을 유지한다
- 집합 기반 연산에 최적화되어 있다
객체지향 언어의 목표
- 데이터를 추상화한다
- 상태와 행위를 캡슐화한다
- 변경에 강한 구조를 만든다
이 둘은 애초에 지향점이 다르다.
그래서 같은 기준으로 비교하면 반드시 이런 말이 나온다.
- 객체지향은 느리다
- ORM은 불필요한 추상화다
하지만 이는 잘못된 비교다.
DB와 객체는 경쟁 관계가 아니라 역할이 다른 존재다.
이런 다른 패러다임을 혼재하고 JPA를 보게되면 JPA를 쿼리 프레임워크로 착각할수 있다.
- JPA의 목적은 ORM이 아니다.
- JPA의 목적은 쿼리 최적화가 아니다.
- JPA는 쿼리 프레임워크가 아니다.
JPA는 Persistence Management다.
영속성 컨텍스트는 리소스 낭비다 ? (유지보수가 더 비싸다.)
솔직히 말하면, 맞는 말이다. 영속성 컨텍스트는 분명히 비용이 든다.
- 1차 캐시를 통해 메모리를 점유하고
- 엔티티 스냅샷을 유지하고
- Dirty Checking을 수행한다
즉, 영속화는 가볍지 않다.
그럼에도 이 비용을 감수하는 이유는 간단하다. 실제 비즈니스 환경에서는 서버 한 대 증설비용보다 버그를 수정하고 기능을 변경하는 개발자의 인건비 비용이 더 크다.
- 요구사항은 끊임없이 변경되고
- 도메인 로직은 점점 복잡해지며
- 데이터 무결성의 중요도는 계속 커진다
이 지점에서 객체지향적으로 모델링된 도메인은 단순한 성능 최적화보다 훨씬 큰 가치를 가진다.
실제로 더 비싼 비용은 다음이다.
- 버그 수정 비용
- 기능 변경 비용
- 도메인 로직 붕괴로 인한 유지보수 비용
JPA의 역할을 다시 정의하면
다시 정리하면,
JPA는 쿼리를 대신 써주는 도구가 아니라. 객체의 상태를 관리해주는 도구다.
JPA는:
- 객체 동일성을 보장하고
- 변경을 추적하며
- 트랜잭션 단위로 상태를 일관되게 관리한다
즉, 복잡한 도메인을 안전하게 변경하기 위한 도구다.
영속화는 리소스 낭비가 아니라 유지보수 비용을 줄이기 위한 투자다.
이 관점 없이 JPA를 쓰면 반드시 겪게 되는 것들
이 관점 없이 JPA를 사용하면 다음 현상이 반드시 나타난다.
- 성능이 예측 불가능해지고
- Flush 타이밍이 이해되지 않으며
- N+1 문제를 프레임워크 버그처럼 느끼게 된다
하지만 N+1과 JPA를 사용하면서 어려움을 겪는 대부분은:
패러다임 일관성을 유지한 결과로 나타나는 부수 효과다.
JPA를 도입하면서 자연스러운 트레이드오프임을 이해하면 전략적으로 대응할 수 있게 된다.
사용하는 기술의 의도를 파악해야 한다...
자전거 vs 대중교통을 비교하더라도 많은 장단점이 보인다. 하지만 도구(기술)들이 사용자들이 기대하는 목적에 따라 가져다 주는 가치는 각각 다르고 상황에 따라 도움이 될수도,안될수도 있다.
기술을 비교할 때 가장 흔하게 빠지는 함정은 "도구 자체의 우열을 따지는 것이다."
자전거를 가볍고 빠르며, 목적지까지 바로 이동할 수 있다.
반면에, 대중교통은 노선에 묶이고, 환승이 필요하며, 때로는 비효율적으로 느껴진다.
여기에서도 잘못된 전제가 잡혀있다. (찾아보길바란다.)
기술의 단점을 지적하는 것은쉽다. 하지만 그 단점은 대부분 그 기술이 해결하려고하는 문제의 반대편에서만 단점으로 보이게된다.
결국 중요한것은 "기술이 해결하려고 하는 문제가 무엇인가?"에 집중해야한다. 의도를 이해하지 못한 채 기술을 사용하면 안쓰니만 못한다.
'1. 개발' 카테고리의 다른 글
| ‘잘하고 있는데 왜 힘들까?’에서 시작된 개발 프로세스 개선 1년 (0) | 2026.01.27 |
|---|---|
| [Spring] 모노레포 환경에서 MessageSource를 모듈별로 독립시키는 방법(feat. BeanPostProcessor) (0) | 2026.01.14 |
| [OpenSource] 아파치 Gravitino 릴리즈(v0.9.1, v1.0.0) 기여 (0) | 2025.10.01 |
| [Spring Security]: 시큐리티 필터 예외 바꿔치기 문제 (0) | 2025.09.07 |
| Tell, Don't Ask (6) | 2025.07.23 |