홈으로 돌아가기

타입 안전한 PHP 배열: +4x 속도

이 기사는 sbwerewolf/language-specific 라이브러리의 최적화를 분석합니다: 4x 속도 향상, wplake/typed와 비교. 벤치마크, 체이너블 API 코드 예제, 불변성과 같은 새로운 기능이 제공됩니다.

PHP: 타입 안전한 배열 4배 빠름
Advertisement 728x90

타입 안전한 PHP 배열: 가독성은 그대로 두고 속도 4배 향상

sbwerewolf/language-specific 라이브러리 버전 10.4.5는 이전 버전 8.4.1 대비 4배의 성능 향상을 달성했습니다. 한편, wplake/typed(1.2.2)와의 성능 격차는 이제 단 2배로 좁혀졌습니다. 전자는 문자열 기반 경로를 사용하고, 후자는 중첩된 데이터 구조 탐색을 위해 메서드 체이닝을 활용합니다.

wplake/typed를 사용한 예시:

use Wplake\Typed\Typed;

$response = file_get_contents(
    'https://geocode-maps.yandex.ru/1.x/?apikey=d3893dc1-c136-4084-b9c-4db26b00463e&geocode=Mohammed+Bin+Rashid+Boulevard+1&lang=en_US&format=json'
);

$object = json_decode(json: $response, associative: true, flags: JSON_THROW_ON_ERROR);

$path = 'response.GeoObjectCollection.featureMember.0.GeoObject.metaDataProperty.GeocoderMetaData.Address.formatted';

// 기본값을 지정한 값 추출
$val = Typed::string($object, $path, '주소를 찾을 수 없습니다');
var_dump($val);
/*
string(77)
"1, Mohammed Bin Rashid Boulevard, Downtown Dubai, Dubai, United Arab Emirates"
*/

$isReal = Typed::stringOrNull($object, $path) !== null;
var_dump($isReal);
/* bool(true) */

sbwerewolf/language-specific에서 동일한 기능 구현:

Google AdInline article slot
use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$response = file_get_contents('https://geocode-maps.yandex.ru/1.x/?apikey=d3893dc1-c136-4084-b9c-4db26b00463e&geocode=Mohammed+Bin+Rashid+Boulevard+1&lang=en_US&format=json');

$object = json_decode(json: $response, associative: true, flags: JSON_THROW_ON_ERROR);
$data = new AdvancedArrayFactory()->makeAdvancedArray($object);
$formatted = $data
    ->pull("response")
    ->pull("GeoObjectCollection")
    ->pull("featureMember")
    ->pull()
    ->pull("GeoObject")
    ->pull("metaDataProperty")
    ->pull("GeocoderMetaData")
    ->pull("Address")
    ->get("formatted")
    ->default("주소를 찾을 수 없습니다");
$val = $formatted->str();
var_dump($val);
/* 
string(77)
"1, Mohammed Bin Rashid Boulevard, Downtown Dubai, Dubai, United Arab Emirates"
*/
$isReal = $formatted->isReal();
var_dump($isReal);
/* bool(true) */

성능 벤치마크

벤치마크는 실제 운영 환경을 반영합니다: 정상적인 JSON 파싱, 누락된 경로 처리, 요소 존재 여부 확인, 타입 강제 변환, 원시 값 조회 등입니다.

| 사용 사례 | 8.4.1 (기존) | 10.4.5 (개선 후) | 1.2.2 (wplake/typed) |

|----------|----------------|----------------|------------------------|

Google AdInline article slot

| 정상 JSON 파싱 | 29.210 µs/op | 6.467 µs/op | 3.013 µs/op |

| 누락된 경로 처리 | 18.716 µs/op | 5.987 µs/op | 1.766 µs/op |

| 요소 존재 여부 확인 | 27.237 µs/op | 6.277 µs/op | 2.863 µs/op |

Google AdInline article slot

| 타입 강제 변환 | 28.581 µs/op | 6.740 µs/op | 2.966 µs/op |

| 원시 값 조회 | 30.395 µs/op | 6.558 µs/op | 3.015 µs/op |

| 모든 스칼라 값 일괄 추출 | 5.897 µs/op | 1.878 µs/op | 미지원 |

| 모든 배열 일괄 추출 | 7.136 µs/op | 2.431 µs/op | 미지원 |

10.4.5 신규 기능: wplake/typed에는 없는 모든 스칼라 및 배열 값 일괄 추출 기능이 추가되었습니다.

핵심 아키텍처 변경 사항

  • 불변 CommonValue: 기본값 설정 후에는 어떤 수정도 허용되지 않도록 불변성 보장.
  • 결정론적 pull(): 배열에서 요소를 추출할 때 항상 첫 번째 요소만 반환 — 비결정론적 동작 제거.
  • 단순화된 API: 보조 클래스 삭제; 로직을 하나의 유기적인 흐름으로 통합.

메이저 버전 업그레이드(8.4.1 → 10.4.5)로 인해 공식적으로 하위 호환성이 깨졌지만, 공개 API는 완전히 동일합니다. 기존 소비자 코드는 수정 없이 바로 사용 가능합니다.

새 메서드 및 기능

완전한 체이닝 가능한 메서드 목록:

  • pull(string $key) — 키를 기준으로 중첩된 요소 추출
  • pull() — 배열의 첫 번째 요소를 결정론적으로 추출
  • get(string $key) — 존재 여부를 검사하며 값 조회
  • default(mixed $fallback) — 누락 시 적용할 기본값 설정
  • str() — 문자열로 캐스팅
  • isReal() — 값의 존재 여부 확인

구조가 불안정한 API 응답을 처리할 때 복잡한 체이닝을 활용한 실용적 예시입니다.

왜 중요한가?

  • 기준 대비 4배 속도 향상, 현재 최고 성능 라이브러리보다는 단지 2배 느림.
  • 문자열 기반 경로의 취약성 없이, 메서드 체이닝의 직관적 가독성 유지.
  • wplake/typed에 없는 고유 기능: 모든 스칼라/배열 값 일괄 수집.
  • 불변성과 결정론성으로 신뢰성 및 테스트 용이성 향상.
  • 중급~고급 개발자에게 이상적: 타입 안전성과 프로덕션 수준의 성능을 동시에 제공.

— Editorial Team

Advertisement 728x90

다음 읽기