Lighthouse 구체적 개발 및 수정 내용

Category
OpenSource
Status
Published
Tags
OpenSource
Lighthouse
Description
Published
Slug

Set 자료형 활용

기존 코드에서는 배열 기반 단순 처리를 사용했지만, 해당 기여에서는 Set을 전략적으로 활용
// Before: 기존 방식 (배열 기반) function getActionableFailureReasons(failureCode, unsupportedProperties) { return ACTIONABLE_FAILURE_REASONS .filter(reason => failureCode & reason.flag) .map(reason => { if (reason.text === UIStrings.unsupportedCSSProperty) { return str_(reason.text, { propertyCount: unsupportedProperties.length, properties: unsupportedProperties.join(', '), }); } return str_(reason.text); }); } // After: Set 기반 분리 로직 function getActionableFailureReasons(failureCode, unsupportedProperties) { return ACTIONABLE_FAILURE_REASONS .filter(reason => failureCode & reason.flag) .map(reason => { if (reason.text === UIStrings.unsupportedCSSProperty) { const customProperties = new Set(); const nonCustomProperties = new Set(); // O(n) 단일 패스 분류 for (const property of unsupportedProperties) { if (property.startsWith('--')) { customProperties.add(property); } else { nonCustomProperties.add(property); } } const reasons = []; if (nonCustomProperties.size > 0) { reasons.push(str_(UIStrings.unsupportedCSSProperty, { propertyCount: nonCustomProperties.size, properties: Array.from(nonCustomProperties).join(', '), })); } if (customProperties.size > 0) { reasons.push(str_(UIStrings.unsupportedCustomCSSProperty, { propertyCount: customProperties.size, properties: Array.from(customProperties).join(', '), })); } return reasons; } return str_(reason.text); }) .flat(); }
 

Set 자료형 선택 이유

1. 중복 제거 보장
// 예시: 중복된 속성이 들어온 경우 const properties = ['color', '--var', 'color', '--var']; // Array 방식: 중복 허용 const arrayResult = ['color', '--var', 'color', '--var']; // Set 방식: 자동 중복 제거 const setResult = new Set(properties); // {'color', '--var'}
 
2. 성능 최적화
// Array.includes(): O(n) 시간복잡도 if (processedProperties.includes(property)) { // 중복 확인에 linear search 필요 } // Set.has(): O(1) 시간복잡도 if (processedProperties.has(property)) { // 해시 테이블 기반 상수시간 검색 }
 
3. 메모리 효율성
// Array 방식: 중복 저장으로 메모리 낭비 가능 const duplicatedArray = ['--var1', '--var1', '--var1']; // 3개 저장 // Set 방식: 유니크 값만 저장 const uniqueSet = new Set(['--var1', '--var1', '--var1']); // 1개만 저장

실제 데이터 처리 예시

입력 데이터
unsupportedProperties: ['--swing-y', '--rotation', 'color', 'height', 'color'] // ↑ 중복
Set 기반 분류 과정
// 1단계: Set 초기화 const customProperties = new Set(); // {} const nonCustomProperties = new Set(); // {} // 2단계: 순차 처리 // property = '--swing-y' if ('--swing-y'.startsWith('--')) { customProperties.add('--swing-y'); // {'--swing-y'} } // property = '--rotation' customProperties.add('--rotation'); // {'--swing-y', '--rotation'} // property = 'color' nonCustomProperties.add('color'); // {'color'} // property = 'height' nonCustomProperties.add('height'); // {'color', 'height'} // property = 'color' (중복) nonCustomProperties.add('color'); // {'color', 'height'} - 중복 무시됨 // 3단계: 결과 생성 // customProperties.size = 2 // nonCustomProperties.size = 2
최종 출력
[ "Unsupported CSS Properties: color, height", "Custom CSS properties cannot be animated on the compositor: --swing-y, --rotation" ]
 

 

비트마스킹 시스템

Chrome의 Failure Reason 시스템

Chrome 내부에서는 compositor 실패 원인을 비트 플래그로 관리
// Chromium source: compositor_animations.h enum FailureReason { kUnsupportedCSSProperty = 1 << 13, // 8192 kTransformRelatedPropertyDependsOnBoxSize = 1 << 11, // 2048 kFilterRelatedPropertyMayMovePixels = 1 << 12, // 4096 kNonReplaceCompositeMode = 1 << 4, // 16 kIncompatibleAnimations = 1 << 6, // 64 kUnsupportedTimingParameters = 1 << 3, // 8 };

JavaScript에서의 비트마스킹 구현

const ACTIONABLE_FAILURE_REASONS = [ {flag: 1 << 13, text: UIStrings.unsupportedCSSProperty}, // 8192 {flag: 1 << 11, text: UIStrings.transformDependsBoxSize}, // 2048 {flag: 1 << 12, text: UIStrings.filterMayMovePixels}, // 4096 // ... ]; // 실제 사용: 비트 AND 연산으로 해당 실패 원인 확인 function checkFailureReason(failureCode, targetFlag) { return (failureCode & targetFlag) !== 0; } // 예시: failureCode = 10240 (8192 + 2048) checkFailureReason(10240, 8192); // true - unsupported CSS property checkFailureReason(10240, 2048); // true - transform depends box size checkFailureReason(10240, 4096); // false - filter may move pixels

내 코드에서의 활용

// 실제 구현에서 비트마스킹 활용 return ACTIONABLE_FAILURE_REASONS .filter(reason => failureCode & reason.flag) // 해당하는 실패 원인만 필터링 .map(reason => { // 각 실패 원인별 메시지 생성 로직 });
 

i18n 시스템 활용

ICU MessageFormat 구문

// 추가한 새로운 UI 문자열 unsupportedCustomCSSProperty: `{propertyCount, plural, =1 {Custom CSS properties cannot be animated on the compositor: {properties}} other {Custom CSS properties cannot be animated on the compositor: {properties}} }`,
  • {propertyCount, plural, ...}: 숫자에 따른 복수형 처리
  • =1 {...}: 정확히 1개일 때의 메시지
  • other {...}: 그 외 모든 경우 (0, 2, 3, ...)
  • {properties}: 동적 변수 삽입
 

렌더링 과정

// 런타임에서 메시지 생성 과정 str_(UIStrings.unsupportedCustomCSSProperty, { propertyCount: 2, properties: "--swing-y, --rotation" }); // ICU 엔진 내부 처리: // 1. propertyCount = 2 → "other" 브랜치 선택 // 2. {properties} → "--swing-y, --rotation" 치환 // 결과: "Custom CSS properties cannot be animated on the compositor: --swing-y, --rotation"

다국어 지원 메커니즘

// 빌드 시점에 자동 추출되는 다국어 파일 구조 // shared/localization/locales/ko.json { "core/audits/non-composited-animations.js | unsupportedCustomCSSProperty": { "message": "커스텀 CSS 속성은 컴포지터에서 애니메이션할 수 없습니다: {properties}" } }