LLM WikiAccess-protected knowledge portal
← 스터디 홈
1편 · 약 12분

Elasticsearch 아키텍처와 핵심 개념

왜 Elasticsearch인가?

MySQL이나 PostgreSQL은 LIKE '%검색어%' 쿼리로도 텍스트를 찾을 수 있다. 하지만 이 방법은 인덱스를 타지 못해 데이터가 많아지면 풀 테이블 스캔이 발생한다. "오늘 저녁 피자 먹고 싶다"라는 문장이 있을 때 "피자"로 검색하려면 형태소를 분석하고 토큰화해야 하는데, RDBMS는 이런 언어 처리를 기본으로 지원하지 않는다.

Elasticsearch는 Apache Lucene 위에 구축된 분산 검색·분석 엔진이다. 2010년 Shay Banon이 처음 오픈소스로 공개했고, 현재는 Elastic이 개발·운영하며 오픈소스(ELv2/SSPL)와 Elastic Cloud 서비스를 함께 제공한다. 전문(full-text) 검색뿐 아니라 로그 분석(ELK 스택), APM, 보안 이벤트 집계에 폭넓게 쓰인다.

역 인덱스: 전문 검색의 기반

역 인덱스(inverted index)는 "어떤 단어가 어떤 문서에 있는가"를 미리 만들어 두는 자료구조다. RDBMS의 B-Tree 인덱스가 "행 → 값"을 빠르게 찾는 구조라면, 역 인덱스는 "값(토큰) → 문서 목록"을 저장한다.

원문 문서 doc1: "Kafka 실시간 스트리밍" doc2: "Kafka 와 Spark 데이터 파이프라인" doc3: "Spark 배치 처리 기초"
분석기(Tokenize·Normalize)
역 인덱스 kafka → [doc1, doc2] spark → [doc2, doc3] 스트리밍 → [doc1] 배치 → [doc3]
역 인덱스 구조: 텍스트 분석과 토큰-문서 매핑

검색어 "kafka"가 들어오면 역 인덱스에서 [doc1, doc2]를 O(1)에 조회한다. 분석기(analyzer)는 입력 텍스트를 토큰으로 쪼개고(tokenizer), 소문자 변환·불용어 제거·형태소 분석 같은 필터를 적용한다. 한국어는 nori 플러그인이 형태소를 처리한다.

클러스터 계층 구조

Elasticsearch의 데이터 모델은 네 계층으로 이루어진다.

계층설명
클러스터동일한 cluster.name을 공유하는 노드의 집합. 단일 논리 시스템으로 동작
인덱스관련 문서의 모음. RDBMS의 테이블에 해당. 실제로는 하나 이상의 샤드로 분산
샤드(Shard)Lucene 인스턴스 하나. 인덱스를 수평 분할한 단위. 기본값 1개(7.x 이후)
레플리카(Replica)프라이머리 샤드의 복사본. 고가용성 + 읽기 성능 향상

프라이머리 샤드 수는 인덱스 생성 시점에 고정된다. 데이터가 많아지면 샤드를 늘릴 수 없으므로, 처음부터 예상 데이터 크기를 고려해 설정해야 한다. 레플리카는 언제든 변경 가능하다.

Cluster (my-cluster) Node 1 (Master+Data) P0 logs 프라이머리샤드 0 R1 logs 레플리카샤드 1 P0 metrics 프라이머리샤드 0 Node 2 (Data) P1 logs 프라이머리샤드 1 R0 logs 레플리카샤드 0 R0 metrics 레플리카샤드 0 Node 3 (Data) P2 logs 프라이머리샤드 2 R2 logs 레플리카샤드 2 P1 metrics 프라이머리샤드 1
클러스터·인덱스·샤드·레플리카 관계도

프라이머리 샤드와 그 레플리카는 같은 노드에 배치되지 않는다. 노드 하나가 죽어도 레플리카가 프라이머리로 승격되어 서비스가 이어진다.

노드 역할

