스프링 기본 개념 정리5 - ORM, JPA, 엔티티, 영속성 컨텍스트

진용완·2025년 5월 16일
0

이 포스팅은 신선영 저, 『스프링 부트 3 백엔드 개발자 되기』(골든래빗, 2023)를 공부하면서 핵심 개념들을 정리하기 위해 작성하였습니다.

5장. 데이터베이스 조작이 편해지는 ORM

   클라이언트가 요청한 데이터를 전달하기 위해서는 데이터베이스에 접근해야 한다. 그런데 ORM이라는 프로그래밍 기법 덕분에 SQL 언어를 쓰지 않고도 자바 언어로만 데이터베이스에 접근할 수 있게 되었다.

□ ORM (Object Relational Mapping)
  ORM은 자바 언어만 가지고도 데이터베이스에 접근할 수 있도록 하는 프로그래밍 기법이다. 데이터베이스의 데이터와 자바의 객체 서로 연결짓는 방식으로 ORM을 실현한다.

   ORM의 장점은 다음과 같다.
  ○ 데이터베이스에 접근하기 위해 SQL 언어를 따로 사용할 필요가 없다.
  ○ 객체 지향적으로 코드를 작성할 수 있기 때문에 비즈니스 로직을 개발하는 데에만 집중할 수 있다.
  ○ 객체가 어떤 데이터와 상응하는지 명확하기 때문에 유지보수할 때에 용이하다.
  ○ 데이터베이스 관리 프로그램을 바꾸더라도 기존의 코드를 거의 변경하지 않아도 된다.

   한편 단점은 다음과 같다.
  ○ 프로젝트가 복잡해질수록 사용 난이도도 올라간다.
  ○ 복잡한 쿼리는 ORM으로 작동시킬 수 없다.


   ORM에도 여러가지 종류가 있다. 그 중에서 자바에서 표준으로 쓰이는 것은 JPA이다.

□ JPA (Java Persistence API)
  JPA는 자바에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스이다.

□ 하이버네이트 (Hibernate)
  JPA는 인터페이스므로 구현체가 필요하다. 하이버네이트가 바로 JPA를 실제로 동작하도록 구현한 ORM 프레임워크이다. 하이버네이트에서는 내부적으로 JDBC API를 사용한다.


   JPA와 하이버네이트가 객체를 통해 데이터베이스에 접근할 때에는 엔티티, 엔티티 메니저, 그리고 영속성 컨텍스트가 사용된다.

□ 엔티티 (Entity)
  엔티티는 데이터베이스의 테이블에 상응하는 객체이다. 엔티티는 데이터베이스에 쿼리를 실행하는 기능을 지니고 있기 때문에 다른 객체들과 차별점을 두어 엔티티라는 별도의 이름으로 부른다.

□ 엔티티 매니저 (Entity Manager)
  엔티티 매니저는 엔티티들을 관리하는 역할을 한다. 엔티티 매니저는 엔티티 매니저 팩토리에서 생성된다.
  같은 요청이 여러곳에서 동시에 들어올 때 엔티티 매니저 팩토리는 각 요청에 대응할 수 있는 엔티티 매니저들을 생성한다. 이때 생성되는 엔티티 매니저들은 실제 엔티티 매니저가 아니라 프록시(가짜) 엔티티 매니저들이다. 왜냐하면 스프링부트에서는 빈을 하나만 생성해서 공유하는 방식으로 동작하기 때문이다. 생성된 프록시 엔티티 매니저는 자신이 맡은 요청에 따라서 엔티티들을 생성하고 저장한다.

□ 영속성 컨텍스트 (Persistence Context)
  영속성 컨텍스트는 엔티티를 관리하는 가상의 공간이다. 엔티티 매니저가 생성한 엔티티는 영속성 컨텍스트에 저장된다.
  영속성 컨텍스트라는 별도의 가상 공간을 만들어서 엔티티를 관리하는 이유는 영속성 컨텍스트가 다음과 같이 데이터베이스에 접근하는 부담을 덜어주는 기능들을 맡아 성능을 올려주기 때문이다.

   ○ 1차 캐시
  영속성 컨텍스트에는 1차 캐시라는 임시 저장 공간이 있다. 엔티티를 조회할 때에 가장 먼저 1차 캐시를 조회한다. 만약 1차 캐시에 엔티티가 존재한다면 데이터베이스에 접근하지 않고도 결과값을 반환할 수 있다. 1차 캐시에 엔티티가 존재하지 않는다면 데이터베이스에서 조회한 데이터를 1차 캐시에 저장해둔다. 자주 조회하는 엔티티는 1차 캐시 덕분에 빠른 속도로 조회할 수 있다.

   ○ 쓰기 지연
  영속성 컨텍스트는 쿼리들을 어느정도 모아둔 다음에 한꺼번에 데이터베이스에 전송한다. 모아뒀던 쿼리들을 한꺼번에 보내는 것을 트랜잭션을 커밋한다고 표현한다. 데이터베이스에 접근하는 회수를 줄임으로써 부담을 줄이려는 목적이다.

   ○ 변경 감지
  트랜잭션을 커밋하면 1차 캐시에 있는 엔티티와 데이터베이스에 있는 데이터를 비교하여, 변경 사항이 감지되었을 경우에 변경된 값을 자동으로 데이터베이스에 반영한다. 쓰기 지연과 마찬가지로 데이터베이스에 접근하는 회수를 줄임으로써 부담을 줄이려는 목적이다.

   ○ 지연 로딩
  쿼리로 요청한 데이터를 애플리케이션에 바로 로딩하지 않고 필요할 때에만 로딩한다.

   엔티티는 영속성 컨텍스트와 어떤 관계를 맺고 있느냐에 따라서 네가지 상태로 나뉜다.

  1. 비영속 상태 : 엔티티가 영속성 컨텍스트와 전혀 관련이 없는 상태이다.
  2. 관리 상태 : 엔티티가 영속성 컨텍스트에서 관리되고 있는 상태이다.
  3. 분리 상태 : 엔티티가 영속성 컨텍스트로부터 분리된 상태이다.
  4. 삭제 상태 : 엔티티가 영속성 컨텍스트와 데이터베이스에서 삭제된 상태이다.

0개의 댓글