Development

29 posts in this category

테스트 개발 포스트

이것은 development 카테고리 테스트 포스트입니다.

버블 정렬 알고리즘 구현하기

테스트 페이지 - 버블 소트

Hugo와 Bootstrap으로 블로그 만들기

테스트 페이지 - 휴고 블로그

⚙️Analyzer 커스터마이징 가이드

이 문서는 Elasticsearch에서 custom analyzer를 설계하고,
nori tokenizer 기반으로 불용어 제거, 품사 필터링, 동의어 처리 등을 적용하는 방법을 다룹니다.


1. ⚙️ analyzer 커스터마이징 개요

✅ custom analyzer란?

custom analyzer = tokenizer + 0개 이상의 filter
  • tokenizer: 입력 텍스트를 토큰으로 분해
  • filters: 토큰을 소문자화, 불용어 제거, 동의어 처리 등 후처리

2. 주요 filter 종류

필터 이름설명
lowercase모든 텍스트를 소문자로 변환
stop불용어(stopword) 제거 (, , 등)
synonym동의어 치환 (예: kakao => 카카오)
nori_part_of_speech품사(POS) 필터링 (예: 접속사 제거)
nori_readingform한자 → 발음으로 변환

3. 예시: nori 기반 커스텀 analyzer

PUT http://localhost:9200/custom-index
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "my_nori_tokenizer": {
          "type": "nori_tokenizer",
          "decompound_mode": "mixed"
        }
      },
      "filter": {
        "my_pos_filter": {
          "type": "nori_part_of_speech",
          "stoptags": [ "E", "IC", "J", "MAG", "MAJ" ]
        },
        "my_stop_filter": {
          "type": "stop",
          "stopwords": [ "의", "가", "이", "은", "는" ]
        },
        "my_synonym_filter": {
          "type": "synonym",
          "synonyms": [
            "카카오, kakao",
            "네이버, naver"
          ]
        }
      },
      "analyzer": {
        "my_korean_analyzer": {
          "type": "custom",
          "tokenizer": "my_nori_tokenizer",
          "filter": [
            "lowercase",
            "my_pos_filter",
            "my_stop_filter",
            "my_synonym_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "content": {
        "type": "text",
        "analyzer": "my_korean_analyzer"
      }
    }
  }
}

4. 커스텀 analyzer 분석 테스트

POST http://localhost:9200/custom-index/_analyze
{
  "analyzer": "my_korean_analyzer",
  "text": "카카오의 새로운 서비스가 시작되었습니다."
}

📌 예상 결과 (필터 적용됨):

⚡ 검색 성능 향상 팁

이 문서는 Elasticsearch에서 검색 쿼리 성능을 높이기 위한 실전 팁들을 정리한 문서입니다.
대용량 데이터 환경에서도 효율적인 검색을 유지하려면 반드시 알아야 할 핵심 항목들을 포함합니다.


1. 🔍 filter와 must의 분리

must vs filter 비교

항목mustfilter
점수(score)계산함계산 안 함
캐시 활용거의 불가능✅ 캐시 가능
목적relevance 기반 검색조건 필터링 (정확 매칭 등)

📌 Tip: 가능한 조건은 filter로 분리하여 쿼리 성능 향상

"bool": {
  "must": [
    { "match": { "title": "카카오" } }
  ],
  "filter": [
    { "term": { "status": "published" } }
  ]
}

2. 📦 _source 필드 최소화

  • _source는 document 전체를 반환하는 필드
  • 필요한 필드만 지정하여 I/O 비용 절감 가능
"_source": ["title", "date"]

📌 예: 수십 개 필드 중 2~3개만 필요할 때 효과적

✨ 검색어 하이라이팅 기능

이 문서는 Elasticsearch에서 검색어가 포함된 부분을 강조(하이라이트)해서 반환하는 기능을 설명합니다.
기본 <em> 태그를 사용하며, 다양한 하이라이터 설정도 가능합니다.


✅ 1. highlight란?

검색 결과에서 사용자가 입력한 검색어가 일치한 부분을
특정 태그로 감싸서 강조 표시할 수 있는 기능입니다.


🛠️ 2. 기본 highlight 쿼리 예시

{
  "query": {
    "match": {
      "content": "카카오"
    }
  },
  "highlight": {
    "fields": {
      "content": {}
    }
  }
}

반환 예시:

"highlight": {
  "content": [
    "이번 주 <em>카카오</em> 주식이 급등했다."
  ]
}

🎨 3. 태그 커스터마이징

"highlight": {
  "pre_tags": ["<strong>"],
  "post_tags": ["</strong>"],
  "fields": {
    "content": {}
  }
}
  • <em> 대신 <strong>, <mark> 등 원하는 HTML 태그로 감쌀 수 있음

✂️ 4. fragment_size, number_of_fragments

"highlight": {
  "fields": {
    "content": {
      "fragment_size": 100,
      "number_of_fragments": 2
    }
  }
}
설정 항목설명
fragment_size각 조각의 최대 길이 (문자 수 기준)
number_of_fragments최대 반환 조각 수

🧠 5. highlighter 종류

타입설명
unified기본값, 대부분의 경우 추천
plain빠르지만 기능 제한
fvh (Fast Vector Highlighter)빠르고 정밀한 하이라이팅 (필드에 term_vector 필요)
"highlight": {
  "type": "unified",
  "fields": {
    "content": {}
  }
}

✅ 요약

항목설명
기본 태그<em>으로 감싸서 강조
커스터마이징 가능<strong>, <mark> 등 HTML 태그 지정 가능
조각 길이 조절fragment_size, number_of_fragments
하이라이터 선택 옵션unified, plain, fvh

