본문 바로가기

Language/Spring

[JPA] JPA의 개념 / JPA를 사용해야하는 상황과 그렇지 못한 상황

JPA(Java Persistence Api)란?
  • 자바에서 사용하는 ORM(Object-Relational Mapping) 기술 표준
  • 자바 애플리케이션과 JDBC 사이에서 동작하며 자바 인터페이스로 정의

ORM(객체 관계 맵핑, Object-Relational Mapping)이란?
  • 객체와 관계형 데이터베이스의 데이터를 매핑하는 기술
  • ORM 프레임워크가 객체와 데이터베이스 중간에서 매핑
  • 객체와 테이블을 매핑하여 패러다임 불일치 문제를 해결
ORM의 종류
  • Hibernate
    • Java 기반의 ORM 프레임워크로 JPA를 구현하여 많이 사용
    • 객체와 테이블을 매핑하고 SQL을 작성하지 않고도 CRUD 작업 가능
  • Mybatis
    • SQL 맵퍼로 ORM과 유사한 기능을 제공하면서도 SQL을 XML로 작성하여 직접 관리
    • 엄밀히 따지면 Mybatis는 ORM보다는 SQL 매퍼에 더 가깝지만, 객체와 DB의 데이터를 매핑하는 기능을 가지고 있어 ORM과 유사하게 사용
  • Entity Framework(C#), SQLAlchemy(Python), Django ORM(Django), Sequelize(Node.js)

JPA의 동작
  • 애플리케이션과 JDBC 사이에서 동작
  • JDBC API를 사용하여 Database와 데이터를 주고 받음


데이터 저장
  1. MemberDAO 클래스를 통해 persist()를 실행하면 JPA가 Entity 객체를 분석하여 SQL문을 생성
  2. JDBC API를 사용하여 DB에 생성된 INSERT SQL 전송
  3. 이 과정에서 JPA는 객체와 데이터베이스 테이블의 패러다임 불일치를 해결


데이터 조회
  1. MemberDAO 클래스를 통해 find(id)를 실행하면, JPA는 SELECT SQL을 생성
  2. JDBC API를 사용하여 생성된 SELECT SQL 전송
  3. DB에서 반환된 정보ResultSet 매핑을 통해 객체로 변환
  4. 이 과정에서도 패러다임 불일치 문제를 해결


JPA를 사용하는 이유
  • 기존의 개발 방식은 SQL 중심적인 개발이었으나, JPA를 사용하면 객체 중심으로 애플리케이션 개발이 가능
  • 생산성(CRUD) 향상
    • JDBC 방식의 경우 SQL 쿼리문을 직접 작성해야 데이터베이스에 접근할 수 있었으나, JPA는 쿼리문을 별도로 작성할 필요가 없음
    • 다음과 같이 간단한 메서드를 통해 CRUD 가능
      • 저장 : jpa.persist(member)
      • 조회 : Member member = jpa.find(memberId)
      • 수정 : member.setName(”변경할 이름”)
      • 삭제 : jpa.remove(member)
  • 유지보수 용이
    • 기존에는 엔티티 클래스의 필드가 변경되면 모든 SQL 수정이 필요
    • JPA에서는 쿼리를 직접 작성하지 않기 때문에 필드가 변경되더라도 매핑 정보만 잘 연결하면 SQL문은 자동으로 작성되어 유지 보수가 용이 함
  • 패러다임의 불일치 문제 해결
    • 상속, 연관관계, 객체 그래프 탐색, 비교 등의 설계 차이로 인해 발생하는 패러다임 불일치 문제를 해결

패러다임 불일치(Paradigm mismach)란?
  • 객체 지향 프로그래밍에서 객체 모델과 관계형 데이터베이스(RDB)의 테이블 모델 간의 차이로 인해 발생하는 문제를 의미
  • 이 차이로 인해 개발자가 객체 지향 언어로 작업할 때 RDB에 데이터를 저장하거나 조회할 때 서로 다른 방식을 사용해야하는 불편함이 발생
  1. 상속 문제
    • 객체 지향 언어에서는 상속을 통해 클래스를 확장할 수 있으나, RDB는 상속 개념이 없고 테이블 단위로 데이터를 저장
    • 이를 반영하려면 여러 테이블로 나누어 데이터를 관리하거나 상속 구조를 테이블에 맞춰 변경해야할 때가 있음
  2. 연관 관계 문제
    • 객체 간의 연관 관계를 다루는 방식과 DB의 관계를 정의하는 방식이 다름
    • 객체 지향 언어에서는 객체 간의 관계를 참조로 표시하지만, DB에서는 외래 키를 통해 테이블 간의 관계를 정의
  3. 데이터 타입 불일치
    • 객체 지향 언어에서 사용하는 데이터 타입과 DB에서 사용하는 데이터 타입이 다름
    • Java에서 List, Set과 같은 컬렉션을 사용할 수 있지만 DB에는 이러한 데이터 타입이 없어 적절히 변환이 필요
  4. 식별성 문제
    • 객체 지향에서는 객체의 식별성을 참조에 의해 정의
    • DB에서는 기본 키를 통해 식별성을 부여
JPA를 통한 패러다임 불일치 해결
  1. 상속 매핑
    • JPA는 상속된 객체를 데이터베이스에 저장할 때 @Inheritance 어노테이션을 통해 싱글 테이블 전략, 조인 전략, 테이블 퍼 클래스 전략 등 여러 상속 매핑 방식 지원
  2. 연관 관계 매핑
    • 객체 간의 연관 관계를 DB 테이블로 매핑할 수 있도록 @OneToOne, @OneToMany, 
      @ManyToOne, @ManyToMany
      와 같은 어노테이션을 제공
  3. 데이터 타입 변환
    • JPA는 객체 지향언어의 데이터 타입을 RDB의 데이터 타입으로 자동으로 변환해주기 때문에 개발자가 신경쓰지 않아도 됨
  4. 엔티티 식별
    • JPA는 엔티티 객체마다 고유한 식별자를 부여하며, 데이터베이스 기본 키와 매핑하여 객체의 식별성을 보장

JPA를 사용해야하는 상황과 사용하지 말아야 할 상황
JPA를 사용해야 하는 상황
  1. 복잡한 엔티티 간의 관계가 많은 경우
    • JPA는 객체 간의 연관 관계를 쉽게 매핑할 수 있도록 @OneToMany, @ManyToOne, @OneToOne, @ManyToMany 등의 어노테이션을 제공
    • 테이블 간 조인을 쉽게 처리하며 객체지향적인 설계 유지 가능
  2. CRUD 작업이 많은 경우
    • JPA는 엔티티를 통해 CRUD(Create, Read, Update, Delete) 작업을 쉽게 수행 가능
    • 복잡한 SQL을 작성할 필요 없이 객체 조작을 통해 데이터베이스 작업이 가능
  3. 프로젝트가 객체 지향 모델과 밀접하게 연관된 경우
    • JPA는 객체와 관계형 데이터베이스 간의 매핑에 특화되어 있기 때문에 프로젝트가 객체 지향 모델을 중심으로 설계된 경우 사용하기 적합
  4. 캐싱을 통해 성능 최적화가 필요한 경우
    • JPA의 영속성 컨텍스트와 1차 캐시, 2차 캐시를 활용하면 데이터베이스 접근 횟수를 줄이고 성능을 최적화 가능
  5. 표준화된 API를 통해 확장성 있는 개발이 필요한 경우
    • JPA는 Java EE와 Spring과 같은 여러 프레임워크에서 표준화된 방식으로 지원
    • 덕분에 코드의 이식성과 재사용성이 높아지고, 프로젝트가 커져도 유연하게 확장 가능
JPA를 사용하지 않는 것이 좋은 상황
  1. 단순한 SQL 중심의 데이터 조작이 필요한 경우
    • 대용량의 데이터를 간단한 SQL로 조회하거나 일괄 처리해야 하는 경우, SQL로 직접 처리하는 것이 더 효율적일 수 있음
    • JPA는 객체-테이블 간 매핑과 영속성 컨텍스트 관리로 인해 SQL에 비해 약간의 오버헤드가 발생할 수 있음
  2. 대규모의 데이터 일괄 처리(Batch Processing)가 필요한 경우
    • 데이터 마이그레이션이나 일괄 처리를 위해 대량의 데이터를 로드하고 조작해야 할 때, JPA는 메모리 사용량이 많고 영속성 컨텍스트를 관리해야 하므로 비효율적일 수 있음
    • 이런 경우 JdbcTemplate이나 MyBatis처럼 SQL을 직접 실행하는 방법이 더 적합할 수 있음
  3. 고성능이 필요한 경우
    • 고성능이 중요한 경우 JPA의 영속성 컨텍스트와 더티 체킹(Dirty Checking) 등으로 인해 발생하는 오버헤드가 문제가 될 수 있음
    • 이 경우 SQL을 직접 사용하거나 MyBatis와 같은 SQL 매퍼를 통해 최적화된 쿼리를 사용하는 것을 권장
  4. 데이터베이스 중심의 설계가 필요한 경우
    • 프로젝트가 객체 모델보다는 데이터베이스 모델 중심으로 설계되어 있거나, 복잡한 DB 스키마와 SQL 쿼리가 필요한 경우에는 JPA가 오히려 방해가 될 수 있음
    • 예를 들어, 특수한 DB 기능을 자주 사용하거나 DB 벤더에 종속적인 기능을 사용할 때 JPA는 이를 충분히 지원하지 못할 수 있음
  5. NoSQL과 같은 비관계형 데이터베이스를 사용하는 경우
    • JPA는 관계형 데이터베이스를 위한 ORM이기 때문에, NoSQL과 같은 비관계형 데이터베이스에서는 적합하지 않음
    • MongoDB, Cassandra와 같은 비관계형 DB를 사용할 때해당 DB에 특화된 라이브러리나 API를 사용하는 것을 권장

참고 자료

https://ittrue.tistory.com/253