인프런 커뮤니티 질문&답변

김진욱님의 프로필 이미지

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

영속성 컨텍스트 1

'스프링에서 엔티티 매니저와 영속성 컨텍스트가 N:1'의 의미 질문 드립니다.

해결된 질문

22.10.26 23:36 작성

·

418

3

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? 예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요?
비슷한 질문 있지만 해결 되지 않음
3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예

[질문 내용]

'스프링에서 엔티티 매니저와 영속성 컨텍스트가 N:1'의 의미 질문 드립니다.


강의 4분 1초쯤 스프링에서는 엔티티 매니저와 영속성 컨텍스트가 N:1 이라는 장표가 있는데 아래와 같이 이해했습니다.

  • N개의 EntityManager 객체들은 동일한 PersistenceContext 객체를 참조하고 있음 (싱글톤)

위 내용을 확인 해보고자 본 강의의 소스파일(jpashop-v20210728)을 인텔리제이에서 디버그 실행한 상태에서 다수의 HTTP 요청을 보내서, HTTP 요청마다 생성된 다수의 EntityManager 객체가 하나의 PersistenceContext 객체를 참조하고 있는지 확인했습니다.

 

확인 결과 EntityManager 객체마다 각각 다른 PersistenceContext 객체를 참조하고 있었습니다. 5번의 HTTP 요청을 보내서 5개의 엔티티매니저 객체와 영속성 컨텍스트 객체가 생성됐습니다.

위 내용만 본다면, 스프링부트 프로젝트인데 J2SE 환경과 마찬가지로 엔티티 매니저와 영속성 컨텍스트가 1:1로 생성되는것으로 보여서, 제가 위 장표를 잘못 이해한것 같아 질문 드립니다.

감사합니다~

 

답변 2

3

김진욱님의 프로필 이미지
김진욱
질문자

2022. 10. 27. 08:54

좀 더 알아보니 HTTP 요청마다 엔티티매니저 구현체와 영속성 컨텐스트 구현체가 만들어진 이유는 아래와 같이 이해할 수 있었습니다.

  • http 요청이 오면 쓰래드마다 1개의 EntityManager 구현체와 PersistenceContext 구현체가 만들어짐

    • 쓰래드간에 EntityManager 객체가 공유되면 안되기 때문에 (동시성 문제)

  • 위 질문 상황에서는 5개의 쓰래드를 사용 중이기 때문에 5개의 EntityManager 구현체와 PersistenceContext 구현체가 만들어진것

    • 이후 http요청 처리 완료되면 각 EntityManager 구현체와 PersistenceContext 구현체는 필요없으므로 파괴됨

 

그리고 좀 더 디버거로 살펴보니, 엔티티매니저 proxy 객체로부터 N개의 엔티티매니저 메서드가 호출 되면 각 메서드를 처리할 때 필요한 N개의 익명 객체가 생성되는 것을 알 수 있었습니다.

image

image

그렇다면 '스프링에서 엔티티 매니저와 영속성 컨텍스트가 N:1' 라는걸 다음처럼 이해하면 맞을까요?

  • 스프링에서도 다른 환경과 동일하게 (한 개 쓰래드마다) EntityManager 구현체와 PersistenceContext 구현체는 1개씩 생성 (1:1)

  • 엔티티매니저의 각 메서드를 처리하는 N개의 익명 객체, EntityManager, PersistenceContext 구현체 (N:1:1)

 

'엔티티 매니저가 N개'라고 할 때 여기서 엔티티 매니저가 정확히 무엇을 의미하는지 알면 될 것 같은데,
아래의 후보 중에서 N개가 될만한 것이 익명 객체 밖에 안떠올라서 위처럼 생각했습니다.

  • EntityManager 구현체 (SessionImpl 인스턴스) -> 1개

  • EntityManager 프록시 객체 -> 1개

  • EntityManage의 각 메서드를 처리하는 익명 객체 -> N개 (호출된 메서드의 수)

 

** 캡처 이미지는 강의 소스코드의 MemberServiceTest를 수정해서 디버그 실행 했습니다.

1

김영한님의 프로필 이미지
김영한
지식공유자

2022. 10. 30. 17:48

안녕하세요. 김진욱님

이것을 확인하려면, repositoryA, repositoryB를 만들고, 하나의 요청으로 repositoryA, repositoryB 둘다 사용해보시면 됩니다. 물론 하나의 트랜잭션 안에서 둘다 호출해야 합니다.

이렇게 되면 영속성 컨텍스트가 다음과 같이 2개 처럼 보입니다.

repositoryA에 하나

repositoryB에 하나

하지만 둘다 같은 하나의 영속성 컨텍스트에 접근하게 됩니다. 따라서 N:1이 됩니다.

 

다음을 참고해주세요.

https://www.inflearn.com/questions/158967

감사합니다.