Cloud

[AWS] Elastisearch - 인프라 기본 개념 정리

leejunkim 2025. 11. 26. 17:41

모두의 플리 프로젝트를 하는 도중 Elastisearch를 사용해서 고도화하는 부분을 맡게 되었다.

  • 컨텐츠 검색 리팩토링 - Elastisearch의 Full Text Search 기능을 활용하여 개선
  • Elastisearch 배포 - Docker을 사용하여 로컬 환경에 구축하거나 AWS OpenSearch 서비스를 활용

Elastisearch

  • 데이터가 json 문서 (document) 형태로 저장되는 분산형 NoSQL 데이터베이스
  • 수평적 확장이 가능하고 데이터베이스를 여러 서버 (노드)에서 실행할 수 있음
  • 텍스트, 숫자, 지리 공간(Geo-spatial) 데이터, IP 주소 등 다양한 데이터 타입을 지원

인덱스(Indexes), 문서 (Document)

위에서 언급했듯이, Elasticsearch는 문서형 데이터 베이스다 (NoSql).

  • 인덱스 (Index)
    • 문서로 이루어짐 
    • 하나 이상의 물리적 샤드들의 논리적 그룹
    • 예) Employee라는 전체 데이터
    • 테이블 같은 구조
  • 문서 (Document)
    • 인덱스 안에 있는 개별 데이터 (가장 작은 단위의 데이터)
    • 예) {"name":"John", "location":"Mumbai", "Age":24, "Email":"abc@gmail.com"}
    • 레코드 같은 구조
  • 장점: JSON을 색인(삽입) 하면 ES는 문서를 불변으로 저장을 한다!
    • 동시 읽기 -> 불변이여서 Lock 메커니즘이 없고 높은 수준의 동시 읽기 성능 제공 + 여러 스레드가 동기에 동일한 문서를 읽을 때 데이터 충돌 발생할 위험도 없음
    • 효율적인 시스템 캐시 활용 -> 오랫동안 데이터가 변하지 않아 OS 캐시와 ES 내부 데이터 구조 캐시를 오랫동안 재활용하는 것이 가능
  • 단잠: 높은 쓰기 비용
    • UPDATE시 필드 하나만 바꾸는 것이 아닌 문서 전체를 삭제하고 새로운 문서로 재색인

Forward VS Inverted Index

데이터 문자가 그대로 검색을 위해 저장되는 형태다 -> 그래서 쿼리 속도가 매우 빠르다.

샤드 (Shard)

 

    • 데이터베이스 시스템에서 데이터를 수평으로 분할 (partitioning)하여 저장하는 가장 작은 물리적 단위
      • 실제로 문서들이 저장될 때 사용되는 물리적인 공간이라고 생각하면 됌
    • 위에서 언급했듯이, Index는 하나 이상 샤드로 이루어져 있음
    • 샤드의 종류
      • 프라이머리(Primary) 샤드 - 원본 데이터가 저장되는 샤드
      • 레플리카(Replica) 샤드 - 데이터 이중화(Redundancy)와 검색 쿼리 처리를 위한 복제본
    • 샤드 하나는 그 자체로 완전한 기능을 갖춘 루씬(Lucene) 검색 엔진임!
      • Elasticsearch는 Java로 작성된 Apache Lucene 라이브러리를 사용
      • 하나의 샤드 안에는 독자적인 역색인(Inverted Index) 구조, 문서 저장소, 검색 로직이 모두 들어있음 
  • Elasticsearch가 클러스터 환경에서 데이터를 관리할 때 이동시키거나 복제하는 단위가 바로 샤드다
    • 문서(Document)가 저장될 때, Elasticsearch는 문서 ID의 해시값을 계산하여 어떤 샤드에 저장할지 결정(Routing)함 (예: shard_num = hash(_id) % total_primary_shards)
  • 사용자가 검색 요청을 보내면, Elasticsearch는 이 요청을 해당 인덱스를 구성하는 모든 샤드에 병렬로 전송한다. 각 샤드는 자신이 가진 데이터 내에서 독립적으로 검색을 수행하고, 그 결과를 반환한다.
    • 위 예시처럼 노드가 2대 있고 하나의 인덱스에 샤드게 3개 있다면, Elasticsearch는 이 샤드들을 각 노드에 분배해준다.
    • 이때 유저가 이 cluster에 query를 날린다면, 두 노드 다 이 쿼리를 병행으로 받고 결과를 반환한다.

