**매직 메서드(magic method)**는 객체에 대한 특정 동작 — 정의되지 않은 프로퍼티 접근, 정의되지 않은 메서드 호출, 객체를 문자열로 변환 등 — 에 대응하여 PHP가 자동으로 호출하는 특수 메서드(__ 접두사)입니다. 객체 동작에 후크를 걸고 커스터마이즈하게 해 줍니다.
생성자와 일반적인 생명주기 메서드
{
{ }
{ }
}
class Container {
private array $data = [];
public function __get($name) { // 접근 불가/정의되지 않은 프로퍼티 읽기 시 호출됨
return $this->data[$name] ?? null;
}
public function __set($name, $value) { // 쓰기 시 호출됨
$this->data[$name] = $value;
}
public function __isset($name): bool { return isset($this->data[$name]); }
}
$c = new Container();
$c->foo = "bar"; // __set('foo', 'bar') 트리거
echo $c->foo; // __get('foo') 트리거 → "bar"
__get/__set은 존재하지 않거나 접근할 수 없는 프로퍼티에 대한 접근을 가로챕니다 — 동적 프로퍼티를 가능하게 합니다(ORM, 설정 객체에서 사용).
class Api {
public function __call($method, $args) { // 정의되지 않은 메서드 호출 시 호출됨
return $this->request($method, $args); // 예: 동적 API 메서드
}
public static function __callStatic($method, $args) { /* 정적 버전 */ }
}
$api->getUsers(); // getUsers() 메서드 없음 → __call('getUsers', [])
__call/__callStatic은 정의되지 않은 메서드 호출을 가로챕니다 — 유연한/동적 API에 사용됩니다(예: Laravel의 쿼리 빌더, 파사드).
class Money {
public function __construct(private float $amount) {}
public function __toString(): string { // 객체가 문자열로 사용될 때
return '$' . number_format($this->amount, 2);
}
}
echo new Money(9.5); // "$9.50" — __toString이 자동으로 호출됨
class Multiplier {
public function __invoke($x) { return $x * 2; } // 객체를 호출 가능하게 만듦
}
$double = new Multiplier();
$double(5); // 10 — __invoke 호출됨
매직 메서드는 객체 동작을 커스터마이즈하는 중요한 PHP 기능이며, 이를 이해하는 것은 적절히 사용하는 데뿐 아니라 — 특히 — PHP 프레임워크가 "마법"을 어떻게 달성하는지 이해하는 데 가치가 있습니다. __get/__set(동적 프로퍼티 접근), __call/__callStatic(동적 메서드 처리), __toString(문자열 변환), __invoke(호출 가능한 객체) 같은 메서드는 객체가 명시적으로 정의하지 않은 동작에 지능적으로 응답하게 합니다.
이것이 많은 프레임워크 편의 기능의 메커니즘입니다. Laravel의 Eloquent ORM은 모델 속성에 __get/__set을 사용하고, 쿼리 빌더와 파사드는 유연한 동적 메서드에 __call/__callStatic을 사용하며, 설정/컬렉션 객체는 이들을 전반에 걸쳐 사용합니다.
매직 메서드를 인식하면 이 프레임워크들이 어떻게 동작하는지 명확해지고 유사하게 유연한 API를 구축할 수 있습니다.
주요 매직 메서드, 각각을 트리거하는 것, 그리고 일반적인 프레임워크 용례를 아는 것은 표현력 있는 PHP를 작성하고 그 위에 구축된 프레임워크를 효과적으로 사용/확장하는 데 모두 실용적인 지식입니다. (주의: 매직 메서드는 명확성과 IDE 지원을 해칠 수 있으므로 — 남용하면 코드를 이해하기 어렵게 만듭니다. 기본값이 아닌 진정한 동적 동작에 신중하게 사용하는 것이 좋습니다.)