BackEnd/JPA

[JPA] 프록시(Proxy) 기초 (1)

JJangGu 2022. 5. 17. 01:49

연관관계를 마무리하고 프록시로 넘어가려고 합니다. 상속이나 고급매핑 등을 더 다루려고 했으나, 제 경험상으로는 JPA를 사용하면서 연관관계를 너무 복잡하게 맺으면 유지보수나 개발 측면에서 어려움이 있었습니다. 

 

OOP를 염두해두고 개발을 하다보면 안그래도 객체간의 관계에 집중을 하게되고, 어떻게 캡슐화를 시킬지 은닉할지 메시지를 주고받게 할지 많은 고민을 하게됩니다. 그런데 연관관계가 너무 복잡하면 OOP의 난이도도 너무 많이 올라간다고 생각합니다. 적당한 선에서 코드 품질을 유지하고, 꼭 필요한 매핑이 있다면 저도 그때그때 찾아가면서 개발을 하는 편입니다. 

 

그러면 이번부터는 프록시에 대해서 알아보겠습니다. 

 

Proxy

proxy 는 사전적 의미로 다른 사람을 대신 할 권한이 있는 대리인, 다른 사람을 위해 행동할 수 있는 권한 등의 의미를 가지고 있습니다.

 

이런의미를 가지고 있고, 주로 '프록시 서버' 와 '리버스 프록시' 등의 단어로 익숙한 단어입니다. 하지만 디자인 패턴을 공부하다 보면 프록시 패턴이 나오고, 스프링을 공부하다가 AOP 에 대해서 공부하다보면 또다시 프록시라는 단어가 등장합니다.

 

잠시 프록시 패턴에 대해서 얘기해보면 어떤 객체에 대한 접근을 제어하기 위한 용도로 대리인이나 대변인에 해당하는 객체를 제공하는 패턴이라고 설명하고 있습니다. 

 

그렇다면 JPA 에서 프록시가 갖는 의미는 무엇일까요? 

 

JPA에서 엔티티를 조회할 때에는 연관된 엔티티들이 항상 사용되는 것이 아닙니다. 예를 들어 회원 엔티티를 조회할 때 연관된 팀 엔티티는 로직에 따라 사용될 때도 있지만 그렇지 않을 때도 있습니다.

 

@Entity
public class Member {
    
    private String username;
    
    @ManyToOne
    private Team team;
    
    public Team getTeam() {
    	return team;
    }
    
    public String getUsername() {
    	return username;
    }
    ...
}

@Entity
public class Team {
    
    private String name;
    
    public String getName() {
    	return name;
    }
    ...
}

 

이렇게 2개의 엔티티가 있다고 했을 때를 가정해보겠습니다.

 

public void printUserAndTeam(String memberId) {
    Member member = em.find(Member.class, memberId);
    Team team = member.getTeam();
    System.out.println(member.getUsername());
    System.out.println(team.getName());
}

 

위의 코드를 보면 Member 엔티티를 통해 Team 도 찾고, 이름도 출력을 했습니다. 

 

public void printUser(String memberId) {
    Member member = em.find(Member.class, memberId);
    System.out.println(member.getUsername());
}

 

그렇다면 지금은 어떤가요? Team 이 전혀 쓰이지 않고 있습니다. 그래서 이때는 Team 엔티티까지 조회하는 것은 효율적이지 않습니다. JPA는 이런 문제를 해결하려고 엔티티가 실제 사용될 때까지 데이터베이스에서 조회를 지연하는 방법을 제공합니다. 이것을 지연 로딩이라고 합니다.

 

그런데 지연 로딩을 사용하려면 실제 엔티티 객체 대신에 데이터베이스 조회를 지연할 수 있는 가짜 객체가 필요하고, 이를 프록시 객체라고 합니다.

 

프록시가 왜 필요한지에 대해서 먼저 이야기 했는데요, 프록시는 내용이 간단하지 않다고 생각해서 조금 더 여러번 끊어서 가겠습니다. 👍