ELK Stack에서 Object 리스트 인덱싱 누락 문제 해결기

Dev Smile·2025년 7월 27일
1
post-thumbnail

ELK Stack(Elasticsearch/Logstash/Kibana)을 운영하다 보면 예상치 못한 데이터 인덱싱 문제에 부딪히곤 합니다. 최근 properties.values 필드에 객체(Object) 리스트가 들어올 때 데이터가 누락되는 현상을 겪었습니다. 오늘은 이 문제의 원인부터 해결 과정까지 자세히 공유해 보겠습니다.


문제 상황: 데이터가 누락되다

특정 로그 데이터가 Kibana에서 보이지 않는 문제가 발생했습니다. 문제가 된 데이터 구조는 아래와 같이 values 필드에 여러 객체를 담고 있는 형태였습니다.

// 문제가 되는 데이터 구조
{
  "properties": {
    "values": [
      {"bpm": 80, "time": "2025-07-21T18:12:50.542801"},
      {"bpm": 120, "time": "2025-07-21T18:12:50.542801"}
    ]
  }
}

데이터 형식을 변경하는 중에, 어느 순간부터 인덱싱이 되지 않고 있었습니다.


원인 분석: 동적 매핑의 함정

원인은 Elasticsearch의 동적 매핑(Dynamic Mapping) 기능에 있었습니다. Elasticsearch는 필드에 처음 들어온 데이터의 타입을 보고 자동으로 매핑을 결정합니다.

  1. 성공했던 인덱스: values 필드에 객체 리스트가 먼저 들어오면서, 해당 필드가 object 타입으로 정상 매핑되었습니다.
  2. 실패한 인덱스: values 필드에 숫자 리스트([80, 120]과 같은)가 먼저 들어오면서, 필드가 long 타입으로 매핑되어 버렸습니다.

실제 인덱스 매핑을 GET panic-digital-phenotype-logs-*/_mapping 명령어로 확인해보니 두 인덱스의 values 필드 타입이 다른 것을 발견할 수 있었습니다.

// 성공했던 인덱스 (2025.07.21)
"values": {
  "properties": {
    "bpm": { "type": "long" },
    "time": { "type": "text" }
  }
}

// 실패하는 인덱스 (2025.07.22)
"values": {
  "type": "long"
}

long 타입으로 매핑된 필드에는 객체 리스트가 들어올 수 없으니, 데이터가 누락될 수밖에 없었던 것입니다.


해결 방법: 템플릿으로 매핑 고정하기

이 문제를 해결하기 위해 Composable Index Template을 사용하여 values 필드의 매핑을 명시적으로 지정했습니다. 이렇게 하면 데이터가 어떤 순서로 들어오든 항상 의도한 대로 매핑이 적용됩니다.

1. Composable Index Template 설정

Elasticsearch 7.x 이상에서는 아래와 같이 템플릿을 설정하여 values 필드를 항상 object 타입으로 지정할 수 있습니다.

"template": {
  "mappings": {
    "properties": {
      "values": {
        "type": "nested", // 또는 "object"
        "properties": {
          "bpm": { "type": "long" },
          "time": { "type": "date" } // date 타입으로 변경하는 것을 권장
        }
      }
    }
  }
}

팁! 객체 배열을 다룰 때는 object보다 nested 타입을 사용하는 것이 각 객체를 독립적으로 쿼리할 수 있어 더 유리합니다. 또한 time 필드는 text보다 date 타입으로 매핑하는 것이 시간 기반 검색 및 분석에 효율적입니다.

2. 기존 인덱스 삭제 또는 Rollover

인덱스 템플릿은 새로 생성되는 인덱스에만 적용됩니다. 이미 잘못된 매핑으로 생성된 인덱스에는 소용이 없죠. 따라서 기존의 잘못된 인덱스를 삭제하거나 Rollover를 통해 새 인덱스를 만들어야 합니다.

DELETE panic-digital-phenotype-logs-2025.07.22

이후 데이터가 들어와 새 인덱스가 생성되면, 우리가 템플릿에 정의한 매핑이 올바르게 적용됩니다.

3. 데이터 구조 일관성 유지

가장 중요한 것은 애플리케이션(Logger) 단에서 전송하는 데이터의 구조를 일관되게 유지하는 것입니다. values 필드에는 항상 객체 리스트 형태만 보내도록 통일해야 매핑 충돌을 근본적으로 방지할 수 있습니다.


실전 점검 체크리스트

템플릿 적용 후에도 문제가 해결되지 않는다면 아래 사항들을 순서대로 점검해 보세요.

  • 템플릿 적용 후 새 인덱스에서 테스트: 템플릿이 잘 적용되었는지 새 인덱스의 매핑을 직접 확인하세요.
  • 기존 인덱스 삭제 또는 Rollover: 문제가 된 인덱스가 삭제되었는지 확인하세요.
  • 실제 전송 데이터 구조 확인: 애플리케이션에서 보내는 데이터가 의도한 구조와 일치하는지 다시 한번 검증하세요.
  • Logstash 파이프라인 확인: Logstash 필터(e.g., drop, mutate)에서 데이터를 변경하거나 누락시키고 있지는 않은지 확인하세요.
  • Elasticsearch 인덱스 매핑 재확인: 최종적으로 데이터가 저장된 인덱스의 매핑이 올바른지 확인하세요.

결론

Elasticsearch의 동적 매핑은 편리하지만, 다양한 형태의 데이터가 하나의 필드로 들어올 경우 예기치 않은 문제를 일으킬 수 있습니다. Composable Index Template을 사용해 필드 매핑을 명시적으로 고정하고, 데이터 구조를 일관되게 유지하는 것이 안정적인 ELK 스택 운영의 핵심입니다.

0개의 댓글