JPA (Java Persistence API)
: Persistence_지속됨(없어지지 않고 오래 동안)
JPA : 인터페이스들의 묶음 = Java 애플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스.
인터페이스는 '규칙'과 같음. JPA는 데이터베이스를 다루는 방법에 대한 표준적인 규칙을 정의해 놓은 것.
이 규칙을 따르면 어떤 데이터베이스를 사용하든 Java 코드 변경 없이 데이터베이스를 쉽게 전환할 수 있음.
데이터, 그중에서도 특히 엔티티(Entity)의 영속성을 관리하기 위해 쓴다고 보면 됨.
JPA에서 객체에 영속성을 부여하는 주요 이유
JPA에서 객체에 영속성(Persistence) 을 부여하는 이유는 객체와 데이터베이스 간의 데이터 일관성을 유지하고, 효율적인 데이터 관리를 가능하게 하기 위함입니다.
1. 객체와 관계형 데이터베이스 간의 일관성 유지
- JPA는 영속성 컨텍스트(Persistence Context) 를 통해 객체를 관리하며, 변경 사항을 자동으로 감지하고 데이터베이스와 동기화합니다.
- 트랜잭션을 커밋하면, JPA는 변경된 객체들을 자동으로 반영합니다.
2. 변경 감지(Dirty Checking)
- entityManager.find(User.class, 1L) 로 조회한 객체를 변경하면, 별도의 update SQL을 직접 실행하지 않아도 트랜잭션이 커밋될 때 자동으로 변경 사항이 반영됩니다.
- 객체를 수정 후 entityManager.persist()를 다시 호출할 필요 없음.
데이터베이스 세계에서는 깨끗한(Clean) 상태와 더러운(Dirty) 상태를 구분하는 개념이 존재합니다.
1️⃣ Clean 상태 → 데이터가 영속성 컨텍스트와 DB에 저장된 내용과 동일함
2️⃣ Dirty 상태 → 데이터가 변경되었지만 아직 DB에 반영되지 않음 (수정 필요!)
🔹 JPA에서는 엔티티 객체가 처음 저장될 때는 Clean 상태입니다.
🔹 하지만, 객체의 값을 변경하면 JPA가 이를 감지하여 Dirty 상태라고 판단하고, 트랜잭션이 끝나기 전에 변경 내용을 DB에 자동으로 반영합니다.
3. 1차 캐시(First-Level Cache) 활용
- 영속성 컨텍스트는 1차 캐시 역할을 하여, 동일한 트랜잭션 내에서 같은 객체를 여러 번 조회해도 데이터베이스에 여러 번 접근하지 않고 캐시에서 반환합니다.
User user = entityManager.find(User.class, 6L);
User user2 = entityManager.find(User.class, 6L);
동일한 id로 조회할 때, 두 객체가 동일한 인스턴스를 참조하는 것을 확인할 수 있음. (user == user2)
4. 트랜잭션 관리 용이
- transaction.begin()으로 트랜잭션을 시작하고, 여러 개의 엔티티를 한 번에 변경한 후 transaction.commit() 하면 모든 변경 사항이 한 번에 반영됨 (원자성 보장).
- 중간에 예외가 발생하면 rollback()을 통해 데이터 정합성을 유지할 수 있음.
5. 객체 중심 개발 가능 (SQL 직접 작성 최소화)
- entityManager.persist(user); 를 호출하면 INSERT SQL이 자동 생성됨.
- 개발자는 SQL을 직접 작성할 필요 없이 객체 조작을 통해 데이터베이스를 다룰 수 있음.
6. 성능 최적화 (지연 로딩, 배치 쿼리 등)
- JPA는 지연 로딩(Lazy Loading) 을 통해 필요한 시점에만 데이터를 가져올 수 있어 불필요한 쿼리 실행을 방지함.
- JPQL을 사용하면 복잡한 SQL 쿼리를 객체지향적으로 작성 가능.
결론
JPA에서 객체에 영속성을 부여하면 SQL 대신 객체 중심으로 데이터 관리를 할 수 있고, 성능 최적화 및 유지보수성을 높일 수 있음.
특히 변경 감지(Dirty Checking), 1차 캐시, 트랜잭션 관리 덕분에 데이터 정합성을 유지하면서도 성능을 최적화할 수 있습니다.
왜 쓰는 걸까?
1. 객체(Entity)와 데이터베이스(DB)의 '다리' 역할
Java는 객체 지향 프로그래밍 언어이고, 데이터베이스는 관계형 데이터베이스입니다. 둘은 데이터를 다루는 방식이 달라서 직접적인 호환이 어렵습니다. JPA는 이 둘 사이에서 '다리' 역할을 하여 객체 지향적인 방식으로 데이터베이스를 다룰 수 있도록 도와줍니다.
→ DB를 개발 프로그램에서 객체 지향적인 방식으로 DB를 다룰 수 있게 해준다.
2. 생산성 UP!
JPA를 사용하면 반복적인 데이터베이스 코드를 작성할 필요가 없어집니다. JPA는 '마법'처럼 객체를 데이터베이스에 자동으로 저장하고, 조회하고, 수정하고, 삭제하는 기능을 제공합니다. 개발자는 비즈니스 로직에만 집중할 수 있어 생산성이 향상됩니다.
3. 유지보수도 편리하게!
JPA는 데이터베이스 스키마 변경 시 코드 수정 범위를 최소화해줍니다. 객체와 테이블 간의 매핑 정보만 수정하면 되므로 유지보수가 용이해집니다.
JPA, 어떻게 사용하면 될까?
JPA는 인터페이스이므로, JPA를 실제로 사용하려면 JPA를 구현한 ORM (Object-Relational Mapping) 프레임워크가 필요합니다. 대표적인 ORM 프레임워크로는 Hibernate가 있습니다.
JPA와 Hibernate를 함께 사용하면, Java 코드를 통해 데이터베이스를 편리하게 관리할 수 있습니다.
ORM이란?
ORM(Object-Relational Mapping)은 객체 지향 프로그래밍 언어(예: Java, Python 등)에서 사용하는 객체와 관계형 데이터베이스(RDB)의 테이블 간의 데이터를 매핑하는 기술을 말합니다.
필요한 이유 : 객체 지향 프로그래밍과 관계형 데이터베이스는 데이터를 다루는 방식에 차이가 있습니다. 객체 지향 프로그래밍 언어로 작성된 애플리케이션에서 관계형 데이터베이스에 데이터를 저장하고 검색하는 과정이 복잡하고 비효율적일 수 있어서 등장하게 되었습니다.
ORM의 역할:
ORM은 객체와 테이블 간의 매핑을 설정하고, 객체를 통해 데이터베이스에 접근하고 조작할 수 있도록 합니다. 개발자는 SQL 쿼리를 직접 작성하지 않고도 객체 지향적인 방식으로 데이터를 처리할 수 있습니다. ORM은 다음과 같은 역할을 수행합니다.
- 매핑: 객체와 테이블, 필드와 컬럼을 매핑합니다.
- 변환: 객체와 데이터를 상호 변환합니다.
- SQL 생성: 객체 기반으로 SQL 쿼리를 자동으로 생성합니다.
- 트랜잭션 관리: 데이터베이스 트랜잭션을 관리합니다.
ORM의 장점:
- 생산성 향상: SQL 쿼리 작성에 대한 부담을 줄여 개발 생산성을 향상시킵니다.
- 유지보수성 향상: 객체 지향적인 방식으로 코드를 작성하여 코드의 가독성과 유지보수성을 높입니다.
- 재사용성 향상: 매핑된 객체를 재사용하여 코드의 재사용성을 높입니다.
- 데이터베이스 독립성: ORM을 사용하면 특정 데이터베이스에 종속되지 않고 다양한 데이터베이스를 사용할 수 있습니다.
ORM의 단점:
- 성능 저하: ORM은 SQL 쿼리를 자동으로 생성하므로 SQL 쿼리를 직접 작성하는 것보다 성능이 저하될 수 있습니다.
- 복잡성 증가: ORM은 매핑, 변환 등 추가적인 작업을 수행하므로 시스템의 복잡성을 증가시킬 수 있습니다.
- 학습 곡선: ORM을 사용하기 위해서는 ORM 프레임워크에 대한 학습이 필요합니다.
대표적인 ORM 프레임워크:
- Hibernate (Java)
- JPA (Java Persistence API, Java 표준 ORM)* : JPQL 객체 지향 쿼리 언어를 사용.
- MyBatis (Java)* : SQL 쿼리를 직접 작성하여 데이터베이스를 세밀하게 제어할 수 있음.
- Django ORM (Python)
- Active Record (Ruby on Rails)
결론:
ORM은 객체 지향 프로그래밍 언어와 관계형 데이터베이스 간의 간극을 메워주는 중요한 기술입니다. ORM을 사용하면 개발 생산성을 높이고 유지보수성을 향상시킬 수 있지만, 성능 저하 및 복잡성 증가와 같은 단점도 고려해야 합니다. ORM을 사용할 때에는 프로젝트의 특성과 요구 사항을 고려하여 적절한 ORM 프레임워크를 선택하고, ORM의 장단점을 충분히 이해하고 사용하는 것이 중요합니다.
Hibernate : Java 언어를 위한 ORM(Object-Relational Mapping) 프레임워크
자바 진영의 다양한 ORM 프레임워크 중 가장 많이 사용되는 프레임워크. Hibernate 기반으로 만들어진 ORM 기술 표준이 바로 JPA이다. 다시 말하면, JPA라는 ORM기술 표준을 구현한 것이 Hibernate이므로, JPA를 사용하려면 Hibernate를 사용하면 됨.
- 간편한 사용법: 복잡한 SQL 쿼리 작성 없이 객체 조작을 통해 데이터베이스를 다룰 수 있어 개발 생산성을 향상시킵니다.
- 유연성: 다양한 매핑 전략과 옵션을 제공하여 개발자가 원하는 방식으로 데이터베이스를 매핑할 수 있도록 합니다.
- 확장성: 필요에 따라 Hibernate의 기능을 확장하거나 커스터마이징할 수 있습니다.
Hibernate의 장점:
- 개발 생산성 향상: SQL 쿼리 작성에 대한 부담을 줄여 개발 시간을 단축시킵니다.
- 코드 가독성 향상: 객체 지향적인 방식으로 코드를 작성하여 코드의 가독성을 높입니다.
- 유지보수성 향상: 데이터베이스 스키마 변경 시 코드 수정 범위를 최소화하여 유지보수성을 높입니다.
- 재사용성 향상: 매핑된 객체를 재사용하여 코드의 재사용성을 높입니다.
- 데이터베이스 독립성: Hibernate를 사용하면 특정 데이터베이스에 종속되지 않고 다양한 데이터베이스를 사용할 수 있습니다.
Hibernate의 단점:
- 성능 저하: Hibernate는 SQL 쿼리를 자동으로 생성하므로 SQL 쿼리를 직접 작성하는 것보다 성능이 저하될 수 있습니다.
- 복잡성 증가: Hibernate는 매핑, 변환 등 추가적인 작업을 수행하므로 시스템의 복잡성을 증가시킬 수 있습니다.
- 학습 곡선: Hibernate를 사용하기 위해서는 Hibernate 프레임워크에 대한 학습이 필요합니다.
Hibernate 사용 방법:
- Hibernate 설정: Hibernate 설정 파일(hibernate.cfg.xml)을 작성하여 데이터베이스 연결 정보, 매핑 정보 등을 설정합니다.
- 엔티티 클래스 정의: 데이터베이스 테이블과 매핑될 클래스를 정의하고, 어노테이션을 사용하여 매핑 정보를 설정합니다.
- Session 생성: Hibernate Session을 생성하여 데이터베이스 작업을 수행합니다.
- 트랜잭션 관리: 트랜잭션을 시작하고 커밋 또는 롤백하여 데이터의 무결성을 보장합니다.
- CRUD 작업: Session을 통해 객체를 생성, 조회, 수정, 삭제하는 작업을 수행합니다.
JPA의 주요 구성 요소:
- Entity (엔티티) : 데이터베이스의 테이블에 해당하는 클래스. 이 클래스는 JPA 어노테이션을 사용하여 데이터베이스 테이블과 매핑됩니다.
- 엔티티 매니저 (EntityManager): JPA를 통해 데이터베이스 작업을 수행하는 데 중심 역할을 하는 클래스. 엔티티의 생명 주기를 관리합니다.
- 영속성 컨텍스트 (Persistence Context): 엔티티 인스턴스의 생명 주기를 관리하는 환경. 트랜잭션 범위 내에서 엔티티를 저장하고 관리합니다.
- 트랜잭션: 데이터베이스 작업을 묶어주는 방법으로, 작업들이 모두 성공하거나 실패하게 보장합니다.
1️⃣ Entity (엔티티)
✔ 실제 데이터베이스의 테이블과 매핑되는 클래스
✔ @Entity 어노테이션을 사용하여 선언
✔ @Id로 기본 키(PK)를 지정해야 함
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double salary;
}
2️⃣ EntityManager (엔티티 매니저)
✔ 엔티티를 데이터베이스에 저장, 조회, 수정, 삭제하는 역할
✔ 영속성 컨텍스트를 관리
✔ EntityManagerFactory에서 생성됨
예제 (엔티티 저장하기)
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin(); // 트랜잭션 시작
Employee emp = new Employee();
emp.setName("John");
emp.setSalary(5000);
em.persist(emp); // 엔티티 저장
em.getTransaction().commit(); // 트랜잭션 커밋
3️⃣ Persistence Context (영속성 컨텍스트)
✔ JPA가 엔티티 객체를 관리하는 공간
✔ 엔티티를 영속 상태로 만들어서 변경 사항을 자동 감지 (Dirty Checking)
✔ persist(), merge(), remove(), find() 등을 통해 관리
✅ Dirty Checking 예제
Employee emp = em.find(Employee.class, 1L); // 영속 상태
emp.setSalary(6000); // JPA가 변경 사항 자동 감지
// 트랜잭션이 커밋되면 자동으로 UPDATE SQL 실행됨
4️⃣ EntityManagerFactory (엔티티 매니저 팩토리)
✔ EntityManager를 생성하는 역할
✔ 애플리케이션 실행 시 한 번만 생성됨
✔ persistence.xml에 설정된 Persistence Unit을 기반으로 동작
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit");
EntityManager em = emf.createEntityManager();
5️⃣ Repository (리포지토리)
✔ Spring Data JPA에서 데이터베이스 접근을 위한 인터페이스
✔ JpaRepository를 상속하여 CRUD 메서드를 자동 제공
예제 (Spring Data JPA 사용)
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
List<Employee> findByName(String name); // 쿼리 메서드
}
6️⃣ JPQL (Java Persistence Query Language)
✔ SQL과 유사하지만, 테이블이 아닌 엔티티 객체를 대상으로 쿼리
✔ @Query 어노테이션을 사용하여 활용
@Query("SELECT e FROM Employee e WHERE e.salary > :salary")
List<Employee> findHighSalaryEmployees(@Param("salary") double salary);
📌 정리
구성 요소 | 역할 |
Entity | 테이블과 매핑되는 클래스 |
EntityManager | 엔티티 저장, 수정, 삭제, 조회 관리 |
Persistence Context | 엔티티 객체를 관리하는 1차 캐시 역할 |
EntityManagerFactory | EntityManager를 생성하는 팩토리 |
Repository | Spring Data JPA에서 데이터 접근을 담당 |
JPQL | 객체 중심의 쿼리 언어 |
JPA의 역할:
JPA는 다음과 같은 역할을 수행합니다.
- 객체-관계 매핑 (ORM): Java 객체와 데이터베이스 테이블을 매핑하여 객체 지향적인 방식으로 데이터베이스를 다룰 수 있도록 합니다.
- 데이터베이스 접근: JPA는 EntityManager를 통해 데이터베이스에 접근하고 데이터를 CRUD (Create, Read, Update, Delete) 작업을 수행할 수 있도록 합니다.
- 트랜잭션 관리: EntityTransaction을 사용하여 데이터베이스 트랜잭션을 관리하고 데이터의 무결성을 보장합니다.
- JPQL (Java Persistence Query Language): JPQL은 SQL과 유사한 객체 지향 쿼리 언어로, 데이터베이스에서 원하는 데이터를 검색할 수 있도록 합니다.
JPA의 구현체:
JPA는 명세이므로 실제 동작을 위해서는 구현체가 필요합니다. 대표적인 JPA 구현체로는 Hibernate, EclipseLink 등이 있습니다.
결론:
JPA는 인터페이스, 어노테이션, 클래스들의 묶음으로, Java 애플리케이션에서 관계형 데이터베이스를 효율적으로 관리하고 사용할 수 있도록 도와주는 명세입니다.
수업 : log.info(); 사용하기
'멋쟁이사자처럼_부트캠프 > Spring' 카테고리의 다른 글
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 52일차 Double(래퍼 클래스), 빌더 패턴(Builder Pattern) (0) | 2025.02.26 |
---|---|
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 47일차 Spring Data JPA (0) | 2025.02.19 |
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 43일차 EJB (0) | 2025.02.12 |
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 41일차 웹 프로그램 실습-1 (1) | 2025.02.07 |
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 40일차 스트림 (0) | 2025.02.06 |