Elasticsearch - 매핑,스키마,템플릿
[ELK Stack]Elasticsearch - 매핑,스키마,템플릿
1. 매핑이란?
RDB에서는 테이블을 만들 때 스키마 설계를 반드시 해야 함. 스키마는 테이블을 구성하는 각 컬럼의 타입, 길이, 관계 등을 정의하는 규칙임. 이 구조는 데이터 정합성과 효율적인 질의를 가능하게 함. Elasticsearch에서도 비슷한 개념이 존재하는데, 이걸 매핑(Mapping) 이라고 부름.
매핑은 JSON 형태의 도큐먼트를 Elasticsearch 내부의 Lucene이 이해할 수 있는 구조로 변환하는 일종의 스키마 정의임. 검색엔진으로서 Elasticsearch가 대용량 데이터를 빠르게 검색하고 실시간 분석이 가능한 이유는 이 매핑 구조 덕분임. 매핑을 제대로 정의해놓으면 성능은 물론 검색 정확도, 집계 효율성까지 크게 향상됨.
- 자동 매핑: 다이나믹 매핑 (Elasticsearch가 알아서 매핑)
- 수동 매핑: 명시적 매핑 (사용자가 직접 매핑 정의)
2. 다이나믹 매핑
다이나믹 매핑은 데이터를 인덱싱할 때 Elasticsearch가 자동으로 필드 타입을 추론하여 매핑을 생성하는 기능임. 즉, 사용자가 따로 매핑을 지정하지 않아도 기본적인 구조를 판단해서 알아서 설정해줌.
예시로는
PUT index_auto/_doc/1
{
"name": "pcy",
"age": 27,
"is_active": true,
"joined": "2024-01-01",
"tags": ["engineer", "dev"]
}
해당 도큐먼트를 넣으면 자동으로 다음과 같이 매핑이 생성됨:
"properties": {
"name": {"type": "text"},
"age": {"type": "long"},
"is_active": {"type": "boolean"},
"joined": {"type": "date"},
"tags": {"type": "text"}
}
자동 매핑은 편리하지만, 잘못된 타입으로 인덱싱되면 성능 저하나 쿼리 오류를 유발할 수 있음. 따라서 초기에 테스트 환경에서 매핑 결과를 확인하고, 정식 환경에서는 명시적 매핑을 권장함.
다이나믹 매핑의 타입 추론 기준표
| JSON 데이터 타입 | Elasticsearch 매핑 타입 (dynamic: true) |
|---|---|
null |
필드 없음 (매핑 안함) |
true/false |
boolean |
double |
float 또는 double |
long |
long |
object |
object |
array |
배열 내부 첫 번째 값의 타입 따름 |
| 문자열(date 추정) | date |
| 문자열(숫자 추정) | long 또는 float |
| 일반 문자열 | text + keyword |
※ 배열은 내부 값이 null인 경우 필드 자체가 무시됨 ※ 문자열 타입은 내부 룰에 따라 날짜/숫자로도 자동 판별될 수 있음
3. 매핑 조회 예시
GET index2/_mapping
"properties": {
"age": {"type": "long"},
"name": {"type": "text", "fields": {"keyword": {"type": "keyword"}}},
"gender": {"type": "text", "fields": {"keyword": {"type": "keyword"}}},
"country": {"type": "text", "fields": {"keyword": {"type": "keyword"}}}
}
근데?
age: 일반적으로 200세 넘는 사람은 없기 때문에short타입으로 설정 가능 → 공간 절약 + 성능 향상gender,country: 집계, 정렬 용도면keyword타입으로 변경 권장 → 불필요한 분석기 오버헤드 방지
4. 명시적 매핑 (Explicit Mapping)
매핑을 사전에 정의해서 인덱스를 생성하는 방식임. 대용량 데이터를 다루거나, 필드 타입을 엄격하게 통제해야 하는 환경에서는 필수적임.
PUT index_explicit
{
"mappings": {
"properties": {
"name": {"type": "text"},
"family": {"type": "keyword"},
"age": {"type": "short"}
}
}
}
name: 검색 가능한 텍스트family: 집계 및 정렬용age: 적절한 숫자 범위로 효율화
매핑 설정에 사용되는 주요 파라미터들
| 파라미터 | 설명 |
|---|---|
type |
필드의 데이터 타입 |
analyzer |
문자열 분석기 지정 |
format |
날짜 형식 지정 (예: yyyy-MM-dd) |
index |
false로 설정 시 인덱싱 제외 |
null_value |
null일 때 대체값 지정 |
ignore_above |
문자열 길이 초과 시 인덱싱 제외 |
5. 문자열 처리 - text vs keyword
text 타입
- 분석기(analyzer) 를 거쳐 토큰 단위(term) 로 분리되어 역인덱싱됨
- match 쿼리 등 풀텍스트 검색에 적합
- 문장 내부의 일부분만 검색해도 매칭 가능하며, 자연어 검색에 유리함
- 토큰 필터를 이용해 소문자 처리, 불용어 제거, 형태소 분석까지 가능
분석기 단계:
- 캐릭터 필터 → HTML 태그 제거 등 전처리
- 토크나이저 → 문장을 단어 단위로 분리 (예:
cute dog→cute,dog) - 토큰 필터 → 소문자 변환, 불용어 제거 등
match 예제
GET index2/_search
{
"query": {
"match": {
"name": "Chan Young"
}
}
}
keyword 타입
- 전체 문자열이 하나의 토큰으로 취급됨 (분석기 미적용)
- 정확히 일치하는 값 검색, 집계/정렬에 적합
- 대소문자 구분되며, 토큰 처리가 없기 때문에 저장 공간도 절약됨
term 예제
GET index2/_search
{
"query": {
"term": {
"gender.keyword": "male"
}
}
}
6. 멀티필드 (Multi Field)
Elasticsearch에서는 하나의 필드를 다양한 방식으로 검색/처리할 수 있게 fields 속성을 지원함. 이걸 멀티필드라고 함. 주로 text와 keyword 타입을 동시에 정의할 때 활용됨.
예를 들어 contents라는 필드를 분석기 기반의 텍스트 검색과 정확 일치 기반의 집계/정렬 양쪽에서 모두 사용하고 싶다면 다음처럼 설정함.
PUT multifield_index
{
"mappings": {
"properties": {
"contents": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"message": { "type": "text" }
}
}
}
contents: 기본은 text → 전문 검색용contents.keyword: keyword 하위 필드 → 정렬/집계용
멀티필드를 정의해두면 아래처럼 다양한 방식으로 활용할 수 있음.
match 쿼리 (풀텍스트 검색)
GET multifield_index/_search
{
"query": {
"match": {
"contents": "elasticsearch tutorial"
}
}
}
term 쿼리 (정확 일치 검색)
GET multifield_index/_search
{
"query": {
"term": {
"contents.keyword": "elasticsearch tutorial"
}
}
}
집계 쿼리
GET multifield_index/_search
{
"size": 0,
"aggs": {
"content_terms": {
"terms": {
"field": "contents.keyword"
}
}
}
}
멀티필드를 통해 텍스트 분석 기반 검색과, 정확한 키워드 기반 집계/정렬을 유연하게 병행할 수 있음.
7. 인덱스 템플릿
동일한 매핑/설정을 반복해서 여러 인덱스에 적용하려면 템플릿을 사용하는 것이 효율적임. 특히 파티셔닝된 인덱스 구조에서는 필수적인 기능임.
템플릿 조회
GET _index_template
GET _index_template/ilm-history
GET _index_template/ilm*
템플릿 생성 예시
PUT _index_template/test_template
{
"index_patterns": ["test_*"],
"priority": 1,
"template": {
"settings": {
"number_of_replicas": 1,
"number_of_shards": 3
},
"mappings": {
"properties": {
"name": {"type": "text"},
"age": {"type": "short"},
"gender": {"type": "keyword"}
}
}
}
}
템플릿 주요 파라미터
| 키 | 설명 |
|---|---|
index_patterns |
어떤 인덱스에 적용할지 패턴 지정 (와일드카드 사용 가능) |
priority |
템플릿 우선순위 (숫자가 클수록 우선 적용) |
template.settings |
인덱스 설정 (샤드 수, 복제 수 등) |
template.mappings |
인덱스 매핑 정보 |
템플릿 적용 확인
PUT test_index1
GET test_index1/_mapping
→ test_template이 자동으로 적용된 매핑 확인 가능
우선순위가 높은 템플릿이 먼저 적용되며, 충돌 시 우선순위 기준으로 병합됨.
댓글남기기