프로덕션 환경에서는 노드에 역할을 분리해 성능과 안정성을 높인다.

  • Master-eligible node: 클러스터 메타데이터(인덱스 매핑, 샤드 배치)를 관리. 홀수 대수로 운영(뇌분리 방지).
  • Data node: 실제 샤드를 저장하고 색인·검색 연산을 수행. 디스크와 I/O 집약적.
  • Coordinating node: 클라이언트 요청을 받아 관련 샤드에 분산하고 결과를 취합. 전용 코디네이터는 힙 메모리 부담을 줄여준다.
  • Ingest node: 색인 전 파이프라인(grok, geoip, rename 등) 처리. Logstash 없이 간단한 전처리를 클러스터 내에서 처리할 때 사용.

소규모 클러스터에서는 한 노드가 여러 역할을 겸한다. Elastic 공식 권고는 노드 3대 이상, 마스터 전용 3대, 데이터 전용 N대 분리다.

문서 색인 흐름: Buffer → Segment → Disk

문서를 색인할 때 즉시 디스크에 쓰지 않는다. 세 단계로 나뉜다.

클라이언트 PUT
프라이머리 샤드
In-memory Buffer + Translog (fsync)
↓ refresh (1s) Lucene Segment (검색 가능, 메모리) ↓ flush (30분 or translog 크기) Segment 디스크 커밋 + Translog 초기화
색인 흐름: Translog · In-memory Buffer · Lucene Segment · Disk
  1. Translog 기록: 색인 직후 내구성을 위해 트랜잭션 로그에 기록된다. 노드 재시작 시 미커밋 연산을 복구한다.
  2. Refresh (기본 1초): 인메모리 버퍼가 새 Lucene 세그먼트로 변환되고 검색 가능해진다. 아직 디스크엔 없다. refresh_interval: -1로 비활성화해 대량 색인 성능을 높일 수 있다.
  3. Flush (기본 30분 or translog 512 MB): Lucene이 세그먼트를 디스크에 커밋(fsync)하고 translog를 초기화한다.

세그먼트는 불변(immutable)이다. 문서 업데이트는 실제로 새 세그먼트에 새 버전을 쓰고 기존 세그먼트의 문서를 삭제 표시(tombstone)한다. 작은 세그먼트들은 백그라운드 병합(merge)으로 통합된다.

분산 쿼리 실행: Query + Fetch 2단계

검색 요청은 코디네이팅 노드를 통해 두 단계로 실행된다.

  1. Query phase: 코디네이터가 관련 샤드(프라이머리 또는 레플리카) 전체에 쿼리를 브로드캐스트한다. 각 샤드는 자신의 역 인덱스에서 매칭 문서의 _id와 점수를 반환한다.
  2. Fetch phase: 코디네이터가 상위 N개 _id를 선별해 해당 샤드에 실제 문서 본문을 요청하고 취합해 반환한다.

이 구조 덕분에 쿼리는 여러 샤드에서 병렬 처리된다. 반면 from + size 페이지네이션 깊이가 깊어질수록 각 샤드가 더 많은 상위 결과를 반환해야 하므로 메모리 부담이 커진다(deep pagination 문제).

한 줄 정리

Elasticsearch는 역 인덱스 기반의 Lucene을 분산 계층으로 감싼 검색·분석 엔진이며, 샤드를 여러 노드에 분산해 대규모 데이터의 색인·검색을 병렬 처리한다.

References

  • https://www.elastic.co/docs/deploy-manage/distributed-architecture/clusters-nodes-shards
  • https://opster.com/guides/elasticsearch/glossary/elasticsearch-flush-translog-and-refresh/
  • https://learncsdesigns.medium.com/demystifying-elasticsearch-understanding-nodes-clusters-shards-and-indices-part-2-c1835e1e061e
  • https://qbox.io/blog/refresh-flush-operations-elasticsearch-guide/
  • https://shayne007.github.io/2025/06/16/Elasticsearch-Underlying-Principles-Deep-Dive/
  • https://medium.com/@bohyunlee.dev/understanding-opensearch-data-indexing-and-translog-f67d65b2b920