1. JPA 소개

2025. 6. 11. 11:13Spring/JPA

1. SQL 중심적인 개발의 문제점

1) 반복되는 SQL 코드

  • 기존 개발 방식에서는 INSERT, SELECT, UPDATE, DELETE 등 CRUD 쿼리를 직접 작성해야 함.
  • 자바 객체를 DB에 저장하려면 필드를 SQL에 맞게 매핑하고, 결과를 객체로 다시 매핑하는 코드가 반복됨.
  • 코드가 지루하고 유지보수가 어려움, 개발 생산성 저하 

2) SQL 의존성

  • 도메인 클래스에 필드를 하나 추가하면 모든 SQL 수정이 필요함
  • SQL에 지나치게 의존적이라 객체지향적인 모델링이 어려움
  • 결과적으로 객체의 구조를 SQL에 맞추는 형태의 개발이 되어버림.

3) 객체와 관계형 DB의 패러다임 불일치

  • 객체: 상속, 다형성, 캡슐화 등으로 복잡한 구조를 표현
  • 관계형 DB: 정형화된 테이블 구조를 사용하며, JOIN, 외래 키 등 관계 중심 설계가 핵심
  • 이 두 체계가 서로 달라서 "객체 ↔ 테이블"을 매핑하는 작업에서 많은 충돌이 발생한다. 

4) 상속 처리의 어려움

  • 객체지향 언어에서는 상속을 활용해 코드 재사용과 다형성을 누림.
  • 하지만 관계형 DB에서는 상속이라는 개념이 없기 때문에, 상속 관계를 슈퍼타입/서브타입 테이블 구조로 나눠야 함.
  • 이때 객체 1개를 저장/조회하려면 2개 이상의 테이블을 나눠 INSERT/SELECT해야 하고, JOIN도 복잡함.
    → 그래서 현실에서는 DB에 저장되는 객체에는 상속을 잘 사용하지 않게 됨.

5) 연관관계 표현의 제약

  • 자바 객체: 서로를 참조로 연결하고, 메서드 체이닝처럼 member.getTeam().getName()으로 탐색
  • 관계형 DB 테이블: 외래키와 JOIN을 통해 연관된 데이터 접근
  • 객체다운 모델링을 하려면 오히려 더 많은 매핑 코드가 필요
    • 객체와 테이블의 연관관계 표현 차이를 맞추기 위해 객체에 외래 키(teamId) 필드를 직접 넣는 경우가 많지만, 이건 객체답지 않은 방식이다. 
    • 객체답게 모델링하려면 Member 안에 Team team; 형태로 참조를 걸어야 하지만, 이럴 경우 SQL과 매핑 로직이 더 복잡해지고, 추가 작업이 늘어남.

6) 탐색 및 계층 문제

  • 객체는 내부에 연결된 객체들을 자유롭게 탐색할 수 있어야 함 (객체 그래프 탐색)
  • 그러나 SQL 기반 개발에서는 이 객체 그래프 탐색이 자동으로 되지 않음
    직접 JOIN SQL을 작성하거나, 필요한 조합마다 DAO 메서드를 만들어야 함
//참조를 따라가면서 탐색하며 객체 사용 → 객체 그래프 탐색
member.getTeam().getName();
member.getOrder().getDelivery().getAddress();

//SQL로 연관 데이터 가져오는 경우 JOIN을 명시적으로 해줘야함 
//요구하는 데이터마다 다른 SQL과 DAO 메서드를 만들어야 함 
memberDAO.getMember(); // Member만 조회
memberDAO.getMemberWithTeam(); // Member + Team 조회
memberDAO.getMemberWithOrderWithDelivery(); // Member + Order + Delivery 조회
  • 이로 인해 계층(Service/Repository) 사이의 역할 분리가 흐려지고 (Service에서도 Repository 계속 확인)
    "이 객체에 Team이 로딩돼 있을까?" 라는 불확실성으로 인해 엔티티 신뢰성이 떨어짐

