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와 데이터를 주고 받음
데이터 저장
- MemberDAO 클래스를 통해 persist()를 실행하면 JPA가 Entity 객체를 분석하여 SQL문을 생성
- JDBC API를 사용하여 DB에 생성된 INSERT SQL 전송
- 이 과정에서 JPA는 객체와 데이터베이스 테이블의 패러다임 불일치를 해결
데이터 조회
- MemberDAO 클래스를 통해 find(id)를 실행하면, JPA는 SELECT SQL을 생성
- JDBC API를 사용하여 생성된 SELECT SQL 전송
- DB에서 반환된 정보를 ResultSet 매핑을 통해 객체로 변환
- 이 과정에서도 패러다임 불일치 문제를 해결
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에 데이터를 저장하거나 조회할 때 서로 다른 방식을 사용해야하는 불편함이 발생
- 상속 문제
- 객체 지향 언어에서는 상속을 통해 클래스를 확장할 수 있으나, RDB는 상속 개념이 없고 테이블 단위로 데이터를 저장
- 이를 반영하려면 여러 테이블로 나누어 데이터를 관리하거나 상속 구조를 테이블에 맞춰 변경해야할 때가 있음
- 연관 관계 문제
- 객체 간의 연관 관계를 다루는 방식과 DB의 관계를 정의하는 방식이 다름
- 객체 지향 언어에서는 객체 간의 관계를 참조로 표시하지만, DB에서는 외래 키를 통해 테이블 간의 관계를 정의
- 데이터 타입 불일치
- 객체 지향 언어에서 사용하는 데이터 타입과 DB에서 사용하는 데이터 타입이 다름
- Java에서 List, Set과 같은 컬렉션을 사용할 수 있지만 DB에는 이러한 데이터 타입이 없어 적절히 변환이 필요
- 식별성 문제
- 객체 지향에서는 객체의 식별성을 참조에 의해 정의
- DB에서는 기본 키를 통해 식별성을 부여
JPA를 통한 패러다임 불일치 해결
- 상속 매핑
- JPA는 상속된 객체를 데이터베이스에 저장할 때 @Inheritance 어노테이션을 통해 싱글 테이블 전략, 조인 전략, 테이블 퍼 클래스 전략 등 여러 상속 매핑 방식 지원
- 연관 관계 매핑
- 객체 간의 연관 관계를 DB 테이블로 매핑할 수 있도록 @OneToOne, @OneToMany,
@ManyToOne, @ManyToMany와 같은 어노테이션을 제공
- 객체 간의 연관 관계를 DB 테이블로 매핑할 수 있도록 @OneToOne, @OneToMany,
- 데이터 타입 변환
- JPA는 객체 지향언어의 데이터 타입을 RDB의 데이터 타입으로 자동으로 변환해주기 때문에 개발자가 신경쓰지 않아도 됨
- 엔티티 식별
- JPA는 엔티티 객체마다 고유한 식별자를 부여하며, 데이터베이스 기본 키와 매핑하여 객체의 식별성을 보장
JPA를 사용해야하는 상황과 사용하지 말아야 할 상황
JPA를 사용해야 하는 상황
- 복잡한 엔티티 간의 관계가 많은 경우
- JPA는 객체 간의 연관 관계를 쉽게 매핑할 수 있도록 @OneToMany, @ManyToOne, @OneToOne, @ManyToMany 등의 어노테이션을 제공
- 테이블 간 조인을 쉽게 처리하며 객체지향적인 설계 유지 가능
- CRUD 작업이 많은 경우
- JPA는 엔티티를 통해 CRUD(Create, Read, Update, Delete) 작업을 쉽게 수행 가능
- 복잡한 SQL을 작성할 필요 없이 객체 조작을 통해 데이터베이스 작업이 가능
- 프로젝트가 객체 지향 모델과 밀접하게 연관된 경우
- JPA는 객체와 관계형 데이터베이스 간의 매핑에 특화되어 있기 때문에 프로젝트가 객체 지향 모델을 중심으로 설계된 경우 사용하기 적합
- 캐싱을 통해 성능 최적화가 필요한 경우
- JPA의 영속성 컨텍스트와 1차 캐시, 2차 캐시를 활용하면 데이터베이스 접근 횟수를 줄이고 성능을 최적화 가능
- 표준화된 API를 통해 확장성 있는 개발이 필요한 경우
- JPA는 Java EE와 Spring과 같은 여러 프레임워크에서 표준화된 방식으로 지원
- 덕분에 코드의 이식성과 재사용성이 높아지고, 프로젝트가 커져도 유연하게 확장 가능
JPA를 사용하지 않는 것이 좋은 상황
- 단순한 SQL 중심의 데이터 조작이 필요한 경우
- 대용량의 데이터를 간단한 SQL로 조회하거나 일괄 처리해야 하는 경우, SQL로 직접 처리하는 것이 더 효율적일 수 있음
- JPA는 객체-테이블 간 매핑과 영속성 컨텍스트 관리로 인해 SQL에 비해 약간의 오버헤드가 발생할 수 있음
- 대규모의 데이터 일괄 처리(Batch Processing)가 필요한 경우
- 데이터 마이그레이션이나 일괄 처리를 위해 대량의 데이터를 로드하고 조작해야 할 때, JPA는 메모리 사용량이 많고 영속성 컨텍스트를 관리해야 하므로 비효율적일 수 있음
- 이런 경우 JdbcTemplate이나 MyBatis처럼 SQL을 직접 실행하는 방법이 더 적합할 수 있음
- 고성능이 필요한 경우
- 고성능이 중요한 경우 JPA의 영속성 컨텍스트와 더티 체킹(Dirty Checking) 등으로 인해 발생하는 오버헤드가 문제가 될 수 있음
- 이 경우 SQL을 직접 사용하거나 MyBatis와 같은 SQL 매퍼를 통해 최적화된 쿼리를 사용하는 것을 권장
- 데이터베이스 중심의 설계가 필요한 경우
- 프로젝트가 객체 모델보다는 데이터베이스 모델 중심으로 설계되어 있거나, 복잡한 DB 스키마와 SQL 쿼리가 필요한 경우에는 JPA가 오히려 방해가 될 수 있음
- 예를 들어, 특수한 DB 기능을 자주 사용하거나 DB 벤더에 종속적인 기능을 사용할 때 JPA는 이를 충분히 지원하지 못할 수 있음
- NoSQL과 같은 비관계형 데이터베이스를 사용하는 경우
- JPA는 관계형 데이터베이스를 위한 ORM이기 때문에, NoSQL과 같은 비관계형 데이터베이스에서는 적합하지 않음
- MongoDB, Cassandra와 같은 비관계형 DB를 사용할 때는 해당 DB에 특화된 라이브러리나 API를 사용하는 것을 권장
참고 자료
'Language > Spring' 카테고리의 다른 글
[Entity] 엔티티와 영속성 컨텍스트 (1) | 2024.11.09 |
---|---|
[JPA/Hibernate] Hibernate 기초 (1) | 2024.11.09 |
[Redis] 캐시란? (0) | 2024.09.07 |
[JWT] Refresh Token을 이용한 Access Token 재발급 (0) | 2024.08.28 |
[JWT] JwtUtil 사용 예제 및 설명 (0) | 2024.08.27 |