OpenSearch 인덱스와 샤드 최적화를 상징하는 톱니바퀴, 도구, 퍼즐 조각의 나무 위 평면 배치
글 요약
OpenSearch Service 운영 노하우를 Index 설계, Shard 튜닝, 성능 최적화, 모니터링, 비용 절감, 대안 비교까지 6개 섹션으로 정리했습니다. 흔히 겪는 실패 사례와 노하우, 다른 검색 엔진과의 구체적 차이점까지 한 번에 얻을 수 있습니다.
“OpenSearch Shard를 어떻게 나눠야 할지 모르겠고, 검색이 점점 느려져서 어디부터 손대야 할지 막막합니다.”
Shard 사이징 실수 한 번이 클러스터 전체를 마비시킬 수 있습니다. 이 글에서는 Index 설계 원칙부터 Shard 분할 전략, 캐시 튜닝, 비용 절감, Elasticsearch·Algolia·Solr와의 비교까지 운영자가 반드시 알아야 할 실전 노하우를 모두 담았습니다.
운영 중인 OpenSearch에서 검색 지연이 느는 건 단순히 데이터가 늘어서가 아니라 대부분 Shard 설계 미스에서 시작됩니다. 처음에 “그냥 기본값으로 가자” 하고 넘어간 설정이 몇 달 뒤 수백 GB가 쌓이면 회복하기 어렵거든요. 실제로 샤드 수를 잘못 잡아 클러스터를 재구축한 사례를 여러 번 봐왔더라고요. 그래서 도입부에서는 핵심 키워드 위주로 개념을 빠르게 짚고, 본문에서 실전 최적화 전략을 단계별로 풀어보겠습니다.
📑 목차
OpenSearch는 Elasticsearch 7.10에서 포크된 오픈소스 검색 엔진으로, AWS에서 관리형으로 제공됩니다. 라이선스 걱정 없이 풀텍스트 검색, 로그 분석, 벡터 검색까지 처리할 수 있어 도입 기업이 늘고 있거든요. 다만 무료라고 해서 가볍게 다루면 운영 6개월쯤부터 슬슬 병목이 드러나기 시작합니다. 다음 섹션부터 운영의 핵심을 하나씩 짚어드리겠습니다.
📌 이 글의 핵심 정리
- Shard 사이즈는 10~50GB가 황금 구간이며, 샤드당 1~2개 코어에 매칭되는 것이 안정적입니다.
- Index 설계는 도메인·시간 단위로 분리하고, rollover API로 라이프사이클을 자동화해야 합니다.
- 캐시·refresh_interval 튜닝이 체감 성능을 좌우하며, JVM 메모리의 절반을 heap에 할당하는 게 원칙입니다.
- CloudWatch와 Slow Log를 병행 모니터링해야 장애 5분 전에 신호를 잡을 수 있습니다.
- UltraWarm·Cold Storage로 비용 90% 절감이 가능하지만, 쿼리 패턴 분석이 선행되어야 효과가 큽니다.
- Elasticsearch와 기능은 유사하나 라이선스·가격 모델이 다르므로 워크로드에 따라 선택지가 갈립니다.
OpenSearch Service 개요와 Index 관리 기본
OpenSearch는 문서 지향 NoSQL 구조로 데이터를 Index → Shard → Segment 계층에 저장합니다. Index는 RDBMS의 테이블에 해당하고, 그 안에서 검색·집계가 병렬로 일어납니다. 초보 운영자가 가장 많이 하는 실수가 모든 로그를 하나의 인덱스에 몰아넣는 건데, 이러면 매핑 변경과 삭제가 전체에 영향을 미치고 장애 범위가 넓어지거든요.
Index 분리 원칙
인덱스는 비즈니스 도메인 단위로 쪼개는 게 기본입니다. 예를 들어 전자상거래라면 products, orders, reviews를 각각 별도 인덱스로 만들고, 시간 기반 데이터(로그·이벤트)는 logs-2024.01.01처럼 날짜 단위로 둡니다. 날짜 기반 인덱스의 장점은 오래된 데이터를 한 번에 삭제할 때 비용이 거의 0이라는 점이거든요. force merge 후 delete 시 디스크가 즉시 회수됩니다.
Index 템플릿으로 매핑 표준화하기
운영이 3개월만 지나도 인덱스가 수십 개로 늘어나는데, 매번 매핑을 수동으로 작성하면 필드 타입 불일치가 발생합니다. Index Template을 활용하면 패턴에 맞는 신규 인덱스가 생성될 때 자동으로 매핑·설정이 적용됩니다. 특히 keyword와 text 필드 구분, dynamic 매핑 strict 모드는 반드시 템플릿에서 강제하는 게 좋습니다.
- settings.number_of_shards는 처음에만 설정 가능하므로 신중하게 결정
- number_of_replicas는 클러스터 노드 수보다 작게 설정
- refresh_interval 기본값 1초를 로그용이면 30초로 조정
Alias와 Rollover 활용
애플리케이션이 항상 최신 인덱스를 가리키도록 하려면 Alias를 써야 합니다. logs-write, logs-read 두 개의 Alias를 두고, 쓰기는 최신 인덱스로, 읽기는 검색 대상 인덱스 그룹으로 라우팅합니다. 그리고 ILM(Index State Management)의 rollover 액션을 30GB·30일 기준으로 걸어두면 자동으로 신규 인덱스가 만들어지거든요. 운영자의 수동 개입 없이도 라이프사이클이 굴러갑니다.
Shard 사이징 실전 전략
Shard는 한 번 만들면 개수를 줄이기 매우 어렵습니다. number_of_shards는 인덱스 생성 후 변경이 안 되거든요. 그래서 처음에 5로 시작했는데 데이터가 늘어나 200GB가 됐고, 검색이 한 샤드당 50GB가 적정한데 어쩌지? 하는 상황이 자주 벌어집니다. 이때 reindex로 새 인덱스를 만들어야 하는데 다운타임을 감수해야 하니 처음 설계가 핵심입니다.
샤드 사이즈 황금 비율
업계 권장값은 샤드당 10~50GB입니다. 너무 작으면 파일 핸들·메모리 오버헤드가 크고, 너무 크면 복구 시간이 길어집니다. 또한 노드당 샤드 수는 JVM heap 1GB당 20개 이하가 안전한데, heap 16GB라면 노드당 300개 안팎이 한계거든요. 다음 표는 데이터 규모별 권장 샤드 수 가이드입니다.
| 총 데이터 크기 | 권장 샤드 수 | 샤드당 평균 크기 | 필요 노드 수 (data 노드) |
|---|---|---|---|
| 100GB 이하 | 2~5개 | 20~50GB | 3개 (r5.large) |
| 100GB ~ 1TB | 10~30개 | 30~50GB | 3~5개 (r5.xlarge) |
| 1TB ~ 10TB | 50~200개 | 30~50GB | 5~10개 (r5.2xlarge) |
| 10TB 이상 | 200개+ | 40~50GB | 10개+ (UltraWarm 도입) |
⚠️ 실전 함정: 초기에 샤드 1개로 시작한 뒤 데이터 폭증
처음에 “일단 샤드 1개로 시작하자”는 판단이 6개월 뒤 reindex 작업을 강요하는 원인이 됩니다. 데이터 증가 속도를 미리 예측해 두 배 정도 여유를 두는 것이 안전합니다.
샤드 분할 후 재해복구 시나리오
샤드를 잘게 쪼개면 검색은 빨라지지만 장애 시 복구해야 할 단위도 많아집니다. 노드 하나가 죽으면 다른 노드로 샤드가 재배치되는데, 이때 I/O 버스트가 발생해 클러스터 전체가 일시적으로 응답하지 않을 수 있거든요. cluster.routing.allocation.node_concurrent_recoveries 값을 기본 2에서 1로 낮추면 복구 속도는 느려지지만 안정성이 올라갑니다. 실시간 검색 응답성을 우선시한다면 기본값을 유지하는 게 좋습니다.
⚠️ OpenSearch 샤드 운영 주의
- 샤드 수는 인덱스 생성 후 변경 불가하므로 초기 설계가 가장 중요합니다. 데이터 증가 추이를 6개월·1년 단위로 예측해 두 배 여유를 두세요.
- 노드당 샤드 수 20개/GB가 안전선입니다. 이 값을 넘으면 GC가 빈번해지고 검색 지연이 급격히 증가합니다.
- replica 수를 노드 수보다 크게 설정하면 클러스터가 yellow 상태로 멈춥니다. 항상 (노드 수 – 1) 이하로 설정하세요.
검색·인덱싱 성능 튜닝
OpenSearch 성능 튜닝은 크게 세 갈래로 나뉩니다. JVM 메모리, 캐시 설정, 인덱싱 파이프라인입니다. 이 세 개 중 하나라도 어긋나면 다른 설정을 아무리 만져도 효과가 없거든요. 운영자 입장에서 가장 먼저 점검해야 할 항목이 무엇인지 명확히 해두는 게 중요합니다.
JVM Heap과 Field Data Cache
JVM heap은 노드 메모리의 절반만 할당해야 합니다. 나머지 절반은 Lucene가 파일 시스템 캐시로 사용하기 때문이거든요. AWS OpenSearch에서는 opensearch.yml의 indices.fielddata.cache.size를 20~30% 정도로 제한하는 것이 안전합니다. field data cache가 heap을 잠식하면 GC가 멈추고 클러스터가 행(hang)에 걸립니다. 또한 indices.query.bool.max_clause_count는 1024로 두는 게 디폴트인데, 너무 많은 should 절을 쓰는 쿼리가 있다면 4096으로 올려야 합니다.
Bulk 인덱싱과 Refresh 정책
초당 수만 건의 로그가 쏟아지는 환경이라면 Bulk API 사이즈가 핵심입니다. 일반적으로 5~15MB 단위로 묶어 보내는 것이 최적이며, 너무 작으면 요청 오버헤드가 크고 너무 크면 메모리 압박이 옵니다. 로그성 인덱스라면 refresh_interval을 30초~5분으로 늘려 segment 생성 빈도를 줄이는 게 체감 성능에 큰 차이를 만들어주더라고요. 실시간성이 중요하지 않은 분석용이라면 무조건 1분 이상으로 설정하시기 바랍니다.
💡 성능 튜닝 꿀팁
- _source 필드 축소가 가장 효과적인 최적화입니다. 표시가 필요한 필드만 includes로 지정해 저장 용량을 30~50% 줄이세요.
- doc_values는 비활성화하지 마세요. 집계·정렬 성능이 10배 이상 차이 납니다. 디스크만 약간 더 쓰는 것 대비 효과가 압도적입니다.
- _id 자동 생성을 피하고 비즈니스 키를 직접 쓰면 인덱싱이 빨라집니다. UUID 생성 비용이 사라집니다.
모니터링과 장애 대응 노하우
장애는 늘 가장 바쁜 시간에 찾아옵니다. 새벽에 노드가 하나 죽었다고 가정해 보죠. 이때 CloudWatch 알람만 의존하면 CPU·메모리 같은 시스템 지표는 잡히지만 검색 지연이나 shard 할당 실패는 놓치기 쉽습니다. 그래서 운영자는 두 가지 신호를 동시에 봐야 합니다.
CloudWatch 핵심 지표
AWS OpenSearch 대시보드에서 가장 자주 봐야 할 지표는 ClusterStatus.yellow, JVMMemoryPressure, SearchableDocuments입니다. JVMMemoryPressure가 75%를 넘으면 곧 OOM이 나올 수 있으니 즉시 알람을 걸어두는 게 필수입니다. 또한 CPUUtilization은 80% 이상 지속될 때 노드 증설 검토 대상입니다.
Slow Log와 Hot Thread 분석
검색이 갑자기 느려졌다면 우선 Slow Search Log를 확인합니다. index.search.slowlog.threshold.query.warn을 10s, fetch를 1s로 설정해 두면 어떤 쿼리가 무거운지 명확히 드러납니다. 인덱싱 병목이라면 Slow Index Log에서 batch size가 너무 큰지 확인하고, Hot Thread API로 어떤 스레드가 CPU를 점유하는지 보면 원인이 거의 잡힙니다.
- yellow status: replica가 할당 안 된 상태로 노드 복구 후 자동 해소
- red status: primary shard 손실로 즉시 복구 작업 필요
- unassigned shards: 디스크 워터마크 초과 시 발생, 인덱스 삭제·확장으로 해결
비용 최적화와 리소스 관리
OpenSearch는 데이터가 늘수록 비용이 선형으로 증가하는 구조라 처음엔 저렴하다가 1년 차에 비싸지는 경우가 많습니다. 가장 효과적인 절감 방법은 UltraWarm과 Cold Storage 도입입니다. 자주 조회하지 않는 로그를 S3 기반 스토리지로 옮기면 비용이 GB당 1/10 수준으로 떨어지거든요.
UltraWarm·Cold Storage 적용 기준
데이터 액세스 패턴을 먼저 분석해야 합니다. 최근 7일 데이터만 자주 조회되고 30일 이후는 월 1회 감사용이라면 UltraWarm이 적합합니다. 90일 이상 거의 조회하지 않는다면 Cold Storage가 맞아요. 다음 표는 스토리지 옵션별 비교입니다.
| 옵션 | GB당 월 비용 (대략) | 쿼리 지연 | 적합한 용도 |
|---|---|---|---|
| Hot (EBS) | 높음 (0.10~0.15$) | 수십 ms | 실시간 검색·집계 |
| UltraWarm | 중간 (0.024$) | 수백 ms ~ 2초 | 주 1회 이하 조회 로그 |
| Cold Storage | 낮음 (0.003$) | 수초 ~ 수십 초 | 월 1회 미만 감사·백업 |
인스턴스 타입별 선택 가이드
읽기 위주 워크로드라면 메모리 최적화(R5, R6g) 인스턴스가, 인덱싱이 많다면 컴퓨트 최적화(C5, C6g)가 효율적입니다. Graviton(ARM) 인스턴스는 동일 vCPU 대비 20~30% 저렴하므로 신규 구축 시 우선 검토하길 권합니다. 단, 일부 플러그인이 ARM과 호환되지 않을 수 있으니 사전 확인이 필요합니다.
다른 검색 솔루션과의 비교 분석
OpenSearch가 모든 상황에 최적인 건 아닙니다. 워크로드에 따라 Elasticsearch, Algolia, Typesense 같은 솔루션이 더 잘 맞을 수 있거든요. 다음 표는 4가지 검색 엔진을 운영·기능·비용 측면에서 비교한 것입니다.
| 비교 항목 | OpenSearch | Elasticsearch | Algolia | Typesense |
|---|---|---|---|---|
| 라이선스 | Apache 2.0 (무료) | SSPL/Elastic (상용) | 상용 SaaS | GPL (무료 셀프호스팅) |
| 관리 방식 | AWS 관리형 / 셀프호스팅 | Elastic Cloud / 셀프호스팅 | SaaS only | 셀프호스팅 / SaaS |
| 강점 | 무료·풀 기능·로그 분석 | 성숙한 생태계·ML | 타이포 허용·즉시 응답 | 저지연·타이포 허용 |
| 약점 | 자체 운영 부담 | 라이선스 비용 부담 | 레코드당 비용·종속성 | 고급 집계·ML 미지원 |
| 추천 워크로드 | 로그·분석·검색 통합 | 엔터프라이즈 검색 | 전자상거래 즉시 검색 | 중소규모 검색 SaaS |
OpenSearch만의 차별화된 통찰
Elasticsearch와 기능은 90% 이상 유사하지만 결정적 차이가 있습니다. OpenSearch는 Apache 2.0이라 라이선스 비용이 없고, AWS 관리형과 완벽 통합되어 VPC 내 배포가 자유롭습니다. 반면 Elasticsearch는 v8부터 SSPL/Elastic License이라 호스팅을 외부에 노출하면 비용이 발생합니다. 초기 비용을 절감하고 싶고 로그 분석과 검색을 한 번에 처리하고 싶다면 OpenSearch가 가장 합리적인 선택입니다. 다만 자체 운영 부담이 있으므로 작은 팀이라면 SaaS 형태의 Algolia·Typesense도 검토할 가치가 있습니다.
선택 기준 체크리스트
- 월 1억 건 이상 로그 + 검색 필요 → OpenSearch
- 엔터프라이즈 SLA·ML 기능 필수 → Elasticsearch
- 전자상거래 즉시 응답·타이포 허용 → Algolia
- 저예산·중소규모·운영 부담 최소화 → Typesense
자주 묻는 질문
Q. OpenSearch 샤드 수는 인덱스 생성 후 정말 변경할 수 없나요?
A. 네, number_of_shards는 한 번 설정하면 그 인덱스에서는 변경 불가합니다. 변경하려면 reindex API로 새 인덱스를 만들어 alias를 교체해야 하므로 처음 설계가 결정적입니다.
Q. UltraWarm과 Cold Storage의 실제 비용 차이는 얼마나 나오나요?
A. 같은 데이터를 Hot에 두면 GB당 약 0.12$, UltraWarm은 0.024$, Cold Storage는 0.003$ 수준입니다. 데이터가 5TB라면 월 600$에서 120$, 15$까지 줄일 수 있어 액세스 패턴이 중요하다.
Q. JVMMemoryPressure 알람은 어느 수준으로 걸어야 하나요?
A. 일반적으로 75%를 5분 지속 기준으로 알람을 설정합니다. 80%를 넘으면 곧 OOM이 나올 가능성이 매우 높고, 90% 이상이면 GC가 끝없이 돌며 응답이 멈춥니다.
Q. OpenSearch와 Elasticsearch 중 무엇을 선택해야 할까요?
A. 라이선스 비용 절감과 AWS 통합이 중요하다면 OpenSearch, 엔터프라이즈 SLA·머신러닝·고급 보안이 핵심이라면 Elasticsearch가 적합합니다. 기능 자체는 거의 동등합니다.
Q. 노드 1개가 죽었을 때 자동으로 복구되나요?
A. replica가 다른 노드에 있으면 자동으로 재배치됩니다. 다만 디스크 워터마크 초과나 마스터 노드 손실 같은 경우는 수동 개입이 필요하므로 CloudWatch 알람과 함께 정기 점검을 권합니다.
OpenSearch 운영은 처음에 어떻게 설계하느냐에 따라 6개월 뒤의 안정성이 결정됩니다. 샤드 사이즈 황금 비율을 지키고, 인덱스를 도메인·시간 단위로 분리하고, 캐시와 refresh 정책을 워크로드에 맞게 조정하면 대부분의 문제는 예방됩니다. 비용까지 고려한다면 UltraWarm과 Cold Storage 도입을 망설이지 마시길 바랍니다.
본 글의 모든 수치·가격·권장값은 일반적인 운영 경험을 바탕으로 한 참고용이며, 실제 환경에 따라 차이가 발생할 수 있습니다. 도입 전에는 반드시 공식 문서와 AWS 최신 요금을 직접 확인하시고, 프로덕션 적용 전에는 테스트 클러스터에서 충분히 검증하시기 바랍니다. 본 콘텐츠는 정보 제공 목적이며 특정 제품·서비스에 대한 보증을 의미하지 않습니다.