elasticsearch

10 개의 포스트

gitlab4분 읽기큐레이션 요약

GitLab 패치 릴리스: 19.0.1, 18.11.4, 18.10.7 | GitLab Docs

2026년 5월 27일 GitLab은 CE/EE용 패치 릴리스 19.0.1, 18.11.4, 18.10.7을 공개했습니다. 이번 릴리스에는 인증·인가 오류, 정보 노출, 서비스 거부 등 7건의 보안 취약점과 다양한 버그 수정이 포함되어 있어, 영향을 받는 모든 자체 관리형 설치 환경은 즉시 업그레이드하는 것이 권고됩니다. GitLab.com은 이미 패치가 적용됐으며 GitLab Dedicated 고객은 별도 조치가 필요하지 않습니다. ## 릴리스 대상과 업그레이드 권고 - 대상 버전: - GitLab 19.0.1 - GitLab 18.11.4 - GitLab 18.10.7 - CE와 EE 모두에 해당하는 수정이 있으며, 별도 배포 유형이 명시되지 않은 경우 Omnibus, 소스 설치, Helm Chart 등 모든 설치 방식에 영향을 줍니다. - GitLab 패치 릴리스는 일반적으로 매월 둘째·넷째 수요일에 제공되며, 심각한 취약점에는 긴급 패치가 별도로 배포될 수 있습니다. - 보안 취약점의 상세 이슈는 패치된 릴리스가 공개된 뒤 30일 후 이슈 트래커에 공개됩니다. ## Duo AI 워크플로 실행 주체 혼동 - **CVE-2026-4868** - GitLab EE에 영향을 주는 부적절한 접근 제어 취약점입니다. - 인증된 사용자가 특정 조건에서 다른 사용자의 신원으로 Duo AI 워크플로를 실행하도록 만들 수 있었습니다. - CVSS **8.2**로 이번 릴리스에서 가장 심각한 취약점입니다. - 수정 대상: - 18.8 이상 18.10.7 미만 - 18.11 이상 18.11.4 미만 - 19.0 이상 19.0.1 미만 ## Wiki 입력 검증 부족에 따른 서비스 거부 - **CVE-2026-1402** - GitLab CE/EE의 Wiki 기능에서 입력값 검증이 충분하지 않아, 인증된 사용자가 특정 조건에서 서비스 거부를 유발할 수 있었습니다. - CVSS **6.5**입니다. - 17.1부터 18.10.7 미만, 18.11.4 미만, 19.0.1 미만 버전이 영향을 받습니다. ## GraphQL WorkItem API의 비인가 프로젝트 열람 - **CVE-2026-6713** - GraphQL WorkItem API의 권한 검사가 잘못되어, 인증되지 않은 사용자가 비공개 프로젝트를 열거할 수 있었습니다. - 프로젝트 내용 전체가 노출된다는 의미는 아니지만, 비공개 프로젝트의 존재나 식별 정보가 노출될 수 있는 문제입니다. - CVSS **5.3**이며 GitLab CE/EE에 영향을 줍니다. - 수정 버전은 18.10.7, 18.11.4, 19.0.1입니다. ## Duo Workflows 및 Operations 권한 우회 - **CVE-2026-5296** - GitLab EE의 Duo Workflows API 취약점입니다. - 그룹 수준에서 foundational flow가 활성화된 경우, Developer 권한 사용자가 특정 조건에서 워크플로 제한을 우회할 수 있었습니다. - CVSS **4.3**입니다. - **CVE-2026-2601** - GitLab EE Operations 기능의 권한 검사 오류입니다. - Developer 권한 사용자가 다른 프로젝트의 민감한 배포 데이터를 볼 수 있었습니다. - CVSS **4.3**입니다. - 두 취약점 모두 18.10.7, 18.11.4, 19.0.1에서 수정되었습니다. ## CI/CD 및 토큰 인증 관련 취약점 - **CVE-2026-8716** - Pipelines에서 ref 유형 이름을 잘못 해석해, 인증된 사용자가 의도하지 않은 다른 ref의 CI 데이터를 볼 수 있었습니다. - GitLab CE/EE에 영향을 주며 CVSS는 **4.3**입니다. - **CVE-2026-2710** - 차단된 Project Access Token이 특정 인증 엔드포인트를 통해 계속 비공개 리소스에 접근할 수 있었습니다. - GitLab CE/EE에 영향을 주며 CVSS는 **4.3**입니다. - 두 취약점 모두 18.10.7, 18.11.4, 19.0.1에서 해결되었습니다. ## 19.0.1의 주요 버그 수정 - GitLab Credits 대시보드의 평가판 CTA 오류를 수정했습니다. - 작업 토큰의 세분화된 권한에 저장소 쓰기 권한 옵션을 추가했습니다. - Helm 기반 릴리스 환경 QA를 제거했습니다. - API 보안 수정 지침을 릴리스 노트에 반영했습니다. - 19.0 최종 릴리스 관련 변경 사항을 백포트했습니다. ## 18.11.4의 주요 버그 수정 - Ruby 스레드 스케줄러 우선순위 패치를 적용했습니다. - Elasticsearch 인덱서 버전을 5.14.7로 업데이트했습니다. - Zlib를 3.2.3으로 업데이트하고 GitLab Shell을 14.50.0으로 올렸습니다. - Wiki 페이지 이동 시 댓글이 사라지는 문제를 수정했습니다. - 성공한 빌드가 삭제되는 문제와 SyncPolicyWorker 타임아웃 문제를 해결했습니다. - CI/CD 프로젝트 생성 테스트, Epic 보드, swimlane 등 불안정한 기능과 테스트를 수정했습니다. - AI Workflows 범위와 subgroup 프로비저닝 서비스 계정 관련 기능을 보완했습니다. - 파이프라인 취소 및 trace 처리, 다이어그램 프록시의 허용 엔드포인트 전달을 개선했습니다. - 고급 검색 대량 인덱싱에서 기본 데이터베이스 연결을 사용하도록 수정했습니다. - 라이선스 승인 규칙 워크플로의 성능을 개선했습니다. - `num_context_lines=0`일 때 발생하던 off-by-one 오류를 수정했습니다. ## 실용적인 권장 사항 자체 관리형 GitLab 운영자는 현재 지원 중인 브랜치에 맞춰 즉시 19.0.1, 18.11.4 또는 18.10.7로 업그레이드하는 것이 좋습니다. 특히 Duo AI/Workflows, GraphQL WorkItem, Wiki, CI/CD, Project Access Token, Operations 기능을 사용하는 환경은 업그레이드 전까지 권한과 비공개 데이터 접근 로그를 점검해야 합니다.

