모두의 플리 프로젝트를 하는 도중 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등분 해서 저장이 됨

- 이렇게 서버가 여러개이기 때문에, 검색을 할 때 한번에 90건을 검색하는게 아니라 각각 30건을 검색하기 때문에 검색 속도가 빠르다!
- 여기서 P는 원본 데이터를 저장하는 Primary shard다
예시 2: Product 레코드 90개와 샤드 3, 그리고 User
- 먼저 샤드들을 설정을 하고, 그 샤드에 맞게 노드들이 샤드들을 분배받고 있는 상황 (남는 샤드가 있음)

- 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) 하도록 자동화할 수 있다
자료
'Cloud' 카테고리의 다른 글
| [AWS] Elastisearch Analyzer- 데이터가 검색되는 원리(텍스트 분석/처리) (0) | 2025.11.27 |
|---|---|
| [AWS] RDS VS EC2 비교와 차이점 (7) | 2025.08.25 |