Elasticsearch 매핑 폭발 방지 및 샤드 사이징 최적화 가이드 5가지

로그 데이터 양이 급증하면서 Elasticsearch 클러스터가 갑자기 느려지거나 Out of Memory(OOM) 에러로 중단되는 상황을 자주 겪습니다. 대부분의 원인은 통제되지 않은 필드 생성으로 인한 매핑 폭발(Mapping Explosion)과 잘못된 샤드(Shard) 설계에 있습니다.

이 가이드에서는 클러스터의 안정성을 보장하고 검색 속도를 유지하기 위한 매핑 관리 전략과 샤드 사이징 최적화 방법을 구체적으로 공유합니다.

TL;DR — dynamic: strict 설정으로 필드 생성을 통제하고, 인덱스당 샤드 크기를 20GB~50GB 사이로 유지하여 클러스터 리소스를 효율적으로 관리하세요.

1. 매핑 폭발(Mapping Explosion)의 위험성

💡 비유로 이해하기: 도서관에 새로운 책이 들어올 때마다 사서가 새로운 분류 카테고리를 무한정 만드는 상황입니다. 카테고리 목록(매핑)이 너무 커지면 사서는 책을 찾는 것보다 목록을 읽는 데 더 많은 시간을 쓰게 되고, 결국 머릿속(메모리)이 복잡해져 업무를 포기하게 됩니다.

매핑 폭발은 인덱스에 정의된 필드 수가 기하급수적으로 늘어나 클러스터 상태(Cluster State) 정보가 비대해지는 현상을 말합니다. 최신 버전 8.12.x 기준으로 Elasticsearch는 기본적으로 인덱스당 1,000개의 필드 제한을 두지만, 이 수치를 임의로 높이면 마스터 노드의 부하가 극심해집니다.

각 필드는 메모리 소비와 디스크 I/O에 영향을 줍니다. 특히 동적 매핑(Dynamic Mapping)이 활성화된 상태에서 비정형 로그가 유입되면, 의도치 않은 필드들이 계속 생성되어 결국 전체 클러스터의 가용성을 떨어뜨립니다.

2. 대용량 로그 클러스터에서 발생하는 문제 상황

애플리케이션 로그를 JSON 형태로 수집할 때, 개발자가 실수로 로그 구조를 중첩(Nested)시키거나 사용자 정의 필드를 수백 개 추가하는 경우가 발생합니다. 이 로그가 Elasticsearch로 들어오면 즉시 새로운 매핑이 생성됩니다.

또한 샤드 사이징을 고려하지 않고 인덱스를 생성하면 '오버샤딩(Oversharding)' 문제가 발생합니다. 너무 작은 샤드가 수천 개 존재하면 검색 시 모든 샤드에 쿼리를 분산해야 하므로 CPU 오버헤드가 커지고 힙 메모리가 부족해집니다.

3. 단계별 매핑 및 샤드 최적화 구현 가이드

사전에 정의된 템플릿을 사용하여 데이터 유입 단계부터 엄격하게 통제해야 합니다.

Step 1. 인덱스 템플릿 정의 및 동적 매핑 제한

새로운 필드가 임의로 추가되는 것을 막기 위해 dynamic 설정을 strict로 변경합니다.

PUT /_index_template/log_template
{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "index.mapping.total_fields.limit": 1000,
      "index.number_of_shards": 3,
      "index.number_of_replicas": 1
    },
    "mappings": {
      "dynamic": "strict",
      "properties": {
        "@timestamp": { "type": "date" },
        "message": { "type": "text" },
        "service_name": { "type": "keyword" }
      }
    }
  }
}

Step 2. Flattened 데이터 타입 활용

구조를 알 수 없는 가변적인 객체 데이터는 flattened 타입을 사용해 단일 필드로 처리합니다. 이는 매핑 폭발을 방지하는 가장 효과적인 방법입니다.

PUT /logs-app/_mapping
{
  "properties": {
    "user_defined_metadata": {
      "type": "flattened"
    }
  }
}

Step 3. 샤드 사이징 최적화 계산

로그 데이터의 경우 샤드 하나당 크기를 20GB에서 50GB 사이로 유지하는 것이 권장됩니다. 일일 데이터 적재량이 300GB라면 샤드 수를 다음과 같이 계산합니다.

계산식: (일일 데이터 300GB) / (샤드 목표 크기 30GB) = 10개의 프라이머리 샤드

4. Dynamic Mapping 설정 방식 비교

상황에 맞는 매핑 전략을 선택하여 유연성과 안정성의 균형을 맞춰야 합니다.

기준true (기본값)falsestrict
동작 방식새 필드 자동 추가데이터 저장 후 무시에러 발생 및 거부
매핑 폭발 위험매우 높음낮음없음
데이터 유실 가능성없음필드 검색 불가문서 삽입 실패
추천 환경개발 단계로그 데이터 수집엄격한 정형 데이터

로그 수집 시스템에서는 예상치 못한 필드가 들어올 때 시스템이 멈추지 않도록 false를 쓰거나, 데이터 무결성이 중요하다면 strict를 선택하세요.

5. 주의사항

⚠️ 가장 자주 하는 실수: 샤드 개수를 노드 수보다 적게 설정하면 특정 노드에만 부하가 쏠리는 '핫 스팟' 현상이 발생하여 클러스터 전체 성능이 저하됩니다.

샤드 크기가 50GB를 초과하면 인덱스 복구(Recovery) 시간이 너무 오래 걸리고, 10GB 미만으로 너무 작으면 수천 개의 샤드 관리 비용으로 인해 마스터 노드가 응답 불능 상태에 빠질 수 있습니다.

에러 메시지별 해결법

[Limit of total fields [1000] has been exceeded]
원인: 인덱스 필드 수가 설정된 한도를 초과함.
해결: mapping.total_fields.limit을 일시적으로 상향하되, 근본적으로는 flattened 타입을 도입하거나 불필요한 필드를 제거해야 함.

6. 실전 팁

노드당 힙 메모리 1GB당 샤드 수를 20개 이하로 유지하세요. 예를 들어 32GB 힙을 가진 노드라면 최대 600개 내외의 샤드를 관리하는 것이 안전합니다.

인덱스 생명주기 관리(ILM)를 사용하여 오래된 데이터는 shrink API를 통해 샤드 수를 줄이고, 최종적으로는 frozen 단계로 이동시켜 메모리 점유율을 낮춰야 합니다.

📌 핵심 요약

  • 매핑 폭발 방지를 위해 dynamic: strictflattened 타입을 사용하세요.
  • 샤드 크기는 20GB~50GB를 목표로 설정하여 오버샤딩을 방지하세요.
  • ILM 정책을 통해 인덱스 관리 자동화를 구현하고 클러스터 상태를 가볍게 유지하세요.

Frequently Asked Questions

Q. Elasticsearch 매핑 폭발 해결 방법은?

A. dynamic 설정을 strict로 바꾸고 가변 필드는 flattened 타입을 사용하세요.

Q. 적절한 샤드 크기는 얼마인가요?

A. 일반적인 로그 데이터 기준 샤드당 20GB에서 50GB 사이가 가장 적합합니다.

Q. 인덱스당 필드 제한을 늘려도 안전한가요?

A. 2,000개까지는 가능하지만 그 이상은 마스터 노드 메모리 부하를 유발하므로 권장하지 않습니다.

Post a Comment