얕은 복사 (Shallow Copy)
- 객체의 1차 필드(속성)만 복사하고 그 필드가 또 다른 객체를 참조하고 있으면 참조 주소만 복사함
- 겉껍질만 복사하고 안의 내용은 원본과 공유
- 객체 안에 있는 참조 타입 필드는 원본과 복사본이 같은 객체를 가리킴
- 하나를 바꾸면 다른 하나도 바뀔 수 있음
class Person {
String name;
Address address;
}
class Address {
String city;
}
Person p1 = new Person();
p1.name = "Alice";
p1.address = new Address();
p1.address.city = "Seoul";
// 얕은 복사
Person p2 = p1; // 참조만 복사
p2.address.city = "Busan";
System.out.println(p1.address.city); // "Busan"
깊은 복사 (Deep Copy)
- 객체를 복사하면서 참조 타입 필드도 새로운 객체로 생성해서 복사
- 객체 구조 전체를 재귀적으로 복사
- 원본과 복사본이 완전히 독립적인 객체가 됨
- 하나를 바꿔도 다른 하나에 영향 없음
class Person implements Cloneable {
String name;
Address address;
public Person clone() {
Person cloned = new Person();
cloned.name = this.name;
cloned.address = new Address();
cloned.address.city = this.address.city;
return cloned;
}
}
class Address {
String city;
}
Person p1 = new Person();
p1.name = "Alice";
p1.address = new Address();
p1.address.city = "Seoul";
// 깊은 복사
Person p2 = p1.clone();
p2.address.city = "Busan";
System.out.println(p1.address.city); // "Seoul"
항목 | 얕은 복사 (Shallow Copy) | 깊은 복사 (Deep Copy) |
---|---|---|
기본 방식 | 참조만 복사 | 객체를 새로 생성해 복사 |
참조 타입 필드 | 공유됨 | 독립적 |
메모리 사용 | 적음 | 많음 |
독립성 | 낮음 | 높음 |
.clone()
메서드
- 기본적으로 얕은 복사
- clone()을 오버라이드해서 내부 객체도 새로 생성해야 깊은 복사 가능
- Cloneable 인터페이스를 Implements해야 함 → CloneNotSupportedException 발생
clone()을 왜 오버라이딩해야 하나요?
- clone()은 Object 클래스에 protected로 정의되어 있기 때문에 직접 사용하려면 오버라이딩해서 public으로 변경해야 함
- 깊은 복사를 구현하려면 내부 로직도 커스터마이징 해야 하므로 오버라이딩 필요
빌더 패턴
- 필드를 그대로 넘기면 얕은 복사
- 내부 객체를 새로 생성하면 깊은 복사
- 유연하고 가독성 좋음, 불변 객체에 유리
복사 생성자 (Copy Constructor)
- 얕은 복사 / 깊은 복사 선택 가능
- 선택적으로 구현
- 자주 사용되며 코드 명확
직렬화 / 역직렬화
- 기본적으로 깊은 복사
- 느리지만 객체 전체를 통째로 복제할 때 사용
상황 | 추천 방식 |
---|---|
단순한 복사, 속도 중요 | clone() (주의해서) |
불변 객체 만들고 싶을 때 | 빌더 패턴 |
코드 가독성 중요할 때 | 빌더 or 복사 생성자 |
객체가 복잡하고 깊은 구조일 때 | 빌더 / 복사 생성자 / 직렬화 방식 |
적용 사례
-
얕은 복사 → DTO나 설정값처럼 객체 구조가 단순하고 공유해도 문제없는 경우 주로 사용, 컨트롤러에서 서비스로 전달되는 객체는 불변으로 설계되어 있어 얕은 복사로 충분
-
깊은 복사 → 내부 상태까지 완전히 분리된 객체가 필요한 경우 사용
-
멀티스레드 환경에서 공유된 객체가 상태 변경시 문제를 일으킬 수 있기 때문에 깊은 복사를 통해 안전하게 분리해서 사용