콘텐츠로 건너뛰기
Telemetry
문서 찾아보기
가이드업데이트된 2026년 7월 30일Telemetry 편집 및 제품 팀의 검토5 최소 읽기

코딩 에이전트와 함께 이 문서를 사용하세요.

Claude Code, Codex, Cursor 또는 다른 코딩 에이전트에 대한 집중 프롬프트 팩을 연 다음 여기에서 다루는 워크플로에 맞게 조정하세요.

이 페이지에서
  1. 이 패턴이 맞을 때
  2. 클라이언트 계약 정의
  3. 애플리케이션 소유 엔드포인트 구현
  4. 4개의 서버 측 컨트롤 적용
  5. 인증하다
  6. 허용 목록
  7. 비율 제한
  8. 신뢰할 수 있는 컨텍스트 추가
  9. 모바일 전송 동작 선택
  10. 결과 쿼리 및 확인
  11. 계획해야 할 실패 모드
  12. 주요 참고문헌

보안 모바일 Telemetry 프록시

모바일 애플리케이션은 귀하가 제어하지 않는 장치에 배포됩니다. React Native 번들, Swift 앱, Kotlin 앱 또는 Flutter 바이너리로 컴파일된 모든 항목을 최종적으로 검사할 수 있습니다. 앱에 Telemetry API 키, 앱에 전달된 원격 구성 값 또는 클라이언트가 읽을 수 있는 환경 파일을 제공하지 마세요.

대신, 애플리케이션이 소유한 인증된 엔드포인트에 작은 이벤트를 보내세요. 해당 엔드포인트는 고정 계약의 유효성을 검사하고, 신뢰할 수 있는 서버 컨텍스트를 추가하고, 서버 측 키를 사용하여 이벤트를 전달합니다.

Telemetry 이전에 인증, 허용 목록 작성 및 속도 제한이 포함된 애플리케이션 API를 통한 모바일 앱의 개념적 모바일 텔레메트리 흐름

모바일 앱은 Telemetry 수집 키를 수신하지 않습니다. API는 인증, 검증, 샘플링 및 전달을 소유합니다.

이 패턴이 맞을 때

제품 이정표, 제한된 성능 측정, 동기화 결과, 제어된 오류 범주 및 릴리스 품질 신호를 위해 모바일 프록시를 사용하세요. 예는 다음과 같습니다:

  • 로컬-서버 동기화가 터미널 결과에 도달한 후 mobile_sync_completed.
  • mobile_screen_ready는 명명된 화면과 측정된 지속 시간의 작은 집합입니다.
  • 서버가 내구성 있는 결과를 확인한 후 mobile_purchase_flow_completed입니다.
  • 샘플링되고 분류된 종속성 결과에 대한 mobile_api_request_completed입니다.

이는 충돌 기호화, 장치 로그, 분산 추적 또는 정확한 감사 원장을 대체하지 않습니다. 모바일 전송은 연결, 백그라운드 실행 제한, 앱 종료, 동의 및 클라이언트 시계 품질의 영향을 받습니다. 전문가 시스템에 전문가 진단을 유지하고 SQL 분석에 필요한 결과만 보냅니다.

클라이언트 계약 정의

클라이언트는 버전이 지정된 이벤트 이름 및 필드 목록에서 선택해야 합니다. Telemetry 테이블 이름을 선택하거나 임의의 속성 모음을 보내거나 예외 메시지를 전달해서는 안 됩니다.

{
  "event_name": "mobile_sync_completed",
  "event_version": 1,
  "event_id": "0196f37e-6e83-7b75-9d04-6b8283b35f74",
  "occurred_at": "2026-07-30T18:42:11.150Z",
  "status": "success",
  "duration_ms": 842,
  "item_count": 12,
  "network_type": "wifi"
}

치수를 제한적으로 유지하세요. 원시 경로보다는 제어된 screen_name를, 예외 문자열보다는 error_type 열거형을, 네트워크 식별자보다는 대략적인 network_type를 선호합니다. 액세스 토큰, 장치 광고 식별자, 연락처 데이터, 메시지 내용, 파일 경로, 클립보드 데이터, 자유 형식 검색 텍스트 또는 원시 URL을 포함하지 마십시오.