7) 동일성 비교 문제

  • 자바 컬렉션에서 객체를 조회하면 항상 같은 객체가 반환되기 때문에 == 비교가 가능함.
  • 하지만 SQL 기반 개발에서는 DB를 조회할 때마다 새로운 객체가 생성되기 때문에,
    같은 ID 값을 가지고 있어도 member1 == member2는 항상 false가 됨.
  • 따라서 자바 컬렉션처럼 일관된 방식으로 객체를 다루기 어렵고, 로직에도 혼란이 생김.

2. JPA 소개 및 장점

1) JPA란?

  • Java Persistence API의 약자
  • 자바 진영의 ORM(Object-Relational Mapping) 기술 표준
    • 이전에 자바 표준으로 EJB 엔티티 빈이 존재했으나 너무 복잡하고 어려웠음 
    • 개빈 킹이 개발한 Hibernate라는 실용적인 오픈소스가 등장했고
    • 자바가 Hibernate를 JPA라는 새로운 자바 표준으로 만들어서 제공함 
  •  애플리케이션과 JDBC 사이에서 동작
  • JDBC를 직접 사용하는 방식보다 더 객체 중심적이고 선언적인 개발이 가능함

2) ORM이란?

  • Object-Relational Mapping(객체-관계 매핑)의 약자
  • 객체와 관계형 DB 각각의 설계 철학을 유지하면서
    양쪽을 연결해주는 매핑을 프레임워크가 자동으로 처리해주는 기술
  • 다른 언어에도 ORM 기술이 존재 

3) JPA 주요 구현체

  • Hibernate  (가장 많이 쓰임)
  • EclipseLink
  • DataNucleus

4) JPA 버전 정리

  • JPA 1.0 (2006): 초기 버전, 복합 키나 연관관계 기능 부족
  • JPA 2.0 (2009): 대부분의 ORM 기능 포함, JPA Criteria 추가 
  • JPA 2.1 (2013): 컨버터, 스토어드 프로시저 지원 등 실무 기능 강화

 

3. JPA의 주요 장점

1) SQL이 아닌 객체 중심 개발

  • SQL 없이도 자바 코드에서 객체를 자연스럽게 다루듯이 DB에 저장/조회/수정/삭제 가능  
    • 저장: jpa.persist(member)
    • 조회: jpa.find(Member.class, id)
    • 수정: 필드만 변경하면 됨
    • 삭제: jpa.remove(member)

2) 생산성 향상

  • SQL을 반복해서 작성할 필요 없음
  • 필드 하나 추가해도 JPA가 SQL을 알아서 처리
  • CRUD 로직이 간단하고 직관적

3) 유지보수 용이

  • 도메인 클래스가 변경되더라도 SQL 쿼리를 직접 수정할 필요가 거의 없음
  • 코드 변화량이 줄어들어 유지보수가 쉬워짐

4) 패러다임 불일치 해소

  • 객체처럼 모델링하면, DB 매핑은 JPA가 알아서 처리해줌
  • 상속, 연관관계, 객체 그래프 탐색, 동일성 등 객체지향의 개념을 JPA가 자동으로 매핑해줌
    • 상속: 테이블 분리 및 조인을 자동 처리
    • 연관관계: 객체 참조 기반으로 저장 및 탐색 가능
    • 객체 그래프 탐색: 자유로운 탐색 가능 (member.getTeam())
    • 객체 비교시 동일성 보장: 같은 트랜잭션 내 동일 엔티티는 동일 객체로 반환

5) 성능 최적화 기능

  • 1차 캐시: 같은 트랜잭션에서 SQL 한 번만 실행, 객체 동일성 보장 
  • 쓰기 지연: INSERT/UPDATE/DELETE SQL을 트랜잭션 커밋 시 한꺼번에 실행
  • 지연 로딩(Lazy Loading): 객체가 실제 사용될 때 로딩 
  • 즉시 로딩(Eager Loading): JOIN으로 연관 객체까지 한 번에 미리 조회