스프링
프록시
148june
2025. 4. 18. 16:47
🧩 프록시(Proxy)란?
JPA에서 em.getReference()를 호출하면 실제 엔티티 객체가 아닌 프록시 객체를 반환해. 이 프록시는 지연 로딩(Lazy Loading) 을 위한 가짜 객체야.
🔁 프록시의 목적
- DB 접근을 지연시키기 위해 사용돼.
- 엔티티의 실제 데이터를 당장 불러오지 않고, 필요할 때 DB에서 조회하게 만들어.
✅ 프록시 작동 방식
Tutor proxyTutor = em.getReference(Tutor.class, tutor.getId());
- 이 시점에서는 DB에 쿼리를 날리지 않음
- 대신 Tutor를 상속받은 프록시 객체가 생성됨
- proxyTutor.getName() 같이 프록시의 필드에 접근하면 그 시점에 DB 조회 발생
✅ 프록시 특징 정리
특징 설명
em.find() vs em.getReference() | find()는 즉시 조회, getReference()는 프록시 반환 (지연 로딩) |
---|---|
프록시 클래스 | Hibernate가 내부적으로 만든 CGLIB 클래스ex. com.example.Tutor$HibernateProxy |
DB 조회 시점 | 속성에 실제로 접근할 때 조회 발생 (getName() 등) |
== 비교 | 프록시와 실제 객체는 다름, == 비교 실패 |
instanceof | 성공 (proxy instanceof Tutor == true) |
초기화 여부 | 최초 1회만 DB 조회됨 |
영속성 컨텍스트 | 준영속 상태(detach) 에서 접근하면 LazyInitializationException 발생 |
✅ 예시 흐름
// 프록시 반환
Tutor proxyTutor = em.getReference(Tutor.class, 1L);
// 실제 데이터 조회는 여기서!
proxyTutor.getName(); // 이때 DB 조회
// ❗준영속 상태에서는 에러 발생
em.detach(proxyTutor);
proxyTutor.getName(); // ❌ LazyInitializationException
⚠️ 프록시 사용 시 주의사항
- 컨트롤러 등에서 프록시 객체를 그대로 JSON 직렬화하면 에러 발생
→ 예: Could not write JSON: failed to lazily initialize a collection - 테스트 코드에서 프록시를 사용할 땐 em.clear() 후 접근에 주의해야 함
- 프록시는 영속성 컨텍스트 안에서만 의미 있음
🧠 요약 한 줄 정리
프록시는 실제 엔티티 대신 "껍데기 객체" 를 반환하고, 실제 데이터는 필요할 때만 가져오는 지연 로딩 도우미다.