🎯 검색 점수 튜닝 실습 예제

이 문서는 function_score 쿼리를 활용하여 검색 결과의 relevance score를 커스터마이징하는 실습 예제입니다.
클릭수, 좋아요, 최신성 등을 반영한 복합 점수 계산 전략을 설명합니다.


1. ⚙️ function_score 기본 구조

function_score 쿼리는 검색 점수를 수식 기반으로 조절할 수 있습니다.

{
  "query": {
    "function_score": {
      "query": { "match": { "title": "카카오" } },
      "functions": [
        ...
      ],
      "score_mode": "sum",
      "boost_mode": "multiply"
    }
  }
}
  • query: 기본 검색 조건
  • functions: 가중치나 decay 함수 등 적용
  • score_mode: 여러 함수의 결과를 합산, 평균 등으로 결합
  • boost_mode: 기존 점수와 함수 점수를 어떻게 합칠지 결정

2. 💡 likes, clicks 기반 가중치 예시

"functions": [
  {
    "field_value_factor": {
      "field": "likes",
      "factor": 1.5,
      "modifier": "sqrt", 
      "missing": 0
    }
  },
  {
    "field_value_factor": {
      "field": "clicks",
      "factor": 0.5,
      "modifier": "log1p",
      "missing": 1
    }
  }
]
  • likes: 제곱근 기반 증가
  • clicks: 로그 기반 완만한 증가

3. 🕒 createdAt 기반 최신 문서 선호 (decay 함수)

{
  "gauss": {
    "createdAt": {
      "origin": "now",
      "scale": "10d",
      "decay": 0.5
    }
  }
}
  • 최신 문서일수록 점수가 높고, 오래될수록 자연스럽게 감소
  • scale: 감소가 시작되는 거리
  • decay: 감소 비율

4. ⚖️ boost_mode와 score_mode 조합

score_mode의미
sum함수 결과 모두 더함
avg평균값 사용
max가장 큰 값만 사용
multiply모두 곱함 (값이 0이면 전체 점수 0됨)
first첫 번째 함수만 사용
boost_mode기존 _score와의 결합 방식
multiply_score * function_score
sum_score + function_score
replace_score 무시하고 function 사용
avg평균 사용
max/min큰 값 또는 작은 값 사용

✅ 전체 예시 쿼리

{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "title": "카카오"
        }
      },
      "functions": [
        {
          "field_value_factor": {
            "field": "likes",
            "factor": 1.2,
            "modifier": "sqrt",
            "missing": 0
          }
        },
        {
          "field_value_factor": {
            "field": "clicks",
            "factor": 0.8,
            "modifier": "log1p",
            "missing": 1
          }
        },
        {
          "gauss": {
            "createdAt": {
              "origin": "now",
              "scale": "15d",
              "decay": 0.4
            }
          }
        }
      ],
      "score_mode": "sum",
      "boost_mode": "multiply"
    }
  }
}

📌 요약

요소설명
function_score점수 계산 방식 커스터마이징
field_value_factor숫자 필드 기반 가중치 반영
gauss최신성 점수 반영 (decay)
score_mode여러 function 결합 방식 (sum, avg 등)
boost_mode기존 점수와 결합 방식 (multiply, replace 등)

🎯 매핑 설계 잘하는 팁 & 전략

이 문서는 Elasticsearch에서 매핑(mapping)을 효율적으로 설계하기 위한 팁과 개념들
http://localhost:9200/contents 기준으로 설명합니다.


1. 🎯 매핑 설계 잘하는 팁

🧹 불필요한 필드 제거

  • 저장할 필요가 없는 데이터는 매핑 자체를 하지 않거나 _source에서 제외
  • 검색/필터링/집계에 쓰이지 않는 데이터는 제외하는 것이 성능에 유리

🧷 타입 명확히 지정

데이터 예시적절한 타입
날짜date
정수integer
가격float
이메일, URLkeyword
본문, 설명, 제목text

🚫 동적 매핑(auto mapping) 주의

  • 설정하지 않으면 자동으로 text + keyword로 매핑됨 → 원치 않는 분석기 적용 가능성
  • 명시적인 매핑 정의 권장

2. ⚖️ text vs keyword

항목textkeyword
분석 여부분석됨 (tokenizer, filter 적용)분석되지 않음 (전체값 그대로)
검색 목적전문(full-text) 검색정확한 일치, 집계/정렬/필터용
예시 필드제목, 내용, 댓글ID, 이메일, 태그, 카테고리

3. 🔀 multi-field 전략

🧠 하나의 필드를 여러 방식으로 활용

예: title 필드를 검색도 하고, 정렬/집계도 하려면?

📉 쿼리 설계 실수 예시 10가지

Elasticsearch에서 쿼리 성능과 정확도에 영향을 주는 대표적인 실수 10가지를 정리한 문서입니다.
실전 검색 엔진에서 흔히 발생하며, 사전에 방지하거나 리팩터링 시 주의해야 할 포인트입니다.


1. ❌ filter 없이 must만 사용하는 경우

  • must는 relevance score 계산 포함 → 성능 저하
  • 단순 조건은 반드시 filter 사용
"bool": {
  "must": [ { "term": { "status": "active" } } ] // ❌
}

✅ 개선 예시:

"bool": {
  "filter": [ { "term": { "status": "active" } } ]
}

2. ❌ from 값을 너무 크게 사용하는 경우

  • from: 10000 이상은 성능 문제 + 기본 max_result_window 초과 오류
  • deep pagination 비효율적

✅ 해결 방법:

