민감한 트레이스 데이터 마스킹

민감한 트레이스 데이터 마스킹 (Mask Sensitive Trace Data)

마스킹 기능으로 트레이스의 민감한 정보를 보호하는 방법을 다루는 페이지예요. 트레이스가 관측소로 보내지기 전에 민감한 데이터를 자동으로 삭제하거나 변환해줘요. 보안과 GDPR·HIPAA·CCPA 같은 규제 준수 모두를 위한 핵심 기능이랍니다.

출처: 문서

본문

개요 (Overview)

마스킹(Masking)은 트레이스가 관측소(observatory)로 보내지기 전에 민감한 데이터를 자동으로 삭제(redact)하거나 변환할 수 있게 해줘요. 마스킹이 중요한 이유는 여러 가지예요:

  • 보안(Security): 자격증명이나 민감한 비즈니스 데이터의 노출을 방지해요
  • 규제 준수(Regulatory Compliance): GDPR, HIPAA, CCPA 같은 요구사항을 충족해요

기본적으로 confident-trace는 스팬의 전체 콘텐츠 — 프롬프트, 완성(completion), 툴 인자, 검색 청크, 업데이트 헬퍼로 설정한 모든 것 — 를 캡처해요. 그 콘텐츠에 PII가 들어갈 수 있다면, 모두 init()에서 한 번에 구성하는 세 가지 컨트롤이 있어요:

Control Python init() TypeScript init() What it does
Disable capture capture_content captureContent Turn content capture off entirely — keep timing, status, model, and usage
Redact redact redact Run your own masking function over every content value before export
Size limit max_content_bytes maxContentBytes Optionally cap the size of each content attribute (disabled by default)

이 컨트롤들은 confident-trace 자체가 관리하는 콘텐츠에 적용돼요 — 즉 통합에서 만든 스팬과 update_span() / update_trace()로 설정한 것들이죠. 네이티브 프레임워크 계측과 서드파티 OpenTelemetry 계측기는 자체 콘텐츠 정책을 유지하므로, 그걸 쓴다면 별도로 확인하세요.

마스킹 구성하기 (Configure Masking)

마스킹을 구현하려면 마스킹 함수를 정의하고 init()에 redact로 전달하면 돼요. 이 함수는 직렬화 직전에 모든 콘텐츠 값에 실행되므로, 민감한 것이 프로세스를 떠나지 않아요.

Python

import re
from confident_trace import init, span, shutdown

def masking_function(data):
    if isinstance(data, str):
        return re.sub(r'\b(?:\d{4}[- ]?){3}\d{4}\b', '[REDACTED CARD]', data)
    if isinstance(data, list):
        return [masking_function(item) for item in data]
    if isinstance(data, dict):
        return {k: masking_function(v) for k, v in data.items()}
    return data

init(redact=masking_function)

@span(type="agent")
def llm_app(query: str):
    return "4242-4242-4242-4242"

try:
    llm_app("Test Masking")
finally:
    shutdown()

TypeScript

import { init, span } from "confident-trace";

const maskingFunction = (data: unknown): unknown => {
  if (typeof data === "string")
    return data.replace(/\b(?:\d{4}[- ]?){3}\d{4}\b/g, "[REDACTED CARD]");
  if (Array.isArray(data)) return data.map(maskingFunction);
  if (data && typeof data === "object") {
    return Object.fromEntries(Object.entries(data).map(([k, v]) => [k, maskingFunction(v)]));
  }
  return data;
};

const runtime = init({ redact: maskingFunction });

const llmApp = span({ name: "llm_app", type: "agent" }, (query: string) => {
  return "4242-4242-4242-4242";
});

try {
  llmApp("Test Masking");
} finally {
  await runtime.shutdown();
}

통합 스팬도 마스킹되도록 Node preload로 진입점을 실행하는 걸 잊지 마세요.

마스킹 함수는 자동으로 적용돼요:

  1. 스팬 I/O: 모든 스팬의 캡처된 입력과 출력 — 함수 인자와 반환값뿐 아니라 통합이 기록한 메시지와 완성까지
  2. 업데이트 헬퍼 필드: update_span() / update_trace()로 설정한 것 — 예: input, output, retrieval_context, metadata

마스킹 함수가 입력·출력·헬퍼 필드 모두에 적용되므로, 받을 수 있는 여러 데이터 타입 — 문자열, 리스트, 딕셔너리 등 — 을 처리하고 같은 형태로 반환해야 해요. 이 페이지의 예시는 리스트·딕셔너리를 재귀적으로 순회하고 다른 타입은 그대로 통과시켜요.

콘텐츠 캡처 끄기 (Disable Content Capture)

프롬프트와 완성을 아예 내보내고 싶지 않다면 — 예를 들어 마스킹으로 부족한 규제 환경에서 — 콘텐츠 캡처를 끄면 돼요. 그래도 타이밍, 상태, 스팬 계층, 모델·토큰 사용량 속성은 얻으므로 비용 추적과 지연 모니터링은 계속 동작해요. 단지 콘텐츠 필드만 빠질 뿐이죠.

Python

from confident_trace import init

init(capture_content=False)

TypeScript

import { init } from "confident-trace";

const runtime = init({ captureContent: false });

단일 스팬에 대해서도 그 스팬의 옵션에서 capture_content=False / captureContent: false로 캡처를 끌 수 있어요. 파이프라인의 한 단계만 민감한 데이터를 다룰 때 유용하죠.

콘텐츠 컨트롤은 confident-trace가 관리하는 콘텐츠만 규율해요. 직접 붙이는 원시 OpenTelemetry 속성은 이것을 완전히 우회하므로 거기에 민감한 값을 넣지 마세요. 완전한 탈퇴를 원한다면 모든 것을 삭제하려고 하기보다 캡처를 끄는 쪽을 선호해요.

크기 제한 (Size Limits)

콘텐츠 크기 제한은 기본적으로 꺼져 있어요. 별도로 구성하지 않으면 confident-trace는 콘텐츠 속성을 제한하지 않아요.

max_content_bytes / maxContentBytes를 설정하면 제한이 활성화돼요. 제한을 넘는 값은 잘리거나 생략되고, 채팅 메시지 배열은 가능하면 유효하고 경계가 있는 접두사를 유지해서 스팬이 계속 렌더링되도록 해요. 스트리밍 출력도 같은 방식으로 제한되고 잘림(truncated) 표시되는 반면, 토큰 사용량은 계속 추적돼요:

Python

from confident_trace import init

init(max_content_bytes=8192)

TypeScript

import { init } from "confident-trace";

init({ maxContentBytes: 8192 });

이 제한은 내보내는 것에 적용되며, 애플리케이션이나 프레임워크가 메모리에 유지하는 버퍼에는 적용되지 않아요. Vercel AI SDK를 자동 모드로 사용한다면 captureContent: false가 recordInputs와 recordOutputs도 false로 설정해줘요. 수동 모드에서는 두 플래그를 직접 꺼야 해요.

다음 단계 (Next Steps)

민감한 데이터를 마스킹했다면, 어떤 트레이스를 보낼 것인지부터 제어해요.

Sample Traces

트래픽이 많은 앱에서 볼륨과 비용을 관리하려고 일정 비율의 트레이스만 Confident AI로 보내요.

Drop Traces

헬스 체크, 내부 테스트 요청, 그리고 Observatory에 넣고 싶지 않은 기타 노이즈에 대해 트레이싱을 아예 건너뛰어요.

더 알아보기

  • Trace Sampling — 비율 기반으로 트레이스 볼륨을 제어해요.
  • Dropping Traces — 런타임 조건에 따라 트레이스를 조건부로 제외해요.