원문 읽기(새 탭에서 열림)
discord4분 읽기큐레이션 요약

Discord가 대규모로 ScyllaDB 클러스터를 자동화하는 방법

Discord는 수백 개의 ScyllaDB 노드를 소수의 인원이 운영하기 위해, 취약한 스크립트 모음 대신 Scylla Control Plane(SCP)을 구축했다. SCP는 실제 트래픽을 복제하는 shadow cluster를 자동으로 생성·검증해 ScyllaDB 업그레이드와 인프라 변경을 운영 환경에 적용하기 전에 안전하게 테스트한다. 작업을 태스크와 워크플로로 구조화하고, 사전 조건·재시도·상태 저장·병렬성 제어를 제공함으로써 클러스터 구축 시간을 크게 줄이고 실패 시 처음부터 다시 시작해야 하는 문제를 해결하는 것이 핵심이다. ## 대규모 ScyllaDB 운영의 어려움 - Discord의 Persistence Infrastructure 팀은 7명으로 Elasticsearch, Postgres, ScyllaDB 클러스터를 운영한다. - ScyllaDB는 메시지, 채널, 서버, 사용자 데이터 대부분을 저장하며, 수십 개 클러스터와 수백 개 노드로 구성된다. - 주요 운영 작업에는 다음이 포함된다. - 설정 변경 후 롤링 재시작 - 트래픽 증가에 따른 클러스터 확장 - 무중단 운영을 유지한 운영체제 업그레이드 - 새 ScyllaDB 버전을 검증하기 위한 신규 클러스터 생성 - 작업 간 순서와 검증이 중요하기 때문에 단순한 일회성 자동화만으로는 부족하다. ## 기존 스크립트의 한계 - Python과 Bash 스크립트를 점진적으로 추가해 왔지만, 운영 규모가 커지면서 도구가 취약해졌다. - 스크립트가 제공하던 문제점은 다음과 같다. - **안전하지 않음:** 잘못된 순서나 대상 노드에 실행할 수 있고, 실행 전 조건 확인이 부족했다. - **복구 불가능:** 여러 단계 중간에 실패하면 완료한 작업까지 되돌리거나 전체 작업을 처음부터 다시 해야 했다. - **확장하기 어려움:** 새 작업을 추가할 때 기존 스크립트를 복사하고 수정하는 방식이 필요했다. - 운영에 필요한 절차와 노하우가 개별 엔지니어의 경험에 의존했다. ## Shadow Cluster를 통한 안전한 업그레이드 검증 - Shadow cluster는 운영 클러스터의 전체 복제본으로, 짧은 기간 동안 실제 운영 트래픽의 읽기와 쓰기를 함께 처리한다. - 운영 환경에 영향을 주기 전에 다음과 같은 문제를 실제 부하에서 발견할 수 있다. - 특정 ScyllaDB 버전의 예외적인 동작 - 대규모 클러스터에서만 발생하는 버그 - 모든 노드 업그레이드 후에야 나타나는 문제 - 신규 shadow cluster를 수동으로 만들려면 다음 절차를 반복해야 했다. - 노드 프로비저닝 및 설정 - 노드를 클러스터에 순차적으로 조인 - 복제 상태 검증 - dual-write 파이프라인 구성 - 테스트 후 리소스 제거 - Discord는 ScyllaDB 버전뿐 아니라 운영체제와 하드웨어 변경 전에도 shadow cluster를 표준 검증 절차로 활용한다. ## SCP 설계 목표 SCP는 기존 운영 경험에서 얻은 문제를 바탕으로 다음 네 가지 목표를 세웠다. - **확장 가능한 태스크 프레임워크** - 작업의 입력과 실행 로직만 정의하면 기존 오케스트레이션 환경에서 동작하도록 설계한다. - 새로운 개발자가 내부 실행 구조를 모두 이해하지 않아도 새 작업을 추가할 수 있어야 한다. - **설정 가능한 병렬성** - 여러 노드에서 동시에 실행해도 되는 작업과 순차 실행이 필요한 작업을 구분한다. - 예를 들어 서로 다른 availability zone의 노드에서 특정 작업을 동시에 실행하지 않도록 제약을 표현할 수 있다. - **기본적으로 안전한 실행** - 태스크가 실행 전제 조건을 직접 선언한다. - 일시적 오류는 자동으로 재시도한다. - 실행 상태를 저장해 중단된 작업을 완료 지점부터 재개한다. - **점진적 개발과 배포** - 처음부터 거대한 시스템을 만들기보다 사용할 수 있는 기능부터 배포한다. - 실제 클러스터에서 사용하며 온보딩과 사용성 문제를 조기에 발견하고 개선한다. - 사용되지 않는 복잡한 프레임워크를 만드는 일을 피한다. ## SCP의 기본 구조 SCP는 **태스크(task)**, **워크플로(workflow)**, **잡(job)**이라는 계층적 개념을 중심으로 구성된다. - **태스크** - 하나의 구체적인 작업 단위다. - 예: 노드 drain, repair 상태 확인, 정리 작업 실행 - 단일 노드에서 실행되는 **노드 태스크**와 클러스터 전체를 조정하는 **클러스터 태스크**로 나뉜다. - 클러스터 태스크는 여러 노드에서 노드 태스크를 실행하는 역할도 담당한다. - **조건(condition)** - 다음 태스크로 넘어가기 전에 클러스터가 특정 상태에 도달했는지 확인하는 특수한 태스크다. - Scylla API나 Prometheus 메트릭을 주기적으로 조회한다. - 조건이 충족되면 진행하고, 제한 시간 안에 충족되지 않으면 오류를 발생시킨다. - **명시적인 상태 대기** - 노드 재시작 후에는 compaction이 안정될 때까지 기다려야 한다. - 고정된 `sleep`만 사용하면 대기 시간이 너무 짧아 장애를 일으키거나, 너무 길어 전체 롤링 재시작이 불필요하게 느려질 수 있다. - 조건 태스크는 대기 과정을 관찰 가능하고 조정 가능하게 만든다. ## 실용적인 결론 대규모 데이터베이스 운영에서는 개별 스크립트를 계속 늘리기보다, 작업의 선행 조건·재시도·상태 저장·병렬 실행 규칙을 표준화한 오케스트레이션 계층이 필요하다. 특히 운영 트래픽을 재현하는 shadow cluster와 재개 가능한 태스크 프레임워크를 결합하면, 위험한 업그레이드를 자동화하면서도 실패 복구 비용을 크게 줄일 수 있다.