📊 검색 로그 기반 점수 튜닝 전략

이 문서는 사용자의 검색 로그(search logs) 를 활용하여
검색 점수를 튜닝하고 추천 기능을 강화하는 전략을 설명합니다.


✅ 1. search_logs 인덱스 구성 예시

{
  "mappings": {
    "properties": {
      "query": { "type": "keyword" },
      "clicked_doc_id": { "type": "keyword" },
      "timestamp": { "type": "date" },
      "user_id": { "type": "keyword" }
    }
  }
}
  • 각 로그는 사용자가 어떤 검색어로 어떤 문서를 클릭했는지를 기록
  • clicked_doc_id 기준으로 클릭 빈도 집계 가능

📈 2. 검색어 → 클릭률 분석

예시:

검색어검색 횟수클릭 횟수클릭률 (%)
카카오1004040%
삼성805062.5%
  • 클릭률이 높은 검색어는 추천 검색어로 활용 가능
  • 특정 문서가 어떤 검색어에 자주 클릭되는지 분석해 점수 반영

🔍 3. 인기 키워드 추출

{
  "size": 0,
  "aggs": {
    "popular_queries": {
      "terms": {
        "field": "query",
        "size": 10
      }
    }
  }
}
  • 최근 n일 동안 가장 많이 검색된 키워드 집계 가능

✨ 4. 추천어 생성 예시

  • 입력 시 → [“카카오”, “카드”, “카메라”] 추천
  • 인기 키워드를 기반으로 prefix 매칭 추천어 생성 가능

🛠️ 5. 오타 교정 (Did You Mean)

{
  "suggest": {
    "text": "kakaoo",
    "spellcheck": {
      "term": {
        "field": "query"
      }
    }
  }
}
  • 실제 로그에 존재하는 단어를 기준으로 오타 보정 가능
  • did_you_mean 기능 구현 가능

🚀 6. 클릭 수 기반 추천 점수 반영

방법 1: 검색 쿼리에서 function_score 사용

{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "title": "카카오"
        }
      },
      "field_value_factor": {
        "field": "click_count",
        "modifier": "log1p",
        "missing": 0
      },
      "boost_mode": "multiply"
    }
  }
}
  • 클릭 횟수가 높은 문서일수록 가중치가 올라감
  • 로그 데이터를 집계해 click_count 필드로 인덱싱해야 함

✅ 요약

전략 항목설명
search_logs 인덱스검색어, 클릭 문서, 시간, 사용자 ID 등 기록
클릭률 기반 분석검색어 → 클릭률 계산 → 인기 검색어 추출
추천어 생성자주 검색된 검색어 기반 자동완성 구현 가능
오타 교정자주 등장한 검색어 기반 "Did You Mean" 구현 가능
점수 반영function_score로 클릭 수 기반 가중치 부여

🔁 추천/정확도/최신/인기순 분리 전략

Elasticsearch에서 검색 결과를 다양한 기준으로 정렬하는 전략을 정리한 문서입니다.
사용자의 니즈에 따라 정확도, 인기, 최신, 추천순을 분리하여 검색 품질을 높일 수 있습니다.


1. 🎯 정확도 정렬 (Relevance Based)

전략

  • multi_match 쿼리로 다양한 필드 검색
  • 중요한 필드에는 boost 적용
{
  "multi_match": {
    "query": "카카오",
    "fields": ["title^3", "content", "tags^2"],
    "type": "best_fields"
  }
}
  • title 필드는 ^3 → 가장 높은 점수 기여
  • tags^2 → 중간 가중치

2. 🔥 인기순 정렬 (Popularity Based)

전략

  • likes, clicks 등의 수치 필드를 점수에 반영
  • function_score + field_value_factor 사용
{
  "function_score": {
    "query": {
      "match": {
        "title": "카카오"
      }
    },
    "functions": [
      {
        "field_value_factor": {
          "field": "likes",
          "factor": 1.5,
          "modifier": "sqrt",
          "missing": 0
        }
      },
      {
        "field_value_factor": {
          "field": "clicks",
          "factor": 0.5,
          "modifier": "log1p",
          "missing": 1
        }
      }
    ],
    "score_mode": "sum",
    "boost_mode": "replace"
  }
}

3. 🕒 최신순 정렬 (Latest First)

전략

  • createdAt 필드로 정렬
{
  "sort": [
    { "createdAt": { "order": "desc" } }
  ]
}
  • 최신 문서가 먼저 노출됨
  • relevance 점수는 무시됨

4. 🧠 추천순 정렬 (Recommendation Ranking)

전략

  • 정확도 × 인기 × 최신성 조합
  • function_score로 통합 점수 계산
{
  "function_score": {
    "query": {
      "multi_match": {
        "query": "카카오",
        "fields": ["title^3", "content", "tags^2"]
      }
    },
    "functions": [
      {
        "field_value_factor": {
          "field": "likes",
          "factor": 1.2,
          "modifier": "sqrt"
        }
      },
      {
        "gauss": {
          "createdAt": {
            "origin": "now",
            "scale": "10d",
            "decay": 0.5
          }
        }
      }
    ],
    "score_mode": "sum",
    "boost_mode": "multiply"
  }
}
  • 정확도는 기본 _score
  • likes: 인기 점수
  • gauss(createdAt): 최신성 점수
  • multiply로 결합 → 추천순

✅ 요약 정리

정렬 기준전략 요약
정확도순multi_match + boost
인기순function_score + likes, clicks
최신순sort by createdAt desc
추천순정확도 × 인기 × 최신성 조합 (function_score)

🔗 동의어 처리 (synonym filter)

