조용진의 개발 블로그
← 글 목록

Loki 라벨 카디널리티를 화이트리스트로 제어한 과정

Loki로깅관측성React Native

React Native 키오스크 로그의 배치 전송을 구성하고 고유값을 본문으로 분리해 Loki 라벨 카디널리티를 제한한 과정을 정리합니다.

키오스크 애플리케이션에서 Loki로 로그를 전송하기 시작했을 때는 로그에 포함된 메타데이터를 라벨에도 함께 넣었다. 검색에는 편리해 보이지만 요청 ID, 세션 ID, 장비 ID처럼 값의 종류가 계속 늘어나는 필드가 라벨이 되면 Loki의 스트림 수가 급격히 증가한다.

이를 막기 위해 검색 축으로 사용할 필드만 라벨로 허용하고, 나머지는 로그 본문 메타데이터로 유지하는 정책을 적용했다.

전송부터 끊김을 고려했다

React Native 키오스크 로거는 로그를 즉시 한 건씩 보내지 않고 버퍼에 모았다. 일정 건수를 묶어 주기적으로 전송했고 오류 로그는 빠른 확인을 위해 즉시 전송 대상으로 처리했다.

아래 코드 예시는 설명을 위해 식별자와 운영 설정값을 일반화했습니다.

this.config = {
  environment: currentEnvironment,
  enabled: true,
  batchSize: configuredBatchSize,
  flushInterval: configuredFlushInterval,
  ...options,
};
if (this.config.enabled) this.startFlushTimer();

네트워크가 불안정한 키오스크 환경에서 매 로그마다 요청을 보내는 비용을 줄이면서, 중요한 오류가 배치 주기만큼 늦어지지 않도록 한 절충이었다.

라벨과 본문 메타데이터를 나눴다

초기 구현처럼 메타데이터 전체를 라벨로 펼치면 값이 고유한 필드마다 새로운 스트림이 만들어질 수 있다. 이후 라벨 화이트리스트와 차단 목록을 두어 분류 기준을 코드로 고정했다.

for (const [key, value] of Object.entries(metadata)) {
  if (value == null) continue;
  if (EXCLUDED_FIELDS.includes(key)) continue;

  if (
    INDEXED_FIELDS.includes(key) &&
    (typeof value === 'string' ||
      typeof value === 'number' ||
      typeof value === 'boolean')
  ) {
    labels[key] = String(value);
  }
}

requestId, sessionId, socketId, deviceId 같은 값은 문제 추적에 필요하므로 삭제하지 않았다. 다만 Loki 인덱스의 라벨이 아니라 로그 메시지 안의 구조화된 메타데이터로 남겼다. timestamp도 Loki가 자체 시간을 보관하므로 호출부에서 중복으로 전달하던 값을 정리했다.

flowchart LR
    A[로그 메타데이터] --> B{라벨 화이트리스트}
    B -- 허용 --> C[Loki 라벨]
    B -- 미허용·고유값 --> D[로그 본문 JSON]
    C --> E[서비스·레벨·환경 검색]
    D --> F[요청·세션·장비 상세 추적]

공통 정보는 로거가 채우게 했다

각 호출부가 환경과 장비 정보를 반복해서 넣으면 필드 누락과 이름 차이가 생긴다. 로거가 stage, 가맹점 이름 같은 공통 값을 조합하고, 이후 장비 저장소의 정보를 연결해 다음 메타데이터를 일관되게 포함하도록 확장했다.

장비 정보가 아직 로드되지 않았거나 저장소 복구 중인 상황도 고려해 로깅 자체가 애플리케이션 오류로 이어지지 않게 했다.

결과

로그 스키마를 정비하면서 가장 중요했던 기준은 “검색하고 싶은 값은 모두 라벨”이 아니었다. 값의 종류가 제한적이고 반복 검색 축으로 쓰이는 필드만 라벨이어야 했다. 개별 요청이나 장비를 특정하는 고유값은 본문에 남겨도 LogQL의 JSON 파싱으로 조회할 수 있다.

이 구분으로 서비스·레벨·환경 같은 공통 조건은 라벨로 빠르게 좁히고, 요청·세션·장비 정보는 선택된 로그의 본문에서 추적하는 구조를 만들었다. 관측성을 높이면서도 Loki의 라벨 카디널리티가 불필요하게 커지는 위험을 코드 수준에서 제한한 작업이었다.