원문 읽기(새 탭에서 열림)
netflix원문

비디오 검색을 위한 멀티모달 인텔리전스 구현 (새 탭에서 열림)

넷플릭스는 방대한 분량의 원본 영상 데이터에서 창작자가 원하는 특정 순간을 신속하게 찾아낼 수 있도록 여러 전문 AI 모델을 결합한 멀티모달(Multimodal) 검색 시스템을 구축했습니다. 이 시스템은 캐릭터, 환경, 대화 등 서로 다른 모델이 생성한 파편화된 신호들을 하나의 통합된 시간축으로 동기화하여 고차원의 문맥 이해와 실시간 검색을 동시에 실현합니다. 결과적으로 수십억 개의 데이터 포인트 속에서도 창작자의 의도에 부합하는 장면을 지연 시간 없이 정확하게 찾아내는 기술적 해결책을 제시합니다. **비디오 검색의 기술적 복잡성과 한계** * **타임라인 통합의 어려움:** 각 모델은 비디오를 서로 다른 간격으로 분석하여 텍스트 레이블이나 벡터 임베딩 등 상이한 형태의 메타데이터를 생성하므로, 이를 하나의 연대기적 지도로 정렬하는 데 막대한 계산 비용이 발생합니다. * **데이터 규모의 폭발:** 2,000시간 분량의 아카이브는 약 2억 1,600만 프레임에 달하며, 이를 여러 모델로 처리할 경우 수십억 개의 레이블과 벡터 데이터가 생성되어 전통적인 데이터베이스로는 처리가 불가능합니다. * **중복 제거와 하이브리드 스코어링:** 시각적으로 유사한 수천 개의 후보 중 최적의 클립을 제안하기 위해, 단순한 수학적 유사도를 넘어 상징적 텍스트 매칭과 의미론적 벡터 검색을 결합한 정교한 랭킹 엔진이 필요합니다. * **제로 프릭션(Zero-Friction) 검색:** 창작 흐름을 방해하지 않기 위해 수십억 개의 레코드를 탐색하면서도 초 단위 미만의 응답 속도를 유지해야 하는 물리적 제약이 존재합니다. **데이터 수집 및 융합 파이프라인 (Ingestion & Fusion)** * **트랜잭션 영속화 (Transactional Persistence):** 고가용성 파이프라인을 통해 수집된 모델의 원본 주석(Annotation)을 Apache Cassandra에 저장합니다. 이 단계에서는 데이터 무결성과 빠른 쓰기 처리량을 최우선으로 하여 모든 모델 출력을 안전하게 확보합니다. * **오프라인 데이터 융합 (Offline Data Fusion):** Apache Kafka를 통해 비동기적으로 실행되며, 파편화된 모델 데이터를 1초 단위의 '시간 버킷(Temporal Buckets)'으로 정규화합니다. 예를 들어 '조이'라는 캐릭터와 '주방'이라는 배경이 겹치는 구간을 하나의 통합 레코드로 병합하여 복합적인 쿼리가 가능하도록 만듭니다. * **실시간 검색 인덱싱:** 융합된 데이터를 Elasticsearch에 인덱싱합니다. 이때 자산 ID와 시간 버킷을 조합한 복합 키(Composite Key)를 사용하여 업서트(Upsert) 방식으로 데이터를 갱신함으로써 데이터 중복을 방지하고 단일 진실 공급원(Single Source of Truth)을 유지합니다. **효율적인 멀티모달 시스템을 위한 제언** 대규모 영상 자산을 관리하는 시스템에서는 원본 데이터를 실시간으로 검색하는 대신, 데이터를 수집-융합-인덱싱 단계로 분리(Decoupling)하여 처리하는 구조가 필수적입니다. 특히 서로 다른 AI 모델의 출력을 공통된 시간 단위(Time Bucketing)로 정규화하여 저장함으로써, 복잡한 다차원 검색 시 발생하는 계산 부하를 오프라인에서 미리 해결하고 사용자에게는 즉각적인 검색 경험을 제공할 수 있습니다.

toss원문

고객은 절대 기다려주지 않는다: 빠른 데이터 서빙으로 고객 만족도를 수직 상승 시키는 법 (새 탭에서 열림)