이 문서는 Elasticsearch에서 동의어(synonym) 를 처리하여
다양한 표현을 하나의 의미로 검색할 수 있도록 하는 전략을 설명합니다.


✅ 1. 동의어 필터란?

사용자가 “검색"이라고 입력했을 때
“서치”, “찾기”, “검색” 등 여러 표현을 동시에 검색할 수 있도록 만드는 텍스트 확장 필터입니다.


🔄 2. 동의어 처리 예시

입력어확장된 검색어
검색검색, 서치, 찾기
자동차차량, 카, 오토모바일

⚙️ 3. analyzer에 동의어 filter 설정 (inline 방식)

{
  "settings": {
    "analysis": {
      "filter": {
        "synonym_filter": {
          "type": "synonym",
          "synonyms": [
            "검색, 서치, 찾기",
            "자동차, 차량, 오토모바일"
          ]
        }
      },
      "analyzer": {
        "synonym_analyzer": {
          "tokenizer": "standard",
          "filter": ["lowercase", "synonym_filter"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "synonym_analyzer"
      }
    }
  }
}

📄 4. 파일 기반 동의어 처리

대용량 동의어 사전은 파일로 관리할 수 있습니다.

🔤 자동완성 & ngram 검색 전략

이 문서는 검색어 자동완성 기능을 구현할 때 사용되는 Elasticsearch 전략을 설명합니다.
prefix, edge_ngram, completion 세 가지 접근 방식과 각각의 장단점, 설정 방법을 다룹니다.


1. 📌 자동완성 구현 방식 비교

방식장점단점
prefix설정 간단, 기본 기능검색 정확도 낮음, 노이즈 발생
edge_ngram검색어 조합 다양, 부분일치 가능인덱스 용량 증가, 튜닝 필요
completion속도 빠름, 추천어에 적합기능 제한, 스코어 커스터마이징 어려움

2. ✍️ prefix 쿼리 예시

{
  "query": {
    "prefix": {
      "title": "카카"
    }
  }
}
  • 사용자가 “카카” 입력 시 “카카오”, “카카시”, “카카푸” 등 반환
  • 정확도보다 간단한 시작 단어 기반 매칭에 적합

3. 🧱 edge_ngram 기반 분석기 설정 예시

매핑 설정

{
  "settings": {
    "analysis": {
      "tokenizer": {
        "autocomplete_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 20,
          "token_chars": ["letter", "digit"]
        }
      },
      "analyzer": {
        "autocomplete": {
          "tokenizer": "autocomplete_tokenizer",
          "filter": ["lowercase"]
        },
        "autocomplete_search": {
          "tokenizer": "standard",
          "filter": ["lowercase"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "autocomplete",
        "search_analyzer": "autocomplete_search"
      }
    }
  }
}
  • autocomplete_tokenizer: edge_ngram 기반으로 부분 토큰 생성
  • search_analyzer: 표준 분석기로 검색어 그대로 사용

4. 🔍 검색 쿼리 예시 (edge_ngram)

{
  "query": {
    "match": {
      "title": {
        "query": "카카"
      }
    }
  }
}
  • 사용자가 카카라고 검색하면 카카오, 카카시, 카카XX 모두 검색 가능
  • 토큰화 예시 (카카오): , 카카, 카카오

5. ⚡ completion 필드 예시

매핑 설정

{
  "mappings": {
    "properties": {
      "suggest": {
        "type": "completion"
      }
    }
  }
}

검색 쿼리

{
  "suggest": {
    "title-suggest": {
      "prefix": "카카",
      "completion": {
        "field": "suggest"
      }
    }
  }
}
  • autocomplete에 특화된 데이터 구조로 빠른 추천
  • 단점: 일반적인 match 쿼리와 통합 어려움

✅ 요약 정리

전략설명
prefix간단하지만 정확도 낮고 유연성 부족
edge_ngram강력한 자동완성 구현 가능, 인덱스 용량 증가 주의
completion빠른 추천 시스템에 적합, 기능 제한 있음

🔰기본 개념

이 문서는 Elasticsearch를 처음 접하는 사람들을 위해 인덱스, 매핑, 구조 등을 설명합니다.
예제 URL은 http://localhost:9200/contents 기준입니다.


1. 📌 /contents는 무엇인가?

  • http://localhost:9200/contents 에서 contents인덱스(index) 이름입니다.
  • Elasticsearch에서 인덱스는 문서들의 집합입니다.
  • RDB로 비유하면 **테이블(table)**에 해당합니다.

2. 🧱 Elasticsearch 구조 요약

Elasticsearch는 다음과 같은 계층 구조로 되어 있습니다:

클러스터
  └── indices (복수형, 여러 인덱스)
        └── index (예: contents)
              └── documents (JSON 형식 데이터)
                    └── fields (각 데이터의 속성)
RDB 용어Elasticsearch 용어
DatabaseCluster
TableIndex
RowDocument
ColumnField

3. 📄 매핑(Mapping) 개념과 _mapping의 역할

  • **매핑(mapping)**이란 인덱스 내 문서의 필드 구조와 타입을 정의한 것입니다.
  • 예를 들어 필드가 text인지 keyword인지, 날짜인지 숫자인지를 정의합니다.
  • RDB로 치면 테이블의 스키마(schema) 와 비슷한 개념입니다.

✅ 매핑 확인 방법

GET http://localhost:9200/contents/_mapping?pretty
  • 위 요청은 contents 인덱스의 매핑 정보를 확인하는 API입니다.

🔠 대표적인 필드 타입

필드 타입설명
text검색용 텍스트 (analyzer로 형태소 분석 가능)
keyword필터, 정렬, 집계용 문자열 (분석 불가)
integer정수형 숫자
float실수형 숫자
date날짜/시간 정보
booleantrue/false 값

✅ 정리 요약

항목설명
/contents인덱스 이름 (RDB의 테이블과 유사)
인덱스 구조클러스터 → 인덱스 → 문서 → 필드
매핑(Mapping)문서의 필드 구조 정의 (타입, 분석기 등)
_mapping API인덱스의 현재 매핑 정보를 확인하는 엔드포인트

🚨 실전 매핑 실수 모음

이 문서는 Elasticsearch를 사용할 때 자주 발생하는 매핑 설계 실수 사례들을 정리한 가이드입니다.
실수를 피하기 위한 베스트 프랙티스도 함께 소개합니다.


1. ❌ keyword 필드에 match 사용

문제 설명

keyword 필드는 분석되지 않은 문자열이기 때문에 match 쿼리로는 동작하지 않음.

"match": {
  "status": "published"  // keyword 필드일 경우 동작 X
}

해결 방법

  • match 대신 term 쿼리를 사용해야 함
"term": {
  "status": "published"
}

2. ❌ text 필드로 정렬

문제 설명

text 필드는 분석된 문자열이기 때문에 정렬이 불가능하거나 성능이 매우 나쁨.

Logs Monitoring 정리 (실무 중심)

✅ 1. 전체 아키텍처 흐름

[App/Infra Logs]
      ↓
   Filebeat / Logstash
      ↓
  [Elasticsearch]
      ↓
   Kibana (대시보드)
  • Filebeat: 로그 파일 수집기 (Lightweight)
  • Logstash: 데이터 처리, 변환, 파싱
  • Elasticsearch: 로그 저장/검색/분석
  • Kibana: 시각화 및 모니터링 대시보드

✅ 2. Filebeat (로그 수집기)

🔹 역할

  • 로그 파일 tailing
  • Multiline (스택트레이스 등) 지원
  • 시스템 로그, Docker 로그, Nginx, Java 로그 등 수집 가능

🔹 설정 예시

filebeat.inputs:
  - type: log
    paths:
      - /var/log/myapp/*.log
    multiline.pattern: '^\['
    multiline.negate: true
    multiline.match: after

output.elasticsearch:
  hosts: ["http://localhost:9200"]
  index: "myapp-logs-%{+yyyy.MM.dd}"

💡 실무 팁

  • multiline 설정 필수 (Java stack trace)
  • fields 옵션으로 서비스명, 환경 태깅
  • JSON 로그 구조화 추천

✅ 3. Logstash (필요 시 중간 가공)

🔹 역할

  • 로그 파싱 및 정제
  • Grok 패턴, mutate, date 필터 등
  • Kafka → Logstash → ES 구성 가능

🔹 Grok 예시

filter {
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} \[%{LOGLEVEL:level}\] %{GREEDYDATA:msg}" }
  }
  date {
    match => [ "timestamp", "ISO8601" ]
  }
}

💡 실무 팁

  • Filebeat에서 JSON 구조면 Logstash 생략 가능
  • Kafka 중계/복잡한 parsing 시 유용

✅ 4. Kibana (시각화 및 알림)

🔹 주요 기능

  • Discover: 실시간 로그 조회
  • Dashboard: 시각화
  • Alerting: 이상 탐지 알림
  • Lens/TSVB: 시간 기반 분석

💡 실무 팁

  • timestamp, level, logger, service_name 필드 표준화
  • Error 로그 대시보드 구성
  • 복합 필터링 예시: log.level: ERROR AND NOT message:"Connection reset"

✅ 5. 성능/보안 로그 모니터링

유형설명
JVM GC 로그메모리 문제 추적
Nginx / ApacheAPI 응답 시간, 요청 수 분석
Kafka / RedisBroker 상태, throughput 추적
Spring Bootactuator 로그 + slf4j 로그
시스템 로그CPU, 메모리 사용량 추적
인증 로그로그인 시도, 실패 분석

✅ 6. 인덱스 전략 및 유지 관리

  • index.lifecycle 정책 (ILM): 오래된 로그 자동 삭제
  • 일별 인덱스: myapp-logs-2025.07.11
  • 템플릿 매핑 필수: @timestamp, log.level
  • hot-warm-cold 아키텍처 고려

✅ 7. 실무 구성 예시 (Docker Compose)

services:
  elasticsearch:
    image: elasticsearch:8.17.6
    environment:
      - discovery.type=single-node
    ports:
      - 9200:9200

  kibana:
    image: kibana:8.17.6
    ports:
      - 5601:5601
    depends_on:
      - elasticsearch

  filebeat:
    image: docker.elastic.co/beats/filebeat:8.17.6
    volumes:
      - ./filebeat.yml:/usr/share/filebeat/filebeat.yml
      - /var/log:/var/log:ro

✅ 정리 요약

구성 요소역할비고
Filebeat로그 수집Multiline 지원, 간단
Logstash로그 정제Grok 필터, Kafka 중계
Elasticsearch저장/검색인덱스 설계 중요
Kibana시각화/모니터링Discover, Alert 활용

Query DSL 정리 (실무 중심)

🔍 1. term 쿼리

{ "term": { "status": "active" } }
  • 정확히 일치하는 값을 찾을 때 사용
  • 형태소 분석되지 않은 필드 (keyword, int, boolean)에 적합
  • text 필드에는 text.keyword로 사용해야 정확히 일치
  • 실무: 상태, ID, 카테고리 코드 등

🔍 2. terms 쿼리

{ "terms": { "status": ["active", "ready"] } }
  • 여러 값 중 하나라도 일치하면 검색
  • IN 조건처럼 사용
  • 65,536개 이상의 값은 사용 불가 (성능 저하)

🔍 3. match 쿼리

{ "match": { "title": "엘라스틱 서치 강의" } }
  • text 필드에 사용
  • 형태소 분석됨 (자연어 검색)
  • 완전 일치 아님 → 관련된 문서도 나올 수 있음

🔍 4. match_phrase 쿼리

{ "match_phrase": { "title": "엘라스틱 서치 강의" } }
  • 정확한 문장 일치 (순서 유지)
  • 중간 단어 빠지면 매칭되지 않음

🔍 5. bool 쿼리

{
  "bool": {
    "must": [ ... ],        // 모두 만족 (AND)
    "should": [ ... ],      // 하나 이상 만족하면 OK (OR 느낌)
    "must_not": [ ... ],    // 만족하면 제외
    "filter": [ ... ]       // 점수 영향 없음, 빠름
  }
}

✔️ 실전 사용 예

{
  "bool": {
    "must": [
      { "term": { "status": "active" } },
      { "match": { "title": "엘라스틱" } }
    ],
    "filter": [
      { "range": { "created_date": { "gte": "now-7d/d" } } }
    ],
    "must_not": [
      { "term": { "is_deleted": true } }
    ]
  }
}

🔍 6. range 쿼리

{ "range": { "price": { "gte": 1000, "lte": 5000 } } }
  • 숫자나 날짜 필드에 범위 조건 적용
  • 실무: 가격, 날짜 필터링

🔍 7. exists 쿼리

{ "exists": { "field": "thumbnail_url" } }
  • 필드가 존재하는지 확인

🔍 8. wildcard / regexp / prefix

{ "wildcard": { "title": "엘라*" } }
  • wildcard, regexp, prefix는 느릴 수 있음
  • analyzed 되지 않은 keyword 필드에 사용 추천

🔍 9. multi_match

{
  "multi_match": {
    "query": "검색어",
    "fields": ["title", "description"]
  }
}
  • 여러 필드에 match 쿼리 적용

🔍 10. script 쿼리

{
  "script_score": {
    "query": { "match_all": {} },
    "script": {
      "source": "doc['click_count'].value * 0.5 + doc['like_count'].value"
    }
  }
}
  • 스크립트 기반 동적 스코어
  • 캐시 안 되고 느릴 수 있음 → 최소 사용 권장

✅ 실무 패턴 정리

목적쿼리
필터링 + 검색bool + must + filter
정확 조건term, terms
자연어 검색match, multi_match
날짜 조건range (filter 사용 권장)
제외 조건must_not
가중치 적용should, script_score
추천 기능should + minimum_should_match

📌 추천 실전 예시

1. 필터 조건 + 본문 검색

{
  "bool": {
    "must": [
      { "match": { "content": "엘라스틱서치 설정법" } }
    ],
    "filter": [
      { "term": { "status": "published" } },
      { "range": { "created_date": { "gte": "now-1M/M" } } }
    ]
  }
}

2. 추천어 기반 검색

{
  "bool": {
    "must": [
      { "term": { "status": "active" } }
    ],
    "should": [
      { "match": { "title": "엘라스틱" } },
      { "match": { "tags": "검색엔진" } }
    ],
    "minimum_should_match": 1
  }
}

⚠️ 주의할 점

  • text 필드에는 term ❌ → .keyword 사용
  • match는 유사도 기반 → 정확 검색은 term
  • filter는 점수 계산 안 함 → 빠름
  • should만 있을 경우 minimum_should_match 설정 안 하면 모두 미일치해도 통과 가능
  • script는 느림
  • wildcard, regexp는 느림 → 되도록 ngram 대체 고려

심화 쿼리 정리 (실무 중심)

1. 🔧 function_score 쿼리

📌 개념

검색 점수(score)에 함수를 적용해서 가중치(weighting)나 랜덤성 부여

✅ 사용 예시

{
  "function_score": {
    "query": { "match": { "title": "엘라스틱" } },
    "functions": [
      {
        "filter": { "term": { "is_premium": true } },
        "weight": 2
      },
      {
        "random_score": {}
      }
    ],
    "boost_mode": "multiply"
  }
}

💡 실무 활용

  • 프리미엄 콘텐츠 우선 노출
  • 추천 콘텐츠 랜덤성 부여
  • 클릭 수, 조회 수 기반 가중치 조정

⚠️ 주의사항

  • 함수마다 성능 차이 큼 (특히 script 포함 시)
  • boost_mode, score_mode 조정 필요

2. 🧮 script_score 쿼리

📌 개념

커스텀 스크립트로 score 직접 계산

퀵 정렬 알고리즘 완전 정복

테스트 페이지 - 퀵 소트

페이징 전략 정리 (실무 중심)

✅ 1. 기본 페이징: from + size

🔹 개념

SQL의 OFFSET, LIMIT처럼 특정 위치부터 몇 개를 가져옴.

{
  "query": { "match_all": {} },
  "from": 0,
  "size": 10
}

✅ 특징

  • 가장 기본적인 방법
  • from=0, size=10 → 1페이지, from=10, size=10 → 2페이지

⚠️ 주의사항

  • from이 클수록 성능이 나빠짐 (deep pagination)
  • 기본 최대는 10,000 (index.max_result_window 초과 시 에러)

💡 실무 팁

  • 리스트 조회에는 적합
  • 대용량 페이징에는 search_after 또는 scroll 사용

✅ 2. 안정적인 순차 페이징: search_after

🔹 개념

정렬된 필드 기준으로 커서를 넘겨 다음 페이지 요청

🛠️ 매핑 + Analyzer + 검색 쿼리 종합 실습

이 문서는 Elasticsearch에서 posts 인덱스를 대상으로
매핑 설계, custom analyzer 구성, 검색 쿼리 실습을 종합적으로 연습하기 위한 실전 예제입니다.


1. 🎯 목표 요약

  • 커스텀 analyzer를 적용한 posts 인덱스 생성
  • title, tags, content 필드를 적절히 text/keyword로 구성
  • 검색 쿼리에서 match, filter, sort, search_after 등 실제 활용

2. ⚙️ 커스텀 Analyzer + 매핑 예제

PUT http://localhost:9200/posts
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "my_nori_tokenizer": {
          "type": "nori_tokenizer",
          "decompound_mode": "mixed"
        }
      },
      "filter": {
        "my_pos_filter": {
          "type": "nori_part_of_speech",
          "stoptags": ["E", "IC", "J"]
        },
        "my_stop_filter": {
          "type": "stop",
          "stopwords": ["은", "는", "이", "가"]
        }
      },
      "analyzer": {
        "my_korean_analyzer": {
          "type": "custom",
          "tokenizer": "my_nori_tokenizer",
          "filter": [
            "lowercase",
            "my_pos_filter",
            "my_stop_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "my_korean_analyzer",
        "fields": {
          "raw": { "type": "keyword" }
        }
      },
      "tags": {
        "type": "keyword"
      },
      "content": {
        "type": "text",
        "analyzer": "my_korean_analyzer"
      },
      "author": {
        "type": "keyword"
      },
      "created_at": {
        "type": "date"
      }
    }
  }
}

3. 📦 예시 문서 삽입 (Bulk API)

POST http://localhost:9200/posts/_bulk
{ "index": {} }
{ "title": "카카오페이 서비스 출시", "tags": ["fintech", "kakao"], "content": "카카오의 새로운 간편결제 서비스가 시작되었습니다.", "author": "alice", "created_at": "2024-01-01T10:00:00Z" }
{ "index": {} }
{ "title": "네이버 지도 업그레이드", "tags": ["map", "naver"], "content": "지도 검색이 더 빠르고 정확해졌습니다.", "author": "bob", "created_at": "2024-02-15T12:30:00Z" }
{ "index": {} }
{ "title": "구글 검색 AI 도입", "tags": ["ai", "google"], "content": "AI로 더 똑똑한 검색이 가능해졌습니다.", "author": "charlie", "created_at": "2024-03-10T15:00:00Z" }

4. 🔍 검색 쿼리 예제

🎯 4-1. 카카오를 포함하고 fintech 태그를 가진 문서 검색

POST http://localhost:9200/posts/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "content": "카카오" } }
      ],
      "filter": [
        { "term": { "tags": "fintech" } }
      ]
    }
  }
}

🧭 4-2. 정렬 + search_after를 사용한 페이징 검색

POST http://localhost:9200/posts/_search
{
  "size": 2,
  "query": {
    "match_all": {}
  },
  "sort": [
    { "created_at": "desc" },
    { "_id": "asc" }
  ],
  "search_after": ["2024-01-01T10:00:00Z", "doc_id_2"]
}

🔍 4-3. title 정렬 (multi-field 사용)

POST http://localhost:9200/posts/_search
{
  "query": {
    "match": {
      "title": "검색"
    }
  },
  "sort": [
    { "title.raw": "asc" }
  ]
}

✅ 요약

항목설명
custom analyzer 설정nori tokenizer + 불용어 + 품사 필터 적용
multi-field 구성title은 text + keyword 함께 사용 (raw 정렬용)
검색 쿼리 활용match, filter, sort, search_after 조합
Bulk 삽입대량 데이터 테스트를 위한 빠른 삽입

🧠 검색 점수 분석: explain 활용하기

이 문서는 ?explain=true를 사용하여 검색 점수(BM25 등)의 계산 근거를 파악하는 방법을 설명합니다.
어떤 문서가 왜 높은 점수를 받았는지 이해하고, 검색 품질을 향상시키는 데 중요한 역할을 합니다.


✅ 1. explain 파라미터란?

검색 API 호출 시 쿼리 파라미터에 ?explain=true를 추가하면,
각 문서의 _score가 어떻게 계산되었는지 자세한 설명이 함께 반환됩니다.

예시 호출

GET /posts/_search?explain=true
{
  "query": {
    "match": {
      "title": "카카오"
    }
  }
}

📊 2. BM25 점수 계산 요소

BM25는 기본적으로 다음 3가지 요소로 점수를 계산합니다:

🧠 형태소 분석기와 Analyzer 비교

이 문서는 Elasticsearch에서의 형태소 분석 개념과
다양한 analyzer의 차이를 이해하기 위한 실전 예제를 포함하고 있습니다.


5. 🧠 형태소 분석기란 무엇인가?

  • 형태소 분석기(morphological analyzer)는 문장을 의미 단위(형태소) 로 분리하는 역할을 합니다.
  • Elasticsearch에서는 analyzer를 통해 이 작업을 수행합니다.

⚙️ analyzer 구성 요소

analyzer = tokenizer + filter
  • tokenizer: 문장을 기본 단위로 쪼갬 (예: 단어 기준, n-gram 등)
  • filter: 소문자 변환, 불용어 제거 등 후처리 작업 수행

🇰🇷 nori: 한글 형태소 분석기

  • Elasticsearch에서 제공하는 nori analyzer한국어에 특화된 형태소 분석기입니다.
  • 띄어쓰기만으로 분리하기 어려운 어미, 조사, 접두어, 복합어 등을 처리 가능
  • 예: "삼성전자의 주가는"삼성전자, , 주가,

6. 🔬 다양한 analyzer 비교

테스트 문장

삼성전자의 주가는 7만 원이다.

1️⃣ standard analyzer (기본)

POST http://localhost:9200/_analyze
{
  "analyzer": "standard",
  "text": "삼성전자의 주가는 7만 원이다."
}

📌 결과 예시:

🧮 추천순 점수 공식 직접 설계

이 문서는 Elasticsearch에서 추천순 정렬을 위해 점수(score)를 수학적으로 설계하는 방법을 설명합니다.
BM25 점수와 사용자 행동 데이터(likes, clicks) 그리고 최신성을 조합하여 추천 점수를 만들 수 있습니다.


✅ 목표 점수 공식

최종 점수 = BM25 × 인기 점수 + 최신성 점수
  • BM25: Elasticsearch 기본 검색 점수
  • 인기 점수: likes, clicks를 기반으로 계산
  • 최신성 점수: createdAt 필드를 기반으로 decay 적용

1. 🎯 BM25 (기본 점수)

  • 기본적으로 match, multi_match 쿼리를 사용할 경우 BM25 점수가 자동 계산됩니다.
  • 정확도 기반 검색에 사용됩니다.
{
  "multi_match": {
    "query": "카카오",
    "fields": ["title^3", "content", "tags^2"]
  }
}

2. 📈 인기 점수 수식 (log1p, sqrt)

{
  "field_value_factor": {
    "field": "likes",
    "factor": 1.2,
    "modifier": "sqrt",
    "missing": 0
  }
},
{
  "field_value_factor": {
    "field": "clicks",
    "factor": 0.8,
    "modifier": "log1p",
    "missing": 1
  }
}
  • sqrt: 좋아요 수의 증가폭을 완화
  • log1p: 클릭 수가 많아도 완만하게 점수 증가

3. 🕒 최신성 점수 (decay 함수)

{
  "gauss": {
    "createdAt": {
      "origin": "now",
      "scale": "10d",
      "decay": 0.4
    }
  }
}
  • createdAt 기준으로 점수 감소
  • 최신 문서일수록 점수가 높고 오래된 문서는 낮아짐

4. ⚙️ score_mode / boost_mode 설정

항목설명
score_mode여러 function 점수를 어떻게 결합할지 (sum, avg 등)
boost_mode기존 _score와 function 결과 결합 방식

추천 공식에 맞는 설정

"score_mode": "sum",
"boost_mode": "multiply"
  • 점수 함수끼리는 sum
  • 그 결과를 BM25 _score× (multiply)

5. 🧪 전체 예시 쿼리

{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query": "카카오",
          "fields": ["title^3", "content", "tags^2"]
        }
      },
      "functions": [
        {
          "field_value_factor": {
            "field": "likes",
            "factor": 1.2,
            "modifier": "sqrt",
            "missing": 0
          }
        },
        {
          "field_value_factor": {
            "field": "clicks",
            "factor": 0.8,
            "modifier": "log1p",
            "missing": 1
          }
        },
        {
          "gauss": {
            "createdAt": {
              "origin": "now",
              "scale": "10d",
              "decay": 0.4
            }
          }
        }
      ],
      "score_mode": "sum",
      "boost_mode": "multiply"
    }
  }
}

✅ 정리

요소설명
BM25기본 텍스트 매칭 점수
인기 점수likes, clicks → sqrt, log1p 적용
최신성 점수createdAt → decay 적용
최종 조합score_mode: sum, boost_mode: multiply

🧰 인덱스(`/contents`)에서 가능한 작업 목록

이 문서는 http://localhost:9200/contents 인덱스를 기준으로
Elasticsearch에서 수행할 수 있는 문서 작업부터 고급 인덱스 관리 기능까지 정리한 문서입니다.


✅ 1. 기본 문서 작업

📥 문서 생성 (Create)

PUT http://localhost:9200/contents/_doc/1
{
  "title": "Elasticsearch 기본 개념",
  "author": "laon",
  "createdAt": "2025-07-11"
}

📤 문서 조회 (Read)

GET http://localhost:9200/contents/_doc/1

📝 문서 수정 (Update)

POST http://localhost:9200/contents/_update/1
{
  "doc": {
    "author": "laon-ez"
  }
}

❌ 문서 삭제 (Delete)

DELETE http://localhost:9200/contents/_doc/1

✅ 2. 매핑 정보 확인

📄 매핑 확인

GET http://localhost:9200/contents/_mapping?pretty

✅ 3. 인덱스 설정 관리

⚙️ 설정 변경 (예: refresh_interval 조정)

PUT http://localhost:9200/contents/_settings
{
  "index": {
    "refresh_interval": "30s"
  }
}

✅ 4. Bulk Insert (대량 삽입)

POST http://localhost:9200/contents/_bulk
{ "index": { "_id": "1" } }
{ "title": "문서 A", "views": 10 }
{ "index": { "_id": "2" } }
{ "title": "문서 B", "views": 5 }

※ 헤더는 Content-Type: application/x-ndjson

JavaScript ES6+ 주요 기능들

테스트 페이지 - ES6에 관해

React Hooks 완전 가이드

테스트 페이지 - React Hooks

Python으로 웹 스크래핑 시작하기

테스트 페이지 - 파이썬 웹 스크래핑

React Hooks 완벽 가이드

테스트 페이지 - react hook guide