수평 확장과 Cluster

  • Cluster
    • ES에서 사용되는 가장 큰 단위, 여러대의 서버를 가지고 있음
  • Node
    • ES를 실행하는 컴퓨터(서버) 한 대
    • 샤드들을 가지고 있음

예시 1: Product 레코드가 90개가 있고 샤드를 3으로 나눌 때, 인덱스가 저장될 때 3등분 해서 저장이 됨

[10분 테크톡] 다로의 Elasticsearch - https://youtu.be/0r0-R8NhINs?si=g5YVVlwOVGTQOUXa

  • 이렇게 서버가 여러개이기 때문에, 검색을 할 때 한번에 90건을 검색하는게 아니라 각각 30건을 검색하기 때문에 검색 속도가 빠르다!
  • 여기서 P는 원본 데이터를 저장하는 Primary shard다

 예시 2: Product 레코드 90개와 샤드 3, 그리고 User

  • 먼저 샤드들을 설정을 하고, 그 샤드에 맞게 노드들이 샤드들을 분배받고 있는 상황 (남는 샤드가 있음)

[10분 테크톡] 다로의 Elasticsearch - https://youtu.be/0r0-R8NhINs?si=g5YVVlwOVGTQOUXa

  • Product의 index부터 샤드에 저장되기 시작
    • 예시 1와 같이 P1-P3 (primary shard)가 각각 A-C 노드에 저장됨 
    • 그 이후에 R1-R3 (replica shard)가 각각 A-C 노드에 저장됨
      • 서버에서 문제가 생기면 각 서버 안에 있는 레플리카에서 문서를 찾을 수 있음
  • Users도 저장하기 시작
    • User 같은 경우 노드B에 primary shard, 노드 C에 replica shard가 저장

인덱스 템플릿 (Index Template)

인덱스가 생성될 때 적용되는 설정값이다 (blueprint)

  • 샤드/레플리카의 갯수, 우선순위 등 설정 포함
  • 데이터 매핑 - 인덱스에 저장될 문서의 스키마/구조 정의
    • 동적 매핑 (dynamic) - 데이터가 수집되는 시점에 스키마를 유추하고 생성 (Schema on Write)
    • 엄격 매핑 (strict) - RDBMS처럼 미리 정의된 매핑 속성을 따르지 않는 문서가 들어오면 거부(reject)하도록 설정 가능

예시:

PUT _index_template/template_1
{
  "index_patterns": ["te*", "bar*"], // 이 패턴에 맞는 인덱스 생성 시 템플릿 적용
  "template": {
    "settings": {
      "number_of_shards": 1
    },
    "mappings": {
      "_source": {
        "enabled": true
      },
      "properties": {
        "host_name": {
          "type": "keyword"
        },
        "created_at": {
          "type": "date",
          "format": "EEE MMM dd HH:mm:ss Z yyyy"
        }
      }
    },
    "aliases": {
      "mydata": { }
    }
  },
  "priority": 500, // 우선순위
  "composed_of": ["component_template1", "runtime_component_template"], 
  "version": 3,
  "_meta": {
    "description": "my custom"
  }
}

인덱스 별칭 (Index Alias)

여러 인덱스를 묶어서 부르는 그룹명

  • 별칭을 사용하여 인덱스 그룹에 문서를 삽입할 수 있음 (쓰기 인덱스 (Write Index)로 지정된 인덱스에만 문서가 저장됨
  • 패턴 사용
    • 특정 인덱스 패턴 (예: logs-*)를 따르는 모든 인덱스를 포함하도록 별칭을 지정할 수 있음

예시:

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-*",
        "alias": "logs"
      }
    }
  ]
}

 

  • 활용법 - 인덱스 수명 주기 관리(ILM)와 함께 사용하여, 특정 기간이나 크기 임계값에 도달하면 데이터를 새로운 인덱스로 롤오버(Rollover) 하도록 자동화할 수 있다

자료