타입 안전한 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에서 동일한 기능 구현:
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) |
|----------|----------------|----------------|------------------------|
| 정상 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 |
| 타입 강제 변환 | 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
아직 댓글이 없습니다.