event_id는 재시도 중복 제거를 지원합니다. occurred_at는 클라이언트 관찰을 기록하지만 프록시는 서버에서 수신한 타임스탬프도 추가해야 합니다. 장치 시계가 잘못될 수 있으므로 신선도 및 수집 모니터링을 위해 서버 타임스탬프를 사용하세요.

애플리케이션 소유 엔드포인트 구현

다음 TypeScript 스케치는 경계를 보여줍니다. API에서 이미 사용하고 있는 프레임워크에 인증 및 속도 제한을 적용하세요.

const allowedEvents = {
  mobile_sync_completed: {
    statuses: new Set(["success", "failed", "cancelled"]),
    maximumDurationMs: 300_000,
    maximumItemCount: 10_000,
  },
} as const;

export async function postMobileTelemetry(request: Request) {
  const actor = await authenticateApplicationRequest(request);
  if (!actor) return new Response("unauthorized", { status: 401 });

  await enforceRateLimit({
    accountId: actor.accountId,
    deviceSessionId: actor.deviceSessionId,
  });

  const body = await readBoundedJson(request, { maximumBytes: 4096 });
  const policy = allowedEvents[body.event_name as keyof typeof allowedEvents];

  if (
    !policy ||
    body.event_version !== 1 ||
    !isUuid(body.event_id) ||
    !policy.statuses.has(body.status) ||
    !isIntegerInRange(body.duration_ms, 0, policy.maximumDurationMs) ||
    !isIntegerInRange(body.item_count, 0, policy.maximumItemCount)
  ) {
    return new Response("invalid event", { status: 422 });
  }

  await telemetry.log("mobile_sync_completed", {
    event_id: body.event_id,
    event_version: 1,
    occurred_at: parseBoundedClientTimestamp(body.occurred_at),
    received_at: new Date().toISOString(),
    status: body.status,
    duration_ms: body.duration_ms,
    item_count: body.item_count,
    network_type: normalizeNetworkType(body.network_type),
    account_id: actor.accountId,
    app_platform: actor.platform,
    app_version: actor.appVersion,
    environment: process.env.APP_ENV ?? "development",
  });

  return new Response(null, { status: 202 });
}

API는 Telemetry 이벤트 이름을 결정합니다. 클라이언트로부터 해당 값을 받아들이는 대신 신뢰할 수 있는 서버 상태에서 ID, 플랫폼, 환경 및 모든 권한 부여 컨텍스트를 파생합니다. 엔드포인트가 둘 이상의 이벤트를 지원하는 경우 모든 이벤트에 독립적인 스키마와 테스트 픽스처를 제공하십시오.

4개의 서버 측 컨트롤 적용

인증하다

나머지 API에서 사용하는 것과 동일한 서명된 애플리케이션 세션 또는 설치 자격 증명이 필요합니다. CORS는 모바일 보안 경계가 아니며 사용자 정의 헤더만으로는 누가 요청을 보냈는지 증명할 수 없습니다.

허용 목록

알 수 없는 이벤트 이름, 필드, 열거형 값, 너무 큰 문자열, 잘못된 숫자, 향후 타임스탬프 및 작은 크기 제한을 초과하는 본문을 거부합니다. 허용 목록은 개인정보 보호 제어이자 카디널리티 제어입니다.

비율 제한

인증된 계정과 적절한 설치 또는 세션 식별자로 제한됩니다. 또한 전역 상한선을 부과합니다. 클라이언트가 제한을 초과하면 무기한 재시도하지 않고 일반 애플리케이션 오류를 반환합니다.

신뢰할 수 있는 컨텍스트 추가

