ELK & Elastic Cloud

Mapping과 Analyzer

meellon 2026. 7. 3. 20:20

학습 목표

mapping이 document 필드의 타입·분석 방식을 정의함을 설명할 수 있다.

textkeyword의 차이와 언제 무엇을 쓰는지 선택할 수 있다.

dynamic mappingexplicit mapping의 트레이드오프를 설명할 수 있다.

analyzer가 character filter·tokenizer·token filter로 term을 만드는 과정을 설명할 수 있다.

로그·이벤트용 index mapping 초안을 작성할 수 있다.

문제 상황

  • 2편에서 message를 넣었는데 집계하려니 Text fields are not optimised for operationstext vs keyword
  • order_id문자열로 들어와 정렬·range가 이상 — dynamic mapping이 long 대신 text로 잡음
  • GET /logs/_searchlevel: ERROR 넣었는데 안 맞음error소문자 분석됐거나 필드 타입 불일치
  • mapping 없이 index 만들다 디스크 2배 — 모든 string이 text + keyword multi-field로 잡힘 (7.x+ text 기본)
  • grok으로 뽑은 trace_id부분 검색이 필요 없는데 analyzed — keyword여야 함
  • Kibana에서 service.keywordservice 둘 다 보임 — multi-field 구조를 모름

앞 편에서 document·inverted index·NRT를 봤다. 이번 편은 필드가 어떻게 인덱싱·검색되는지 — mapping과 analyzer. Query DSL은 4편, index template은 14편이다.

1. Mapping이란?

mapping — index의 스키마에 가깝다. 각 필드의 data type분석(analyze) 여부를 정한다.

  • field — document JSON의 키 (level, message, @timestamp)
  • mapping — 필드별 type (keyword, text, date, long …)
  • index time — document 적재 시 mapping에 따라 inverted index·doc values 생성
  • mapping 변경은 제한적 — 타입 변경은 보통 reindex (새 index + _reindex)
개념 설명
properties object 하위 필드 정의
multi-field 한 필드에 text + keyword 서브필드
dynamic 새 필드 자동 mapping (true / false / strict)
meta _meta에 설명·팀 정보 (검색 영향 없음)
GET /app-logs/_mapping
  • mapping은 index(또는 data stream backing index) 단위
  • 14편 composable index template으로 배포 전 고정하는 것이 프로덕션 패턴

2. text vs keyword

가장 자주 틀리는 구분.

  text keyword
분석 analyzer로 term 분리 통째로 하나의 term
검색 full-text (match) 정확 일치·term query
집계·정렬 기본 불가 (fielddata 비권장) doc values로 가능
message, stack_trace level, service, trace_id
inverted index term마다 posting 전체 문자열 하나
  • 로그
    • messagetext (본문 검색)
    • level, service, host.namekeyword (필터·집계)
    • order_id·trace_idkeyword (정확 매칭; 숫자만이면 long)
  • text + .keyword sub-field
    • message는 검색용 text, message.keyword정확 집계용 — 필요할 때만 (디스크 비용)
// code/logs-mapping.example.json (발췌)
{
  "mappings": {
    "properties": {
      "@timestamp": { "type": "date" },
      "level": { "type": "keyword" },
      "service": { "type": "keyword" },
      "trace_id": { "type": "keyword" },
      "order_id": { "type": "long" },
      "message": { "type": "text" }
    }
  }
}
  • Kibana Terms 집계는 almost always keyword 필드

3. Dynamic vs Explicit Mapping

Dynamic mapping

  • 첫 document 적재 시 ES가 필드 타입 추론
    • string → text + keyword sub-field (기본 템플릿)
    • 숫자 → long / double
    • 2026-07-19 형태 → date
  • 장점 — 빠른 PoC, 스키마 미정 로그
  • 단점 — 첫 값이 잘못되면 타입 고정 ("001" → keyword, 나중에 숫자 불가)
  • dynamic: strict — 미정의 필드 거부 (프로덕션 권장에 가깝다)

Explicit mapping

  • index 생성 시 mapping 선언
PUT /app-logs-000001
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "@timestamp": { "type": "date" },
      "level": { "type": "keyword" },
      "message": { "type": "text" }
    }
  }
}
  Dynamic Explicit
속도 빠른 시작 설계·리뷰 필요
예측성 낮음 높음
프로덕션 PoC·dev 권장
변경 필드 추가는 쉬움, 타입 변경 어려움 template 버전 관리
  • data stream + index template — 9·14편에서 롤오버마다 동일 mapping

