총 포그라운드 시간 계산

이 가이드에서는 사용자가 페이지를 적극적으로 보는 데 소요된 총 시간을 정확하게 계산하는 방법을 자세히 설명합니다. 페이지에 머문 시간과 같은 기존 측정항목에는 백그라운드에서 페이지에 머문 시간이 잘못 포함되는 경우가 많습니다. VisibilityStateEntry API를 사용하면 '포그라운드 시간'만 측정하여 사용자 참여도를 더 정확하게 파악할 수 있습니다.

포그라운드 시간 계산 구현

PerformanceTimeline API는 공개 상태 변경을 성능 항목으로 노출합니다. visibilitychange 이벤트에 반응하고 세션 전체에서 수동으로 시간을 누적하는 대신 언제든지 전체 공개 상태 기록을 쿼리할 수 있습니다.

필수: visibility-state 성능 항목을 쿼리하여 실제 포그라운드 시간을 계산해야 합니다.

/**
 * Calculates total time the page was in the visible state.
 *
 * @returns {number} Total foreground time in milliseconds.
 */
function getTotalForegroundTime() {
  // MANDATORY: Query the visibility-state entries from the performance timeline.
  const entries = performance.getEntriesByType('visibility-state');

  // Fallback: If the browser does not support VisibilityStateEntry,
  // the API will gracefully return an empty array.
  if (entries.length === 0) {
    // Return total time since navigation start as a fallback.
    return performance.now();
  }

  let totalForegroundTime = 0;

  for (let i = 0; i < entries.length; i++) {
    // Only calculate duration for periods where the state was 'visible'
    if (entries[i].name === 'visible') {
      const start = entries[i].startTime;

      // The end time is the start time of the next state change,
      // or the current time if this is the final entry.
      const end = i + 1 < entries.length
          ? entries[i + 1].startTime
          : performance.now();

      totalForegroundTime += (end - start);
    }
  }

  return totalForegroundTime;
}

대체 및 브라우저 지원

VisibilityStateEntry API는 Performance Timeline에 추가된 최신 기능이며 일부 브라우저에서는 지원되지 않을 수 있습니다.

지원되지 않는 브라우저에서는 performance.getEntriesByType('visibility-state')가 빈 배열을 반환하므로 기능 감지가 계산 흐름에 내장되어 있습니다. 계속하기 전에 항상 항목이 반환되는지 확인해야 합니다.

API가 지원되지 않는 경우 권장되는 대체 방법은 performance.now()를 반환하는 것입니다. 이는 탐색 이후의 총 시간을 나타내며, 공개 상태 기록을 사용할 수 없는 경우 참여 시간의 합리적인 상한선 역할을 합니다.

const entries = performance.getEntriesByType('visibility-state');

// If the array is empty, the API is likely unsupported.
if (entries.length === 0) {
  // Fallback: Return total time since page load.
  return performance.now();
}