프록시는 해당 값을 사용할 수 있는 경우 계정 식별자, 서버 수신 시간, 환경 및 확인된 애플리케이션 버전을 추가해야 합니다. 계정 식별자가 귀하의 상황에서 민감한 경우 수집하기 전에 이를 일관성 있게 가명화하고 매핑을 되돌릴 수 있는 사람을 문서화하십시오.

모바일 전송 동작 선택

React Native 및 Flutter의 경우 이미 인증된 API 요청을 담당하는 플랫폼 HTTP 클라이언트를 사용하세요. 기본 iOS 및 Android의 경우 앱에서 사용하는 것과 동일한 URLSession 또는 HTTP 스택을 사용하세요. 엔드포인트와 이벤트 계약은 플랫폼 전반에서 동일하게 유지되어야 합니다.

오프라인 전달이 중요한 경우 소규모의 제한된 대기열을 유지하세요. 항목 수와 기간을 모두 제한하고, 문서화된 창을 초과한 이벤트를 삭제하고, 지터와 함께 지수 백오프를 사용합니다. 분석 재시도로 인해 제품 작업이 지연되지 않도록 하십시오. 서버가 중복을 제거할 수 있도록 시도 전반에 걸쳐 동일한 event_id를 보존합니다.

일부 결과는 서버에서 더 잘 방출됩니다. 구매, 구독 변경, 액세스 정책 결정 또는 완료된 가져오기는 백엔드가 커밋한 후에만 권한이 부여됩니다. 클라이언트 어설션을 신뢰하는 대신 서버가 해당 결과를 직접 내보내도록 합니다.

결과 쿼리 및 확인

하나의 합성 성공, 실패, 취소, 잘못된 페이로드, 인증되지 않은 요청, 속도 제한 버스트, 오프라인 재시도 및 중복 event_id를 보냅니다. 그런 다음 제한된 샘플을 검사합니다.

SELECT
  received_at,
  event_id,
  app_platform,
  app_version,
  status,
  duration_ms,
  item_count
FROM mobile_sync_completed
ORDER BY received_at DESC
LIMIT 50;

출시 전에 다음을 확인하세요.

  1. 배송된 애플리케이션 바이너리와 JavaScript 번들에는 Telemetry API 키가 포함되어 있지 않습니다.
  2. 알 수 없는 이벤트 및 필드는 자동으로 전달되지 않고 거부됩니다.
  3. 원시 예외 텍스트, URL, 사용자 입력, 자격 증명 및 장치 식별자가 없습니다.
  4. 재시도에서는 하나의 event_id가 유지되며, 중복 전송으로 인해 결과 수가 늘어나지 않습니다.
  5. 대시보드에는 요율 및 백분위수 옆에 샘플 수가 표시됩니다.
  6. 동의, 보유, 삭제, 계정 삭제 동작은 애플리케이션 정책과 일치합니다.

계획해야 할 실패 모드

이벤트가 별도로 설계된 내구성 있는 비즈니스 워크플로의 일부가 아닌 한 프록시를 최선의 옵저버빌리티으로 취급합니다. Telemetry 시간 초과는 일반적으로 모바일 제품 작업 실패 없이 기록되고 제한되어야 합니다. 프록시 거부율, 전달 실패, 대기열 수명 및 이벤트 최신성을 모니터링하여 자동 계측 중단이 제품 사용량 감소로 보이지 않도록 합니다.

"디버깅을 더 쉽게 만들기" 위해 임의의 클라이언트 이벤트를 자동으로 수락하지 마세요. 그러면 엔드포인트가 감사되지 않은 데이터 수집 표면으로 전환됩니다. 목적, 유형, 카디널리티, 개인 정보 분류 및 삭제 요구 사항을 검토한 후에만 새 버전이 지정된 필드 또는 이벤트를 추가하세요.

주요 참고문헌

관련 제품 기능

안정적인 이벤트 이름, 타입이 지정된 필드, 개인 정보 보호 검토 컨텍스트를 캡처합니다.

소유권 및 기술 참조

이 설명은 Telemetry 편집팀의 소유입니다. 제품 팀은 동작, 예시, 경계를 검토합니다.

편집 기준 검토