4. Analyzer

analyzertext 필드 문자열을 term으로 바꾸는 파이프라인 (2편 inverted index 입력).

"The Payment TIMEOUT!"  →  char filter  →  tokenizer  →  token filter  →  the, payment, timeout
단계 역할
Character filter 문자 정규화 HTML strip, &and
Tokenizer 문자열 → 토큰 standard (공백·구두점), whitespace
Token filter 토큰 가공 lowercase, stop, stemmer, synonym

기본·커스텀

# 내장 analyzer 테스트
GET /_analyze
{
  "analyzer": "standard",
  "text": "The Payment TIMEOUT!"
}
# tokens: the, payment, timeout
// code/custom-analyzer.example.json
{
  "settings": {
    "analysis": {
      "analyzer": {
        "log_message": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase", "asciifolding"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "message": { "type": "text", "analyzer": "log_message" }
    }
  }
}
  • standard — 대부분 로그 메시지 기본값으로 충분
  • 한국어nori tokenizer·decompound (별도 플러그인·설정)
  • search_analyzer — index 시 analyzer와 검색 시 analyzer 분리 (동의어·stemming)
  • keyword 필드 — analyzer 없음
용도 analyzer 힌트
영문 로그 standard + lowercase
코드·ID 혼재 message 과도한 stemming 지양
도메인 동의어 synonym filter (검색 품질)
URL·path keyword 또는 pattern tokenizer

5. 자주 쓰는 필드 타입

type 용도 로그 예
date 시간·range @timestamp
keyword enum·ID·집계 level, trace_id
text full-text message, stack_trace
long / double 수치 duration_ms, status
boolean 플래그 success
ip IP client.ip
object 중첩 JSON kubernetes.labels
nested object 배열 독립 검색 items[] (배열 요소별 매칭)
flattened 동적 키 많을 때 debug map (키 제한 주의)
  • object — 내부 필드 평탄화; 배열 object는 교차 매칭 위험 → nested
  • ECS(Elastic Common Schema) — 필드명·타입 표준 (Fleet integration이 ECS 사용)

6. 로그 mapping 설계 습관

습관 이유
@timestamp date Kibana time field
차원 필드 keyword filter·aggregation
본문만 text 디스크·집계 분리
dynamic: strict (prod) 예기치 않은 필드 폭발 방지
ignore_above on keyword 초장문 깨짐 방지 (기본 256)
mapping을 template으로 14편 ILM 롤오버와 연동
PUT /_index_template/app-logs-template
{
  "index_patterns": ["app-logs-*"],
  "template": {
    "mappings": {
      "dynamic": "strict",
      "properties": {
        "@timestamp": { "type": "date" },
        "level": { "type": "keyword" },
        "service": { "type": "keyword" },
        "message": { "type": "text" }
      }
    }
  },
  "priority": 200
}
  • ingest pipeline에서 필드 정규화 후 strict mapping — 8편
  • 잘못된 mapping 발견 시 — 새 index + reindex (20편 운영)

7. 실무에서 기억할 점

증상 원인 조치
집계 불가 on message text keyword 필드 또는 .keyword
order_id 정렬 이상 text로 매핑됨 long + reindex
검색 대소문자 안 맞음 keyword에 analyzer 적용 기대 match on text vs term on keyword
필드 폭발 dynamic true strict + template
한글 검색 약함 standard analyzer nori 등 언어 analyzer
  • 4편match vs term vs keyword filter in Query DSL
  • 5편 — aggregation이 doc values에 의존

정리

  • mapping — 필드 타입·분석 규칙; 로그는 keyword 차원 + text 본문
  • text — analyzed, full-text; keyword — exact, 집계·정렬
  • dynamic — PoC용; explicit + strict — 프로덕션
  • analyzer — character filter → tokenizer → token filter → terms
  • 14편 — index template으로 mapping 표준화

다음에 다룰 것

  • Query DSL
  • match, bool, filter, pagination, search_after

해당 내용은 Elasticsearch Guide (Mapping, Text analysis) 를 기반으로 합니다.

'ELK & Elastic Cloud' 카테고리의 다른 글

Beats  (0) 2026.07.11
Aggregation과 클러스터  (0) 2026.07.08
Query DSL  (0) 2026.07.05
Elasticsearch란  (0) 2026.07.02
ELK · Elastic Cloud 오리엔테이션  (0) 2026.06.30