Computer >> 컴퓨터 >  >> 프로그래밍 >> PHP

PHP 약한 맵(WeakMap)이란? 개념부터 실전 예제까지

약한 맵(WeakMap)은 PHP 8.0에서 새롭게 도입된 기능입니다. 캐시가 엔티티 클래스와 같은 객체를 참조할 때, 약한 맵을 활용하면 더 이상 필요하지 않은 객체를 손쉽게 제거할 수 있습니다. 일반적인 참조와 달리 WeakMap이 객체를 참고하더라도 해당 객체가 가비지 컬렉션 대상에서 제외되지 않습니다. 따라서 PHP 8에서는 객체에 연관된 데이터를 자유롭게 저장하면서도 메모리 누수를 걱정하지 않아도 됩니다.

다시 말해, PHP 8의 약한 맵은 키(key)가 객체를 약한 참조(weak reference)로 가리키는 객체 모음입니다. WeakMap 클래스의 인스턴스는 객체를 키로 사용할 수 있으며, 해당 객체를 참조하는 곳이 하나도 남지 않으면 맵 안의 항목 역시 자동으로 제거됩니다. 장시간 실행되는 프로세스에서 메모리 누수를 예방하여 전체적인 성능 향상으로 이어집니다.

약한 맵은 일종의 자동 가비지 컬렉션 메커니즘이라고 볼 수 있습니다. 변수가 삭제될 때마다 PHP는 다른 변수가 아직 그 객체를 참조 중인지 검사합니다. 더 이상 참조하는 변수가 없다면 PHP는 해당 객체를 안전하게 삭제하며, 이 과정을 가비지 컬렉션(garbage collection)이라고 부릅니다.

예제: PHP 8의 약한 맵(WeakMap)

<?php
    class WeakExample {
        public WeakMap $cache;
        public function __construct() {
            $this->cache = new WeakMap();
        }
        public function getCaching(object $obj) {
            return $this->cache[$obj] ??= $this->computeSomethingExpensive($obj);
        }
        public function computeSomethingExpensive(object $obj) {
            print_r("Object called");
            return rand(1, 100);
        }
    }
    $cacheObject = new stdClass;
    $obj = new WeakExample;

    $obj->getCaching($cacheObject);
    $obj->getCaching($cacheObject);
    print_r(count($obj->cache));

    unset($cacheObject); // 객체를 해제하면 약한 맵의 항목도 함께 정리되어 메모리가 확보됨
    print_r(count($obj->cache));
?>

실행 결과

Object called 1 0

결과 해석

getCaching() 메서드를 두 번 호출했지만 "Object called" 문구는 한 번만 출력됩니다. 첫 번째 호출에서 비용이 큰 연산 결과가 캐시에 저장되었고, 두 번째 호출에서는 계산을 반복하지 않고 캐시된 값을 재사용했기 때문입니다.

또한 $cacheObjectunset()하기 전에는 맵의 요소 수가 1이었지만, 해제 후에는 0으로 줄어듭니다. 이는 객체를 참조하는 외부 변수가 사라지자 약한 맵의 항목도 함께 정리되었다는 의미로, WeakMap이 메모리 누수 없이 캐시를 자동으로 관리한다는 점을 잘 보여주는 예시입니다.