Elasticsearch 보강편. 운영 중인 검색 인덱스를 다운타임 없이 통째로 재구축하는 법 — 풀색인 속도 공식, alias 무중단 전환, 증분 색인까지.
이 글은 Elasticsearch 입문에서 운영까지 시리즈의 보강편이에요. 23편 Bulk API에서 대량 입력을 다뤘죠. 그런데 실무에서 꼭 만나는 운영 작업이 하나 빠져 있었어요 — 이미 서비스 중인 검색 인덱스를 통째로 다시 만드는 일. 분석기나 필드 타입을 바꾸려면 인덱스를 새로 만들어 재색인해야 하는데, 그 사이 검색이 멈추면 안 되거든요. 이 글은 다운타임 없이 인덱스를 재구축하는 파이프라인을 풀어요.
왜 매핑을 바꾸면 통째로 재색인해야 할까
처음엔 이게 좀 황당해요. "필드 타입 하나 바꾸는데 인덱스를 통째로 다시 만들라고?" 싶거든요. 그런데 Elasticsearch는 그래요. 한 번 색인된 필드의 타입·분석기는 대부분 나중에 못 바꿔요. 이미 그 설정으로 역색인(inverted index)이 만들어져 버렸으니까요.
그래서 8편 매핑에서 정한 타입을 바꾸거나, 한글 분석기 설정을 손보려면 길은 하나예요 — 새 인덱스를 만들고, 데이터를 새로 색인해 옮기는 것. 이게 재색인이에요.
문제는 운영 중 이라는 거예요. 검색 서비스가 돌아가는 중에 인덱스를 갈아야 하니, 핵심은 "검색이 1초도 멈추지 않게" 가 됩니다. 그래서 재색인은 단순 복사가 아니라 무중단 전환 파이프라인으로 설계해요.
풀색인 — 새 인덱스에 빠르게 다 쌓기
먼저 새 인덱스에 전체 데이터를 색인하는 단계예요. 그냥 넣으면 느리니, 공식 문서가 권하는 색인 속도 올리는 공식을 써요. 핵심은 "색인하는 동안엔 검색용 부담을 잠시 끈다" 예요.
1. 새 인덱스 생성 (바뀐 매핑·분석기로)
2. number_of_replicas = 0 ← 복제본 만드는 부담 제거
3. refresh_interval = -1 ← 실시간 검색 갱신 잠시 끔
4. Bulk API로 대량 색인 (23편)
5. 끝나면 force_merge로 세그먼트 정리(선택)
6. replicas·refresh_interval 원래 값으로 복원
이유를 풀면 — 색인 중에는 아직 검색을 안 받는 새 인덱스라, replicas=0·refresh_interval=-1로 복제·실시간 갱신 부담을 꺼서 쓰기에만 집중시켜요. 다 쌓은 뒤 복제본을 만들고 refresh를 켜면 그제야 검색 준비가 끝나죠. 여기서 함정이 하나 있어요 — 복원을 잊으면 새 인덱스가 복제본 0개(장애에 취약)에다 검색 결과가 갱신 안 되는 상태로 운영에 올라가요. 복원은 절차의 일부로 묶어 두세요.
alias로 무중단 전환
풀색인이 끝났어도, 서비스가 어떻게 새 인덱스를 바라보게 하느냐가 남았어요. 여기서 별칭(alias) 이 핵심이에요.
비결은 애플리케이션이 실제 인덱스 이름을 직접 부르지 않는 것이에요. 대신 products 같은 alias를 바라보게 하고, 그 alias가 진짜 인덱스(products_v1)를 가리켜요. 재색인은 이렇게 흘러요.
products(alias) → products_v1 (현재 서비스 중)
① products_v2 새로 만들어 풀색인
② alias를 products_v1 → products_v2 로 원자적 전환
products(alias) → products_v2 (전환 완료, 다운타임 0)
alias 전환은 원자적이라, 애플리케이션은 코드 한 줄 안 바꾸고 다음 검색부터 새 인덱스를 봐요. 문제가 생기면 alias를 다시 _v1으로 되돌리면 끝이라 롤백도 즉시예요. 처음 인덱스를 만들 때부터 alias를 씌워 두는 게 5편 인덱스 관리의 핵심 습관이에요.
검색 서비스는 첫날부터 alias로 시작하세요. 실제 인덱스 이름을 애플리케이션에 박아 두면, 나중에 재색인할 때 코드 배포까지 엮여 무중단 전환이 어려워져요. alias 한 겹이 미래의 재색인을 공짜로 만들어 줍니다.
증분 색인 — 그 사이 바뀐 것만 따라잡기
풀색인에는 시간이 걸려요. 데이터가 많으면 몇십 분씩. 그동안에도 원본 데이터(DB 등)는 계속 바뀌죠. 그래서 풀색인이 끝난 시점과 alias 전환 사이의 변경분을 메워야 해요. 이게 증분 색인이에요.
방법은 원본의 updated_at(수정 시각)이나 version 컬럼을 기준으로, "풀색인 시작 시각 이후 바뀐 행만" 골라 새 인덱스에 추가 반영하는 거예요. 보통은 풀색인 → 증분 색인 한두 번 → alias 전환 순서로 변경분을 따라잡은 뒤 전환해요. 전환 후에도 짧은 증분 색인을 한 번 더 돌려 빈틈을 메우기도 하고요. 전체를 매번 다시 쌓는 풀색인은 무겁고, 평소 운영은 이 증분 색인으로 가볍게 굴립니다.
시험·면접 직전 압축 노트 — 무중단 재색인
- ES는 한 번 색인된 필드 타입·분석기를 대부분 못 바꿈 → 매핑 변경 = 새 인덱스로 재색인
- 재색인 핵심 = 운영 중 검색 무중단
- 풀색인 속도 공식 =
number_of_replicas=0+refresh_interval=-1→ Bulk 색인 →force_merge(선택) → 복원 - replicas·refresh 복원 누락 = 복제본 0·검색 미갱신 상태로 운영 위험
- 무중단 전환 = alias — 앱은
products(alias)를 보고, 실제는products_v1 - alias를
_v1→_v2로 원자적 전환 = 다운타임 0, 롤백도 즉시 - 검색 서비스는 첫날부터 alias로 시작 (실제 인덱스명 직접 호출 금지)
- 증분 색인 =
updated_at/version 기준으로 그 사이 변경분만 따라잡기 - 운영 순서 = 풀색인 → 증분 색인(변경분) → alias 전환 → (필요시 증분 한 번 더)
- 평소 운영은 풀색인 말고 가벼운 증분 색인으로
공식 문서: Tune for indexing speed와 Aliases에서 자세한 절차를 확인할 수 있어요.
시리즈 다른 편
같이 읽으면 좋은 글: