메이쁘

[Spring] 예상 Q&A 공부(EntityManager, 영속성 컨텍스트, @Transactional readOnly) 본문

면접 대비 CS지식/SELF CS면접 Q&A

[Spring] 예상 Q&A 공부(EntityManager, 영속성 컨텍스트, @Transactional readOnly)

메이쁘 2021. 12. 29. 23:46

안녕하세요.

 

CS관련 질문과 면접에 맞는 답변을 작성하면서 지식도 쌓고 면접도 대비하는 시간을 가지려고 합니다.

 

 

틈틈히 게시글을 작성하며 면접 대비 데이터셋을 확보해둔 다음

 

언젠간 면접하게 될 때 모아서 쓰려고 합니다.

 

(실제로 면접에서 들었던 질문이 아니라, 제가 스스로 답을 정해놓고 짜논 질문이라 이렇게 안나올 수 있습니다!!!)

 

 

 

이번 글은 Spring 카테고리 입니다.

 

 

 

 

  -- 질문 목록

 

Q1. find 시 transaction에 readonly 속성을 준 이유가 있을까요? (=@Transactional 어노테이션에 readOnly 속성을 부여한 이유?)

Q2. EntityManager가 무엇이고, JPA에서는 어떻게 사용하나요?

Q3. 영속성 컨테스트(Persistence Context)가 무엇이고, 어떤 역할을 하나요?


Q1. find 시 transaction에 readonly 속성을 준 이유가 있을까요? (=@Transactional 어노테이션에 readOnly 속성을 부여한 이유?)

 

A. 우선, Read한 데이터를 해당 트랜잭션 안에 수정/삭제하지 않는 경우에 사용했습니다. 이렇게 readOnly 속성을 적용한 이유는 메모리 사용에 있어 좀 더 나은 최적화를 위해서 입니다.

 

readOnly 속성이 없는 보통의 트랜잭션은 데이터 조회 결과 엔티티가 영속성 컨테스트에 관리되고, 이는 1차 캐싱부터 변경상태감지(Dirty Checking)까지 가능하게 됩니다. 하지만, 조회 시 스냅샷 인스턴스를 생성해 보관하기 때문에 메모리 사용량이 증가합니다.

 

위에 말했다시피, 데이터를 Read만 할 목적이라면 영속성 컨테스트에 엔티티를 관리할 필요가 없기 때문에 메모리 성능을 높일 수 있습니다. readOnly 설정이 되면, 트랜잭션 commit 시에도 영속성 컨테스트가 flush되지 않습니다.

 

추가적으로, 데이터 변경 불가능 로직임을 코드로 표시할 수 있어 가독성이 높아집니다.

 

 

Q2. EntityManager가 무엇이고, JPA에서는 어떻게 사용하나요?

 

A. 우선, EntityManager를 설명하기 전에 EntityManagerFactory에 대해서 설명드리겠습니다.

EntityManagerFactory는 보통 애플리케이션에서 사용하는 DB 종류 하나 당 하나만 생성하는데, 이 한 개를 가지고 애플리케이션 전체에서 공유되도록 설계되어있습니다. (싱글톤 방식)

 

여기서 EntityManager를 생성하는 역할이 주 업무인데요. EntityManagerFactory는 thread-safe해서 동시성이 보장되지만, 생성 비용이 상당히 큰 반면, EntityManager는 생성 비용이 거의 없습니다.

그래서 JPA는 DB접근 요청이 들어올 때마다 EntityManagerFactory에서는 EntityManager를 생성하여 DB연결 요청을 처리합니다.

 

EntityManager는 not thread-safe해서 동시성이 보장되지 않기 때문에, 요청 별로 쓰레드가 하나씩 담당하고, 각 쓰레드 별 EntityManager를 생성해 처리합니다.

EntityManager는 Mapping한 Entity를 가지고 DB연결 요청을 처리하고 Entity 상태를 관리하는 클래스입니다.

그래서, DB 연결이 필요한 시점까지는 Connection Pool에서 Connection을 얻지 못합니다. 그러다 필요하게되면 Connection을 사용해서 DB와 연동합니다.

출처 : https://ultrakain.gitbooks.io/jpa/content/chapter3/chapter3.1.html

 

 

Q3. 영속성 컨텍스트(Persistence Context)가 무엇이고, 어떤 역할을 하나요?

 

A. 영속성 컨텍스트는 간단하게 설명드리자면, 엔티티를 영구적으로 저장하는 환경입니다.

영속성은 비휘발성과 같은데, 시스템이나 애플리케이션이 종료되도 데이터는 영구히 남아있는 속성을 말합니다.

 

그래서 영속성 컨텍스트는 애플리케이션과 DB 사이에 엔티티를 보관하는 논리적 / 추상적인 개념입니다.

EntityManager를 통해 영속성 컨텍스트에 접근할 수 있는데요. 보통 EntityManager가 생성되면 영속성 컨텍스트도 함께 생성됩니다.

스프링 프레임워크같은 경우에는 하나의 트랜잭션 범위 안에 여러 개의 EntityManager는 동일한 하나의 영속성 컨텍스트를 바라봅니다. (N:1관계)

 

EntityManager를 통해 데이터를 insert하거나 select하면 영속성 컨테스트에 1차적으로 엔티티를 기록합니다. (1차 캐시) 가장 처음에는 1차 캐시로 기록하면서 동시에 스냅샷을 생성해둡니다.

이는 EntityManager의 persist() 함수를 통해 이뤄지게 됩니다.

 

이후 트랜잭션 내에 엔티티의 변화가 일어난 뒤 commit되는 순간에 flush가 발생합니다. (flush() 호출)

그 때 영속성 컨텍스트의 1차 캐시와 스냅샷을 비교합니다.

 

변경사항이 있는 경우 Update SQL Query를 생성하고, flush가 끝나기 전 이 쿼리를 DB에 날립니다. 이를 상태변경감지, 즉, Dirty Checking이라고 합니다.

(영속 상태의 엔티티만 적용됩니다.)

출처 : https://ultrakain.gitbooks.io/jpa/content/chapter3/chapter3.4.html

또한, 영속성 컨텍스트에는 1차캐시, 스냅샷 뿐 아니라 '쓰기 지연 SQL 저장소' 도 존재하는데, INSERT/DELETE 요청 시 바로 DB에 전달하는 것이 아니라 이 저장소에 SQL 쿼리문을 만들어 저장해둡니다.

그 후 flush 호출 시 한번에 DB에 전달합니다. 이 후 마지막으로 위에 적은 Dirty Checking 과정 후 Update 쿼리문을 전달하는 것으로 '쓰기 지연 SQL 저장소' 의 역할이 끝납니다.

 

추가로, Spring에서는 EntityManager를 Proxy를 통해 감싸고, EntityManager의 메소드 호출 시마다 Proxy를 통해 EntityManager를 생성하여 Thread-safe를 보장합니다.

(참고: https://medium.com/@SlackBeck/spring-container%EB%8A%94-jpa-entitymanager%EC%9D%98-thread-safety%EB%A5%BC-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%B3%B4%EC%9E%A5%ED%95%A0%EA%B9%8C-1650473eeb64)

 

 

 

 

이상입니다.

 

감사합니다!

Comments