토스페이먼츠는 가파른 성장세에 따른 데이터 조회 부하를 해결하기 위해 CQRS 아키텍처를 도입하고 Apache Druid를 중심으로 한 데이터 서빙 환경을 구축했습니다. 초기에는 Elasticsearch와 Druid를 결합하여 대규모 시계열 데이터의 실시간 집계와 검색 성능을 확보했으며, 이를 통해 비용 효율성과 시스템 안정성을 동시에 달성했습니다. 현재는 Druid의 조인 제약과 멱등성 문제를 해결하기 위해 StarRocks를 도입하며, 도메인 간 결합이 자유로운 통합 원장 시스템으로 진화하고 있습니다. ### CQRS와 Apache Druid 도입 배경 * **MSA 전환과 DB 분리:** 서비스 규모가 커지며 모놀리식에서 MSA로 전환했으나, DB가 분산되면서 도메인 간 조인이나 통합 조회가 어려워지는 문제가 발생했습니다. * **명령과 조회의 분리:** 읽기 전용 저장소로 Apache Druid를 선택하여 원장 DB(MySQL)의 부하를 줄이고, 수십억 건의 데이터를 저지연으로 조회하는 CQRS 구조를 설계했습니다. * **Druid의 기술적 이점:** 시계열 데이터 최적화, SQL 지원을 통한 낮은 러닝 커브, 모든 컬럼의 비트맵 인덱스(Bitmap Index)화, 그리고 클라우드 네이티브 구조를 통한 비용 효율성을 고려했습니다. ### 데이터 가공 및 메시지 발행 방식 * **CDC 대신 메시지 발행 선택:** 데이터팀이 도메인 로직을 직접 소유해야 하는 CDC 방식 대신, 각 도메인 팀에서 완성된 데이터를 발행하는 방식을 채택하여 시스템 의존성을 Kafka로 단순화했습니다. * **역정규화 테이블 구성:** 복잡한 수단별 원장 데이터를 조회 친화적인 역정규화 테이블로 변환하여 적재했으며, JSON 필드 단위까지 비트맵 인덱스가 생성되어 효율적인 질의가 가능해졌습니다. ### AWS 환경에서의 비용 및 성능 최적화 * **컴퓨팅과 스토리지 분리:** 고가의 네트워크 스토리지(EBS) 대신 S3를 영구 저장소로 활용하고, 쿼리 수행 시에는 로컬 SSD를 사용하여 성능을 9배 이상 향상했습니다. * **스팟 인스턴스 활용:** 데이터가 S3에 안전하게 보관되는 특성을 이용해 개발/테스트 환경에서 스팟 인스턴스를 적극적으로 사용하여 월 5,000만 원 이상의 클라우드 비용을 절감했습니다. * **고가용성 확보:** 네트워크 스토리지 의존성을 제거함으로써 가용 영역(AZ) 간 분산 배치가 유연해져 시스템의 안정성을 높였습니다. ### Druid 운영의 기술적 도전과 극복 * **파편화 및 멱등성 문제:** 데이터가 시점별로 분산되는 파편화 현상을 해결하기 위해 60초 주기 탐지 프로세스와 자동 컴팩션(Compaction)을 도입했습니다. * **Rollup을 통한 성능 극대화:** 동일 차원의 데이터를 자동 집계하여 저장하는 Rollup 기능을 적용해, 수십 초 걸리던 집계 쿼리 응답 속도를 0.5~1초 내외로 99% 이상 개선했습니다. * **ES 하이브리드 아키텍처:** 단일 ID 기반의 고속 검색은 Elasticsearch가 담당하고, 필터링된 결과의 대규모 집계는 Druid가 처리하도록 역할을 분담해 검색 성능을 안정화했습니다. ### StarRocks 도입을 통한 통합 원장 구축 * **조인 및 멱등성 한계 극복:** Druid의 제한적인 조인 기능과 멱등성 처리의 어려움을 해결하기 위해 StarRocks를 새롭게 도입했습니다. * **도메인 간 데이터 결합:** 결제부터 매입, 정산까지 이르는 전체 라이프사이클을 한눈에 볼 수 있는 통합 원장을 구현하여 비즈니스 요구사항에 유연하게 대응하고 있습니다. **결론적으로** 대규모 트래픽 환경에서는 단순한 DB 분리를 넘어 검색(ES), 시계열 집계(Druid), 그리고 복잡한 조인과 멱등성 보장(StarRocks)이라는 각 도구의 장점을 살린 하이브리드 아키텍처 설계가 필수적입니다. 특히 스토리지와 컴퓨팅을 분리한 구조는 비용 절감뿐만 아니라 운영의 유연성을 확보하는 핵심 전략이 됩니다.

daangn원문

당근 검색 엔진, 쿠버네티스로 쉽게 운영하기 2편 — 데이터 노드 웜업 적용 (새 탭에서 열림)

당근 검색 플랫폼팀은 쿠버네티스(ECK) 환경에서 Elasticsearch 클러스터를 운영하며, 롤링 리스타트 시 발생하는 레이턴시 급증 문제를 해결하기 위해 '데이터 노드 웜업(Warmup)' 시스템을 구축했습니다. 단순히 Pod가 실행되는 것을 넘어 샤드 복구와 캐시 예열이 완료된 후에만 다음 노드를 재시작하도록 제어함으로써, 피크 타임에도 서비스 영향 없이 안정적인 배포가 가능해졌습니다. 이를 통해 운영자의 모니터링 부담을 제거하고 언제든 안심하고 배포할 수 있는 환경을 마련했습니다. **롤링 리스타트와 콜드 캐시의 위험성** * Elasticsearch는 페이지 캐시, 쿼리 캐시 등 다양한 메모리 캐시에 크게 의존하므로, 재시작 직후 캐시가 비어 있는 '콜드 캐시' 상태에서는 성능이 급격히 저하됩니다. * 쿠버네티스의 기본 롤링 업데이트는 Pod의 준비 상태(Ready)만 확인하고 다음 노드를 재시작하기 때문에, 준비되지 않은 노드에 트래픽이 몰리며 전체 검색 레이턴시가 수 초까지 치솟는 장애가 발생할 수 있습니다. * 노드 한 대가 내려간 동안 남은 노드들이 모든 부하를 감당해야 하며, 복제본(Replica) 샤드가 없는 상태에서 다른 노드에 문제가 생기면 클러스터가 'Red' 상태로 변해 가용성이 무너질 위험이 큽니다. **안전한 배포를 위한 단계별 웜업 전략** * 목표는 배포 중에도 P99 레이턴시를 평소 수준으로 유지하고, 클러스터 상태가 'Yellow'에서 다시 'Green'이 된 것을 확인한 후 다음 단계로 넘어가는 것입니다. * 이를 위해 노드 재시작 후 세 가지 단계를 거칩니다: 1) 데이터 노드가 클러스터에 정상 합류할 때까지 대기, 2) 할당된 샤드들의 데이터 복구(Recovery) 완료 확인, 3) 실제 검색 쿼리를 미리 실행하여 캐시를 채우는 과정입니다. * 특히 샤드 복구가 완료되지 않은 상태에서 웜업을 시작하면 데이터가 없는 상태에서 쿼리를 날리는 꼴이 되므로, 반드시 인덱싱 상태를 모니터링하는 로직이 포함되어야 합니다. **사이드카 패턴 기반의 웜업 시스템 구현** * Elasticsearch 컨테이너와 함께 실행되는 별도의 `warmup-sidecar`를 도입하여 노드의 상태를 정밀하게 추적합니다. * 사이드카는 API를 통해 해당 노드의 샤드들이 모두 'Started' 상태인지 확인하고, 실제 운영 환경에서 발생하는 검색 트래픽(Traffic Replay)을 신규 노드에 미리 쏘아주어 메모리에 데이터를 올립니다. * 이 모든 과정이 완료되어야만 쿠버네티스의 Readiness Probe를 통과하게 설계하여, ECK 오퍼레이터가 노드 웜업이 끝날 때까지 다음 Pod의 재시작을 자동으로 대기하도록 제어했습니다. 대규모 트래픽을 처리하는 상태 기반(Stateful) 시스템에서는 인프라 수준의 단순한 헬스체크만으로는 부족하며, 애플리케이션 내부의 데이터 준비 상태를 고려한 정교한 배포 전략이 필수적입니다. 데이터 노드 웜업 도입으로 배포 시간은 기존보다 길어졌지만, 시간에 구애받지 않고 24시간 언제든 안전하게 시스템을 업데이트할 수 있는 운영 안정성을 확보하게 되었습니다.

toss원문

100년 가는 프론트엔드 코드, SDK (새 탭에서 열림)

토스페이먼츠는 결제 연동의 복잡성을 해결하기 위해 SDK를 제공하고 있으며, 최근 V1의 한계를 극복하고 안정성과 확장성을 극대화한 V2 SDK를 구축했습니다. 가맹점의 다양한 런타임 환경과 예측 불가능한 요구사항에 대응하기 위해 단순한 기능 구현을 넘어 체계적인 아키텍처와 모니터링 시스템을 도입했습니다. 결과적으로 개발자에게는 쉬운 연동 경험을, 비즈니스에는 견고한 신뢰성을 제공하는 결제 생태계를 완성했습니다. **SDK 개발의 특수성과 V1의 한계** * **환경의 의존성:** SDK는 가맹점의 코드 내에서 실행되므로, 가맹점의 호출 빈도나 네트워크 상태에 직접적인 영향을 받습니다. 일례로 사용량 분석을 위해 추가한 로그 코드가 특정 가맹점의 잦은 호출과 맞물려 네트워크 병목 현상을 일으키고 서비스 전체를 다운시키는 사례가 발생했습니다. * **런타임 예측 불가능성:** 가맹점에서 잘못된 데이터 타입(예: String 대신 Number)을 전달할 경우 `startsWith` 같은 표준 메서드에서 에러가 발생하는 등, 일반적인 프론트엔드 개발보다 훨씬 방어적인 코딩이 요구됩니다. * **커뮤니케이션의 접점:** SDK는 단순히 API를 호출하는 도구가 아니라 가맹점 개발자와 만나는 기술적 창구이며, 가맹점의 수많은 커스텀 요구사항을 수용해야 하는 복잡성을 안고 있습니다. **안정성 확보를 위한 테스트와 모니터링** * **촘촘한 테스트 체계:** 로직 검증을 위한 300개 이상의 단위 테스트와 다양한 유즈케이스를 반영한 500개 이상의 E2E 통합 테스트를 통해 코드 수준의 안정성을 확보했습니다. * **Global Trace ID:** 프론트엔드부터 백엔드까지 결제 전 과정을 하나의 식별자로 추적하는 체계를 도입하여, 장애 발생 시 시스템 레이어 전체를 쉽게 파악할 수 있도록 했습니다. * **모니터링 CLI:** 배포 전후의 결제 성공률을 가맹점 및 런타임 환경(OS, 브라우저, 웹뷰 등)별로 비교 분석하는 자체 도구를 개발했습니다. 이를 통해 특정 환경에서 발생하는 결제 중단 현상을 실시간으로 탐지하고 즉각 대응합니다. **확장성을 위한 레이어드 아키텍처** * **조립 가능한 구조:** 특정 가맹점만을 위한 예외 처리가 `if`문으로 산재되어 코드 복잡도가 올라가는 문제를 해결하기 위해, 기능을 레고 블록처럼 독립적으로 구성했습니다. * **3계층 분리:** "변경의 원인"을 기준으로 코드의 경계를 명확히 나누어 관리합니다. * **Public Interface Layer:** 가맹점과 약속한 인터페이스를 검증하고 도메인 언어로 번역하는 역할 * **Domain Layer:** 핵심 비즈니스 로직과 결제 정책을 담당하는 중심부 * **External Service Layer:** 서버 API나 Web API 등 외부 의존성과의 통신을 담당하는 계층 * **관심사 격리:** 이러한 계층화를 통해 가맹점별 커스텀 요구사항이 추가되더라도 기존의 핵심 로직에 영향을 주지 않고 특정 블록만 교체하거나 확장할 수 있는 유연성을 확보했습니다. 성공적인 SDK 개발을 위해서는 단순히 편리한 기능을 제공하는 것을 넘어, 타사의 코드 환경에서도 견고하게 동작할 수 있는 방어적인 설계와 문제 발생 시 즉시 원인을 파악할 수 있는 관측성(Observability) 확보가 필수적입니다. 가맹점별 특이 케이스를 코드 전반에 흩뿌리기보다는, 명확한 레이어 구분을 통해 비즈니스 로직과 커스텀 로직을 분리하는 설계 원칙을 권장합니다.

datadog원문

복제의 재정의: 저지연 멀티테넌트 데이터 복제 플랫폼 구축기 (새 탭에서 열림)

데이터독(Datadog)은 모놀리식 포스트그레스(Postgres) 데이터베이스의 확장성 한계와 수동 데이터 파이프라인의 복잡성을 해결하기 위해 자동화된 관리형 데이터 복제 플랫폼을 구축했습니다. 이 플랫폼은 체계적인 변경 데이터 캡처(CDC)와 비동기 복제 방식을 통해 데이터 일관성을 유지하면서도 시스템 성능을 비약적으로 향상시켰습니다. 결과적으로 엔지니어링 팀은 인프라 관리의 부담에서 벗어나 안정적이고 낮은 지연 시간으로 대규모 데이터를 다양한 서비스 간에 자유롭게 이동시킬 수 있게 되었습니다. **포스트그레스의 확장성 한계와 데이터 재건축** * 서비스 초기에는 포스트그레스의 ACID 보장과 편의성이 유용했으나, 데이터량이 증가하면서 복잡한 조인 및 집계 쿼리의 응답 시간이 수 밀리초에서 수 초 단위로 급격히 악화되었습니다. * 특정 조직의 메트릭 요약 페이지에서 수십만 개의 행을 조인할 때 P90 지연 시간이 7초에 달했으며, 인덱스 팽창(Bloat)과 VACUUM 작업 부하로 인한 I/O 병목 현상이 발생했습니다. * OLTP 부하와 검색/필터링 부하를 분리하기 위해, 복제 과정에서 데이터를 비정규화(Denormalization)하여 전용 검색 플랫폼으로 전송하는 아키텍처로 전환했습니다. * 이러한 최적화를 통해 페이지 로드 시간을 최대 97% 단축(30초 → 1초)하고, 복제 지연 시간을 500ms 수준으로 유지하는 성과를 거두었습니다. **Temporal을 활용한 복제 파이프라인 프로비저닝 자동화** * Debezium, Kafka, Elasticsearch 등 다양한 기술 스택이 결합된 복제 파이프라인을 수동으로 구축하는 과정은 운영상 큰 부담이 되었습니다. * 포스트그레스의 `wal_level` 설정, 논리적 복제 슬롯 생성, 사용자 권한 관리, Kafka 토픽 매핑 등 반복적이고 오류가 잦은 단계를 Temporal 워크플로우를 통해 모듈화했습니다. * WAL(Write-Ahead Log) 보존 문제를 해결하기 위한 하트비트 테이블 설정부터 싱크 커넥터 배포까지의 모든 과정을 오케스트레이션하여 운영 탄력성을 높였습니다. * 자동화된 플랫폼 덕분에 개발자들은 인프라 설정 대신 혁신에 집중할 수 있게 되었으며, 멀티 테넌트 환경에서도 일관된 파이프라인 관리가 가능해졌습니다. **성능과 확장성을 위한 비동기 복제 전략** * 강한 일관성을 보장하는 동기 복제 대신, 대규모 고처리량 환경에 적합한 비동기 복제 방식을 채택했습니다. * 동기 복제는 네트워크 지연이나 복제본의 응답 상태가 기본 시스템의 성능에 직접적인 영향을 주지만, 비동기 방식은 애플리케이션의 쓰기 성능을 네트워크 지연으로부터 격리합니다. * 장애 발생 시 미세한 데이터 지연이 발생할 수 있는 트레이드오프가 있으나, 이는 확장성과 가용성을 우선시하는 데이터독의 분산 환경에 더 적합한 선택이었습니다. **결론 및 권장사항** 대규모 시스템에서 데이터베이스의 성능 저하를 방지하려면 OLTP와 읽기 전용 검색 워크로드를 분리하는 것이 필수적입니다. 이때 발생하는 복잡한 데이터 이동 문제는 Temporal과 같은 워크플로우 엔진으로 자동화하여 운영 비용을 낮추고, 비동기 복제 모델을 통해 시스템의 전체적인 처리량과 가용성을 확보하는 전략이 권장됩니다.

discord4분 읽기큐레이션 요약

디스코드가 수조 개의

Discord는 메시지 검색을 Elasticsearch 기반으로 운영했지만, 메시지와 트래픽이 조 단위로 증가하면서 Redis 큐 유실, 장애에 취약한 벌크 색인, 대규모 클러스터의 운영 부담, 단일 인덱스의 문서 수 제한 문제가 발생했다. 이를 해결하기 위해 Kubernetes와 Elastic Kubernetes Operator(ECK)를 도입하고, 거대한 클러스터 대신 여러 개의 작은 클러스터를 운영하는 셀(cell) 아키텍처로 전환하려 했다. 목표는 장애 격리, 무중단 업그레이드, 확장성, 비용 효율성을 동시에 확보하는 것이었다. ## 기존 메시지 검색 구조 - 2017년 Discord는 Elasticsearch에 메시지를 색인했다. - 메시지는 Discord 서버(guild) 또는 DM 단위로 Elasticsearch 인덱스에 분산했다. - 같은 guild의 메시지를 한곳에 모아 검색 속도를 높였다. - 클러스터를 여러 개로 나누어 관리 가능한 규모를 유지했다. - 사용자가 검색을 이용하지 않는 경우를 고려해 메시지는 지연 색인(lazy indexing)했다. - Redis 기반 메시지 큐와 작업자가 메시지를 묶음으로 가져와 Elasticsearch 벌크 색인을 수행했다. ## Redis 메시지 큐의 메시지 유실 - Elasticsearch 장애로 색인 작업이 밀리면 Redis 큐에 메시지가 빠르게 쌓였다. - 큐가 과도하게 커지면서 Redis CPU 사용량이 한계에 도달했고, 결국 메시지가 유실됐다. - 즉, 색인 대상 메시지를 안정적으로 보관해야 할 큐 자체가 장애 지점이 되었다. ## 장애에 취약한 벌크 색인 - 한 번의 벌크 요청에 서로 다른 인덱스와 Elasticsearch 노드에 속한 메시지가 함께 포함됐다. - 예를 들어 50개 메시지를 색인하는 요청이 최대 50개 노드로 분산될 수 있었다. - 그중 단 하나의 노드라도 실패하면 벌크 요청 전체가 실패하고, 모든 메시지를 다시 큐에 넣어 재시도해야 했다. - 100개 노드 클러스터에서 50개 메시지를 무작위로 색인할 때, 특정 노드 하나가 장애 나면 요청 중 약 40%가 실패할 수 있었다. - 실제 장애 하나가 색인 실패와 재시도를 대량으로 유발해 Redis 큐 적체를 악화시켰다. ## 대규모 Elasticsearch 클러스터의 운영 부담 - 메시지와 guild 수가 증가할 때 노드와 인덱스를 추가하는 방식으로 수평 확장했다. - 하지만 클러스터가 커질수록 하나의 벌크 작업이 더 많은 인덱스와 노드로 분산됐다. - 이로 인해 노드 간 조정과 네트워크 팬아웃 비용이 커져 색인 성능이 저하됐다. - 노드 수가 많아질수록 어느 한 노드에서 장애가 발생할 가능성도 증가했다. ## 롤링 재시작과 보안 업데이트의 어려움 - 단일 노드 장애에도 색인 시스템이 크게 영향을 받았기 때문에 안전한 롤링 재시작이 어려웠다. - 200개가 넘는 노드와 수 테라바이트의 데이터를 가진 클러스터를 노드별로 비우고 재시작하는 데 지나치게 오랜 시간이 걸렸다. - 그 결과 오래된 운영체제와 Elasticsearch 버전을 계속 사용해야 했고, 보안 패치와 성능 개선을 적용하지 못했다. - Log4Shell 대응 당시에는 `log4j2.formatMsgNoLookups=true` 설정을 적용하기 위해 전체 검색 시스템을 중단하고 모든 노드를 재시작해야 했다. ## 대형 guild의 인덱스 크기 제한 - 일부 인덱스에는 매우 큰 guild의 메시지가 집중됐다. - Elasticsearch 인덱스는 내부적으로 하나의 Lucene 인덱스이며, 약 20억 개 문서라는 `MAX_DOC` 제한이 있다. - 이 한도에 도달하면 해당 인덱스의 모든 색인 작업이 실패한다. - 당시에는 Safety 팀과 협력해 스팸 목적의 guild를 찾아 삭제하는 방식으로 복구했다. - 그러나 정상적인 대규모 커뮤니티가 20억 개 이상의 메시지를 축적하는 상황도 지원해야 했다. ## Kubernetes와 Elastic Operator 도입 - Discord는 무상태 서비스 운영에서 이미 Kubernetes의 편의성과 비용 최적화 효과를 경험하고 있었다. - 이후 Elasticsearch 같은 상태 저장 서비스에도 Elastic Kubernetes Operator(ECK)를 적용하는 방안을 선택했다. - ECK를 사용하면 다음을 선언적으로 관리할 수 있다. - Elasticsearch 클러스터 토폴로지 - 노드 구성과 설정 - Kubernetes 노드풀 위의 클러스터 배포 - 운영체제 업그레이드를 자동화하고, 안전한 롤링 재시작과 Elasticsearch 업그레이드 도구를 활용할 수 있게 됐다. ## 여러 소형 클러스터를 사용하는 셀 아키텍처 - 기존처럼 200개가 넘는 노드를 가진 거대한 클러스터 하나를 운영하는 대신, 더 많은 수의 작은 Elasticsearch 클러스터를 운영하는 구조를 구상했다. - 작은 클러스터는 다음과 같은 이점을 제공한다. - 장애 범위 축소 - 클러스터 자체의 조정 오버헤드 감소 - 노드 장애가 전체 검색 시스템에 미치는 영향 완화 - 업그레이드와 유지보수의 단순화 - Kubernetes와 ECK를 기반으로 이러한 클러스터들을 표준화하고 운영하려 했다. 대규모 검색 시스템에서는 단순히 노드를 추가하는 것보다 장애 격리와 운영 가능성을 함께 설계하는 것이 중요하다. 특히 벌크 작업을 부분 실패에 강하게 만들고, 클러스터를 작은 단위로 나누며, 롤링 업그레이드가 가능한 플랫폼을 채택하는 것이 장기적인 안정성에 유리하다.

원문 읽기(새 탭에서 열림)
figma3분 읽기큐레이션 요약

Figma에서의 속도 탐

Figma는 검색 지연의 원인을 OpenSearch 자체의 검색 속도보다 쿼리 전후 처리와 잘못된 모니터링 지표에서 발견했다. OpenSearch가 보고한 평균 8ms는 전체 검색 시간이 아니라 개별 샤드 쿼리 시간에 불과했으며, 실제 애플리케이션 호출은 평균 150ms에 달했다. 조사 결과 권한 필터를 만드는 사전 처리와 검색 결과를 검증하는 사후 처리가 전체 시간의 대부분을 차지했고, 이를 개선하는 것이 확장 가능한 검색 기반을 마련하는 핵심이었다. ## OpenSearch 마이그레이션과 검색 성능 문제 - Figma는 2023년 말까지 오래된 Elasticsearch 버전을 사용하다가 AWS 관리형 OpenSearch로 이전하기 시작했다. - OpenSearch는 Elasticsearch의 라이선스 변경 이후 분기된 프로젝트로, 기본적으로 호환되지만 3년간 세부적인 차이가 누적되어 마이그레이션이 예상보다 어려웠다. - 사용자와 데이터가 증가하면서 검색 시스템이 원하는 콘텐츠를 안정적으로 찾기 어려워졌고, 장기적인 확장을 위한 검색 인프라 재정비가 필요해졌다. ## 잘못 해석한 8ms 지표 - Datadog의 OpenSearch 연동에서는 평균 검색 시간이 약 8ms로 나타났다. - 하지만 Figma 검색 API의 p99 지연 시간은 거의 1초였고, 애플리케이션에서 OpenSearch API를 호출하는 데 걸린 시간은 다음과 같았다. - 평균 약 150ms - p99 약 200~400ms - 최소 지연 시간도 40ms 이상 - OpenSearch와 애플리케이션이 같은 AWS 가용 영역에서 실행되고 있었기 때문에 네트워크 지연만으로는 이 차이를 설명할 수 없었다. - 원인은 8ms가 전체 검색 시간이 아니라 **각 샤드에서 실행된 개별 쿼리의 평균 시간**이었기 때문이다. ## OpenSearch의 쿼리 및 fetch 단계 - 검색 요청은 먼저 coordinator 노드에 전달된다. - coordinator 노드는 인덱스의 각 샤드가 있는 worker 노드에 쿼리를 보낸다. - 이 과정이 OpenSearch의 **query 단계**다. - coordinator는 각 샤드의 결과를 수집하고 정렬한 뒤, 상위 결과에 대한 상세 정보를 다시 요청한다. - 이 후속 과정이 **fetch 단계**이며, 최종 결과가 클라이언트에 반환된다. - Figma의 초기 구성에서는 사용자 검색 하나가 최대 500개의 샤드 쿼리를 발생시킬 수 있었다. - 샤드 쿼리 대부분은 병렬 실행되지만 모두 동시에 처리되는 것은 아니므로, 개별 샤드 시간과 전체 검색 시간 사이에 큰 차이가 발생했다. ## 전체 검색 시간을 측정하도록 계측 개선 - Figma는 검색 코드의 주요 구간에 메트릭과 트레이스를 추가했다. - 조사 결과 OpenSearch가 보고하는 지표와 실제 API 호출 시간 사이에 큰 불일치가 있음을 확인했다. - OpenSearch의 기본 메트릭과 로그에는 coordinator 관점의 전체 쿼리 시간이 포함되지 않았다. - 전체 검색 시간은 검색 API 응답의 `took` 필드에만 제공됐다. - Figma는 모든 검색 응답에서 `took` 값을 추출해 모니터링 시스템에 추가했고, 이를 통해 실제 백엔드 검색 지연을 보다 정확하게 파악했다. ## 병목은 OpenSearch 검색 자체가 아니었다 - 실제로 OpenSearch에서 검색을 기다리는 시간은 전체 쿼리 API 시간의 30% 미만이었다. - 나머지 시간은 검색 전후의 애플리케이션 처리에 사용됐다. - **사전 처리** - 사용자가 접근할 수 있는 파일 관련 정보를 조회한다. - 접근 권한이 없는 파일을 대부분 제외하도록 OpenSearch 필터 절을 생성한다. - **사후 처리** - OpenSearch가 반환한 각 파일 결과에 대해 사용자의 실제 접근 권한을 다시 확인한다. - 권한 검증을 통해 사용자가 볼 수 없는 파일이 검색 결과에 포함되지 않도록 보장한다. - 특히 사후 처리가 매우 느렸으며, Figma는 권한 시스템과 협력해 이 부분을 개선하기 시작했다. 검색 성능을 개선하려면 검색 엔진이 표시하는 단일 지표만 믿지 말고, coordinator부터 애플리케이션의 사전·사후 처리까지 전체 요청 경로를 측정해야 한다. Figma 사례처럼 샤드별 지연 시간보다 실제 사용자 요청의 전체 지연 시간을 기준으로 병목을 찾아야 하며, 권한 필터 생성과 결과 검증도 검색 성능의 핵심 구성 요소로 다뤄야 한다.

원문 읽기(새 탭에서 열림)
figma3분 읽기큐레이션 요약

딥 서치 심층 분석 | 피

Figma의 Deep Search는 파일명이나 폴더명을 몰라도 파일 내부의 텍스트와 내용을 검색할 수 있도록 만든 기능이다. 일반 검색이 데이터베이스의 메타데이터를 색인하는 것과 달리, Deep Search는 S3에 저장된 `.fig` 파일을 직접 읽고 객체 트리를 순회해야 한다. 이를 위해 기존 Design System Analytics 인프라를 확장하고, 처리 비용과 최신성 사이에서 타협해 변경 사항을 시간 단위로 모아 색인하는 방식을 선택했다. ## 브라우저 기반 제품이 제공하는 검색 가능성 - Figma는 데스크톱 애플리케이션이 아닌 브라우저 기반 도구이므로, 사용자가 접근할 수 있는 파일에 대한 풍부한 정보를 수집하고 분석할 수 있다. - 파일의 조회 빈도, 컴포넌트 사용량, 파일 구조 등 웹 환경에 적합한 데이터를 활용할 수 있다. - 이러한 특성은 협업을 강화한다. - 별도 파일을 내보내지 않아도 이해관계자가 진행 중인 작업을 확인할 수 있다. - 프로토타입 공유와 핸드오프가 간소화된다. - 작업 중인 결과물을 쉽게 공유할 수 있다. - Deep Search는 파일명보다 프로젝트의 아이디어, 문구, 해결하려던 문제를 기억하는 사용자의 검색 방식에 맞춘 기능으로 기획됐다. ## Design System Analytics에서 얻은 기술적 기반 - Figma는 앞서 Design System Analytics(DSA)를 출시해 팀 간 디자인 시스템과 공유 라이브러리의 사용 현황을 분석했다. - DSA와 Deep Search 모두 다음과 같은 공통 처리가 필요했다. - 최근 수정된 파일을 식별한다. - 스토리지에서 파일을 내려받는다. - 파일 내부를 순회한다. - 목적에 맞는 정보를 추출한다. - DSA는 공유 라이브러리 사용량을 추출하고, Deep Search는 파일 내부의 텍스트를 추출한다. - Figma는 DSA를 위해 만든 파일 분석 인프라와 워커를 일반화해 Deep Search의 기반으로 활용했다. ## 일반 검색의 색인 파이프라인 - 기존 Unified Search를 포함한 일반 검색은 데이터베이스에 저장된 메타데이터를 대상으로 한다. - 예시로 파일 ID, 폴더 ID, 팀 ID, 파일명, 폴더명, 생성자 등의 정보를 사용한다. - 처리 과정은 다음과 같다. - 데이터베이스의 관련 테이블 변경 사항을 감시한다. - 변경된 항목의 ID를 메시징 시스템으로 전달한다. - 검색 색인기가 최신 데이터를 데이터베이스에서 가져온다. - 가져온 메타데이터를 Elasticsearch 클러스터에 색인한다. - 데이터베이스 조회는 비교적 저렴하기 때문에 변경될 때마다 빠르게 색인을 갱신할 수 있다. ## Deep Search가 더 복잡한 이유 - Figma 파일의 실제 표현은 데이터베이스가 아니라 Amazon S3에 저장된 `.fig` 문서다. - `.fig` 파일은 트리 구조로 구성된다. - 각 노드는 타원, 프레임, 벡터, 텍스트 같은 Figma 객체를 나타낸다. - 노드에는 객체의 속성과 콘텐츠가 함께 저장된다. - Deep Search는 파일의 메타데이터만 확인하는 것이 아니라, S3에서 파일을 가져온 뒤 전체 객체 트리를 순회해야 한다. - 하나의 파일에 수천 개의 노드가 있을 수 있어 파일을 읽고 분석하는 작업은 일반적인 데이터베이스 조회보다 훨씬 계산 비용이 크다. ## 처리 비용과 검색 최신성 사이의 타협 - Figma 파일은 편집 중에도 약 30초마다 자동 저장될 수 있다. - 저장될 때마다 Deep Search 색인을 갱신하면 같은 파일을 반복적으로 내려받고 분석하게 되어 서버 비용이 크게 증가한다. - Figma는 이를 해결하기 위해 파일 변경 사항을 한 시간 동안 중복 제거한다. - 이후 변경된 파일을 파일 분석 워커로 보내 주기적으로 처리한다. - 그 결과 Deep Search 결과가 일반 검색보다 잠시 오래된 상태일 수 있지만, 반복적인 파일 분석을 줄여 상당한 서버 자원을 절약할 수 있다. - 이는 검색 결과의 즉시성보다 시스템 비용과 확장성을 우선한 제품·인프라상의 결정이다. ## 실용적인 결론 대용량 문서나 복잡한 구조를 검색할 때는 모든 변경을 즉시 처리하기보다 변경 사항을 모아 중복 작업을 제거하는 방식이 효율적이다. 검색 결과가 수초 또는 수분 정도 지연되어도 괜찮다면, 배치 처리와 주기적 색인을 통해 계산 비용과 인프라 부담을 크게 줄일 수 있다.

원문 읽기(새 탭에서 열림)