2022-04-11 @이영훈
프록시 패턴
다른 객체에 대한 접근을 제어하기 위한 대리자 또는 자리채움자 역할을 하는 객체를 둡니다.
객체를 직접적으로 참조하는 것이 아닌 해당 객체를 대신하는 객체를 통해 접근하는 방식입니다. 해당 객체가 메모리에 존재하지 않아도 기본적인 정보를 참조하거나 설정할 수 있습니다.
해당 객체가 사용될 때까지 생성을 미룰 수 있어(lazy loading) 불필요한 메모리 사용을 줄일 수 있습니다.
데이터베이스 지연 로딩(Lazy Loading) 예제
학교와 학생이 있습니다. 한 학교에는 여러명의 학생이 재학할 수 있습니다.
그리고 학생 정보를 가지고 있는 StudentTable이 있습니다. 데이터베이스의 그 테이블입니다.
학교의 기본 정보를 가져올 때는 학생의 정보가 필요하지 않기 때문에 학생 정보를 Proxy 객체로 가지고 있다가, 학교의 학생들 정보를 호출할 때 데이터베이스에 학생들의 정보를 가져옵니다.
데이터베이스 지연 로딩(Lazy Loading) 예제 - 코드 작성
학교 클래스를 만듭니다
public class School {
private final Long id;
private final String name;
private final StudentListProxy studentListProxy; // List<Student> students 가 아니라 proxy 객체를 가지고 있습니다
public School(Long id, String name) {
this.id = id;
this.name = name;
studentListProxy = new StudentListProxy(id);
}
// 학교와 관련된 정보만 호출
public void getSchoolInfo() {
System.out.println("id= " + id + ", name= " + name);
}
// 학생 정보를 호출. 🚀 이때 데이터베이스에 접근해서 데이터를 가져옵니다
public void getStudentInfo() {
List<Student> students = this.studentListProxy.getStudents();
for (Student student : students) {
System.out.println(student);
}
}
}
Java
복사
학생 클래스를 만듭니다
public class Student {
private final Long id;
private final String name;
private final Long schoolId;
public Student(Long id, String name, Long schoolId) {
this.id = id;
this.name = name;
this.schoolId = schoolId;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public Long getSchoolId() {
return schoolId;
}
}
Java
복사
Lazy Loading을 가능하게 하는 학생 프록시 객체를 만듭니다
프록시 객체는 학생 리스트 객체를 대신하고 있다가 학생 정보를 호출할 때 데이터베이스에 접근해서 학생 데이터를 가져와서 반환합니다.
그리고 매번 호출 때마다 데이터베이스에 접근하지 않고 students 가 있으면 바로 반환해서 캐싱 역할도 합니다.
public class StudentListProxy {
private List<Student> students;
private final Long schoolId;
private final StudentTable studentTable;
public StudentListProxy(Long schoolId) {
this.schoolId = schoolId;
studentTable = new StudentTable();
}
public List<Student> getStudents() {
if (students == null) {
return studentTable.findBySchoolId(schoolId);
}
return students;
}
}
Java
복사
학생 테이블입니다. 데이터베이스의 역할을 합니다.
public class StudentTable {
// 저장된 학생 데이터
List<Student> students = List.of(
new Student(1L, "1번 학생", 1L),
new Student(2L, "2번 학생", 1L),
new Student(3L, "3번 학생", 1L),
new Student(4L, "4번 학생", 2L),
new Student(5L, "5번 학생", 2L)
);
// select 쿼리로 조회하는 역할
public List<Student> findBySchoolId(Long schoolId) {
return students.stream().filter(it -> Objects.equals(it.getSchoolId(), schoolId)).collect(Collectors.toList());
}
}
Java
복사
데이터베이스 지연 로딩(Lazy Loading) 예제 - 코드 실행
public class ProxyPattern {
public static void main(String[] args) {
School school = new School(1L, "Hello World School");
// 💡 학교 정보만 불러오는 경우에는 학생 정보는 필요하지 않으므로 학생 프록시 객체를 가지고 있습니다.
school.getSchoolInfo();
// id= 1, name= Hello World School
// 🚀 학생 정보가 필요할 때 비로소 학생 정보를 데이터베이스에서 조회해서 가지고 옵니다.
school.getStudentInfo();
// Student{id=1, name='1번 학생'}
// Student{id=2, name='2번 학생'}
// Student{id=3, name='3번 학생'}
}
}
Java
복사