728x90
안녕하세요,
오늘은 __clone() 메소드를 활용해서 객체 복사 시, 원본 객체와 복제된 객체가 독립되지 않는 문제를 해결해보도록 하겠습니다.
__clone() 메소드
PHP에서 clone 키워드를 사용해 객체를 복사할 때, 대부분의 개발자는 완전히 독립된 새로운 객체가 생성될 것이라 기대합니다. 하지만 예상과 다르게 동작할 때가 있습니다.
기본적으로 PHP의 clone은 얕은 복사(Shallow Copy)를 수행합니다.
이는 객체 내부의 프로퍼티가 또 다른 객체를 참조하고 있을 경우, 그 참조(주소값)만 복사하기 때문입니다.
결국, 원본 객체와 복제된 객체가 내부의 동일한 객체를 공유하게 되는 문제가 발생합니다.
이 문제를 해결하고, 내부 객체까지 모두 복제하여 완전한 독립을 보장하는 깊은 복사(Deep Copy)를 구현할 때 사용하는 것이 바로 __clone() 매직 메소드입니다.
얕은 복사(Shallow Copy) 문제 예시
<?php
class Profile {
public string $name;
public function __construct(string $name) {
$this->name = $name;
}
}
class User {
public Profile $profile;
public function __construct(Profile $profile) {
$this->profile = $profile;
}
}
// 1. 원본 사용자 객체 생성
$user1 = new User(new Profile('앨리스'));
// 2. user1을 단순 복제하여 user2 생성 (얕은 복사)
$user2 = clone $user1;
// 3. 복제된 user2의 프로필 이름을 변경
$user2->profile->name = '밥';
// 4. user2만 바꾸었는데, 원본인 user1의 이름까지 변경됨
echo "원본 사용자(user1)의 이름: " . $user1->profile->name . PHP_EOL;
echo "복제된 사용자(user2)의 이름: " . $user2->profile->name . PHP_EOL;
?>
얕은 복사(Shallow Copy) 결과
원본 사용자(user1)의 이름: 밥
복제된 사용자(user2)의 이름: 밥
__clone() 깊은 복사(Deep Copy) 예시
<?php
class Profile {
public string $name;
public function __construct(string $name) {
$this->name = $name;
}
}
class User {
public Profile $profile;
public function __construct(Profile $profile) {
$this->profile = $profile;
}
// clone이 호출될 때 이 메소드가 자동으로 실행됨
public function __clone() {
// 내부의 profile 객체도 새로 복제하여 연결을 끊는다.
$this->profile = clone $this->profile;
}
}
// 1. 원본 사용자 객체 생성
$user1 = new User(new Profile('앨리스'));
// 2. user1을 복제 (이때 __clone() 메소드가 실행됨)
$user2 = clone $user1;
// 3. 복제된 user2의 프로필 이름을 변경
$user2->profile->name = '밥';
// 4. user2만 바뀌고, 원본 user1은 영향을 받지 않음
echo "원본 사용자(user1)의 이름: " . $user1->profile->name . PHP_EOL;
echo "복제된 사용자(user2)의 이름: " . $user2->profile->name . PHP_EOL;
?>
__clone() 깊은 복사(Deep Copy) 결과
원본 사용자(user1)의 이름: 앨리스
복제된 사용자(user2)의 이름: 밥'PHP' 카테고리의 다른 글
| [PHP] array_walk()와 array_walk_recursive()의 차이점과 활용법 (0) | 2025.09.28 |
|---|---|
| [PHP] FilterIterator 로 if 없는 foreach loop 만들기 (0) | 2025.09.26 |
| [PHP] 상속(extends)을 사용하기 (0) | 2025.09.15 |
| [PHP] nullsafe 연산자 (?->): null 체크 지옥에서 벗어나기 (0) | 2025.09.12 |
| [PHP] strtotime()으로 자연어 날짜 처리하기 (0) | 2025.09.09 |