Mobile & App Stack/Java Software Architecture & Patterns

프로토타입 패턴(Prototype Pattern) 완벽 정리: 깊은 복사와 얕은 복사 차이점

임베디드 친구 2024. 12. 23. 08:57
반응형

애플리케이션을 개발하다 보면 객체를 생성하는 데 비용이 너무 많이 들거나, 기존 객체와 아주 유사한 객체를 여러 개 만들어야 하는 상황이 발생합니다. 이때 new 키워드로 매번 새로 생성하는 대신, 기존 객체를 복제하여 사용하는 프로토타입 패턴(Prototype Pattern)이 해결책이 될 수 있습니다.

Generated by Gemini AI.


1. 프로토타입 패턴이란?

프로토타입 패턴은 인스턴스를 새로 만드는 대신 기존에 있는 인스턴스를 복사(Clone)하여 새로운 객체를 생성하는 패턴입니다.

왜 사용하는가?

  1. 객체 생성 비용 절감: DB 조회 결과나 외부 API 연동을 통해 만들어진 복잡한 객체를 반복해서 만들 때 성능을 획기적으로 개선합니다.
  2. 초기화 과정 생략: 복잡한 초기 설정 과정을 거친 객체의 현재 상태를 그대로 복제하고 싶을 때 유용합니다.
  3. 클래스 의존성 제거: 구체적인 클래스 타입을 몰라도 인터페이스만 있다면 객체를 복제할 수 있습니다.

2. 핵심 이슈: 얕은 복사 vs 깊은 복사

프로토타입 패턴 구현 시 가장 주의해야 할 점은 복사의 깊이입니다.

구분 얕은 복사 (Shallow Copy) 깊은 복사 (Deep Copy)
특징 필드 값만 복사 (참조 변수는 주소만 복사) 참조하는 객체까지 새로 생성하여 복사
결과 원본과 복제본이 내부 객체를 공유 원본과 복제본이 완전히 독립적
위험성 복제본 수정 시 원본 데이터가 변할 수 있음 메모리 사용량이 상대적으로 많음

3. Java 구현 예제: 깊은 복사 적용

자바에서 제공하는 Cloneable 인터페이스를 활용하여, 내부 객체까지 안전하게 복제하는 예제를 살펴보겠습니다.

Step 1. 모델 클래스 정의

Java
 
// 내부 참조 객체
class Author {
    private String name;
    public Author(String name) { this.name = name; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

// Prototype 구현 클래스
class Book implements Cloneable {
    private String title;
    private Author author;

    public Book(String title, String authorName) {
        this.title = title;
        this.author = new Author(authorName);
    }

    @Override
    public Book clone() {
        try {
            // 1. 기본 얕은 복사 수행
            Book cloned = (Book) super.clone();
            // 2. 깊은 복사 수행: 내부 객체도 새로 복제하여 연결
            cloned.author = new Author(this.author.getName());
            return cloned;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(); // 일어날 수 없는 상황
        }
    }

    public void showInfo() {
        System.out.println("도서명: " + title + " | 저자: " + author.getName());
    }
    // Getter, Setter 생략
}

Step 2. 클라이언트 코드 실행

Java
 
public class Main {
    public static void main(String[] args) {
        Book original = new Book("디자인 패턴", "GoF");
        
        // 객체 복제
        Book copy = original.clone();
        copy.setAuthorName("John Doe"); // 복제본의 저자 변경
        
        System.out.println("--- 원본 데이터 ---");
        original.showInfo(); // 여전히 GoF 유지 (깊은 복사 덕분)
        
        System.out.println("--- 복제 데이터 ---");
        copy.showInfo();     // John Doe로 변경됨
    }
}

4. 프로토타입 패턴의 장단점

👍 장점

  • 성능 최적화: 복잡한 객체 생성 과정을 건너뛰어 실행 속도를 높입니다.
  • 런타임 유연성: 프로그램 실행 중에 객체의 복사본을 동적으로 생성할 수 있습니다.

👎 단점

  • 깊은 복사의 복잡성: 참조 관계가 복잡한 객체일수록 모든 경로를 수동으로 복제해줘야 하므로 구현이 까다롭습니다.
  • Cloneable의 한계: 자바의 clone() 메서드는 생성자를 호출하지 않아 객체 생성 방식이 다소 기형적이라는 비판이 있습니다.

5. 결론: 언제 사용해야 할까?

프로토타입 패턴은 "객체의 생성 과정이 런타임에 결정되거나, 생성 비용이 비쌀 때" 빛을 발합니다. 만약 자바의 clone() 방식이 복잡하게 느껴진다면, 최근 실무에서 더 권장되는 복사 생성자(Copy Constructor) 방식을 대안으로 고려해 보시기 바랍니다.


글이 도움이 되셨다면 공감과 구독 부탁드립니다!

반응형