본문 바로가기
백엔드

[Spring Boot] JPA와 동작원리

by 육빔 2024. 8. 26.
728x90
반응형

요즘 Spring을 하는 사람이라면 JPA를 모를래야 모를수가 없는 기술인 것 같다. 객체지향 패러다임을 살고 있는 개발자 시대에 필수 기술인 듯 하다. 일단 JPA뜻은 무엇일까?

 

JPA(Java Persistence API)는 자바에서 객체를 관계형 데이터베이스에 영구적으로 저장하고 관리하기 위한 표준 API라고 한다.

 

사실 쉽게 설명하면 관계형데이터베이스에는 객체지향이라는 관계가 없다. 상속, 캡슐화 등.. 그러나 java에서는 class단위로 우리가 코드를 설계하고 작성한다. 이러한 간격을 줄여주고자 사용하는 것으로 알고있다.

 

그럼 여기서 Persistence는 무엇인가?

 

GPT한테 물어보자.

 

영속성(Persistence)

  • 영속성은 객체를 데이터베이스에 저장하고, 필요한 경우 이를 다시 불러오는 것을 의미합니다. JPA는 애플리케이션 내의 객체 상태를 데이터베이스에 영구적으로 저장할 수 있게 해줍니다.

단순히 잘 이해가 되지 않는다. 설명이 상당히 빈약하다. 

 

일단 우리가 우선적으로 일반적으로 가장 처음에 하는 entity에 붙이는 코드를 다시 살펴보자.

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class UserEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String username;
    private String password;
    private String email;
    private String role;
}

 

import 되는 곳을 보면 전부 jakarta.persistence에서 가져오고 있다. 

 

아래 의존성을 설치하면 jakarta.persistence에서 가져올 수 있다. 

    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

 

우리는 단순 의존성을 설치하고 저렇게 entity를 설정하고 원하는 데이터베이스와 연동만 한다면 사용할 수 있다. 이게 어떻게 가능한 것일까?

 

우리가 위같은 의존성을 설치하고 entity를 생성하면 다음과 같은 행동이 동작한다.

 

1. 엔티티 매니저 팩토리(Entity Manager Factory) 생성

  • 엔티티 매니저 팩토리는 애플리케이션 전역에서 하나만 생성되는 객체로, 특정 데이터베이스와 연결된 EntityManager를 생성하는 역할을 합니다.

EntityManagerFactory는 이름에서 알 수 있듯이 요청마다 EntityManager를 생성한다.

내부적으로 처음에 생성된다.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");

 

 

2. 엔티티 매니저(Entity Manager) 생성

  • 엔티티 매니저는 영속성 컨텍스트를 관리하는 객체로, 주로 트랜잭션 당 하나씩 생성됩니다.
  • EntityManager는 EntityManagerFactory에서 생성되며, 실제로 엔티티를 관리하고 데이터베이스와 상호작용하는 역할을 합니다.
EntityManager em = emf.createEntityManager();

 

3. 엔티티 매니저가 영속성 컨텍스트 생성

  • EntityManager가 생성되면, 이와 함께 영속성 컨텍스트가 생성됩니다.
  • 영속성 컨텍스트는 엔티티 객체를 관리하는 일종의 "캐시"로, 엔티티의 상태를 추적하고, 데이터베이스와의 동기화를 담당합니다.

영속성 컨텍스트는 '엔티티를 영구 저장하는 환경' 이다. 

em.persist(member);

 

위와 같은 명령어로 엔티티의 생명주기가 시작되는데

엔티티 생명주기

 

엔티티의 생명주기 관리는 4가지로 구분 할 수 있다.

 

1. 비영속 상태(New/Transient): 데이터베이스와 전혀 연결되지 않은 상태입니다. 엔티티가 생성되었지만, 아직 영속성 컨텍스트에 의해 관리되지 않는 상태입니다. 

User user = new User();

 

이렇게 단순히 객체만을 생성한 상태이고 영속성 컨텍스트에 아무런 영향을 주지 못합니다.

 

2. 영속 상태(Managed): 영속성 컨텍스트에 의해 관리되는 상태로, 데이터베이스에 연결되어 있습니다. 이 상태에서는 엔티티의 변경 사항이 자동으로 데이터베이스에 반영됩니다.

em.persist(user);

 

이 상태는 이제 생명주기가 시작되는 단계로 데이터베이스와 연결이 됩니다.

 

3. 준영속 상태(Detached): 영속성 컨텍스트가 더 이상 관리하지 않는 상태입니다. 영속 상태였던 엔티티가 영속성 컨텍스트에서 분리된 상태입니다.

em.detach(user);

 

관리하지는 않고 어떠한 기능을 제공 받지 못합니다.

 

4. 삭제 상태(Removed): 엔티티가 영속성 컨텍스트에서 삭제된 상태로, 데이터베이스에서도 삭제될 예정입니다.

em.remove(user);

 

 

아래는 영속성 컨텍스트의 특징입니다.

 

  • 1차 캐시
    • 영속성 컨텍스트는 1차 캐시 역할을 합니다. 즉, 데이터베이스에서 조회한 엔티티 객체를 영속성 컨텍스트에 캐싱하여, 동일한 엔티티를 다시 조회할 때 데이터베이스에 쿼리를 보내지 않고 캐시된 객체를 반환합니다. 이를 통해 성능이 향상됩니다.
    • 예를 들어, 같은 트랜잭션 내에서 동일한 id로 엔티티를 조회하면 처음에는 데이터베이스에서 데이터를 가져오지만, 이후에는 영속성 컨텍스트의 1차 캐시에서 데이터를 반환합니다.
  • 변경 감지(Dirty Checking)
    • 영속성 컨텍스트는 엔티티의 상태 변화를 감지하여, 트랜잭션이 커밋될 때 자동으로 변경된 데이터를 데이터베이스에 반영합니다. 이를 통해 별도의 UPDATE 쿼리를 작성하지 않고도 엔티티의 변경 사항이 자동으로 처리됩니다.
    • 예를 들어, 영속 상태의 엔티티 객체의 필드 값을 변경하면, 트랜잭션이 커밋될 때 JPA는 변경된 내용을 감지하고 해당 UPDATE 쿼리를 실행합니다.
  • 쓰기 지연(Batch Writing)
    • 영속성 컨텍스트는 여러 데이터 변경 작업을 모아서 한 번에 처리할 수 있습니다. 트랜잭션이 커밋되기 전까지 SQL 쿼리들은 실행되지 않고 영속성 컨텍스트에 모아두었다가, 트랜잭션이 커밋될 때 한 번에 실행됩니다. 이를 통해 데이터베이스와의 통신 횟수를 줄이고 성능을 최적화할 수 있습니다.

 

728x90
반응형