출처:

How we catch and mitigate performance regressions at scale in Jira Cloud

작성자:
James Parkyn (Software Engineer)



Jira Cloud처럼 규모가 크고 멀티 테넌트(Multi-tenant) 구조를 가진 제품에서는,

시스템 어디에서든 발생한 “작은” 변경이 전체 지표에 이상으로 나타나기 전에 일부 주요 고객에게 문제를 야기할 수 있습니다.

Feature flag(기능 플래그), 점진적 롤아웃, 테넌트별 데이터와 트래픽 형태로 인해 이러한 성능 저하는 Jira의 일부 영역(예: 3개 테넌트에서 관리자 사용자에게만 해당되는 특정 엔드포인트)에만 영향을 미치는 경우가 많습니다.

이처럼 영향 범위가 매우 제한적이기 때문에 문제를 발견하기도 어렵고, 원인을 파악하는 것은 더 까다롭습니다.


이번 글에서는 Jira에서 테넌트별·엔드포인트별로 성능 저하를 감지하는 시스템을 어떻게 구축했는지, 그리고 이를 Rovo Dev CLI와 연동해 단순히 특정 부분이 느려졌다는 것뿐 아니라 왜 느려졌는지까지 빠르게 파악할 수 있는 방법을 살펴봅니다.

지난 몇 달 동안 이 시스템 덕분에 8건 이상의 프로덕션 환경 성능 저하 문제를 감지하고 해결하여 성능 악화를 방지하는 동시에 지속적인 성능 개선 투자를 진행할 수 있었습니다.


Regression(성능 회귀)이란?

먼저 몇 가지 정의를 살펴보겠습니다:

회귀란 성능(예: 엔드포인트 지연 시간)이 기존 기준선보다 성능이 저하되는 경우를 의미합니다.

기준선이란 회귀가 발생하기 전에 측정된 "정상" 성능을 의미합니다.



테넌트에 따라 크게 달라지는 Jira 성능

Jira Cloud는 수백만 개의 테넌트를 지원하며, 각 테넌트는 다양한 형태를 가질 수 있습니다: 

  • 데이터 형태(이슈 수, 필드 설정, 변경 이력 등)

  • 트래픽 패턴(변동이 큰 트래픽 vs 안정적인 트래픽, 글로벌 팀 vs 로컬 팀)

  • 애드온 및 구성

  • 네트워크 환경 및 클라이언트 하드웨어


이러한 차이들로 인해 성능은 테넌트별뿐만 아니라 프로젝트별로도 크게 달라집니다.

대부분의 테넌트(99.99%)에서는 문제가 되지 않는 변경이라도, 규모나 사용 패턴이 극단적인 일부 테넌트(0.01%)에는 크게 영향을 줄 수 있습니다.


상위 10,000 개 고객에서 하나의 백엔드 엔드포인트 지연 시간 변동

끊임없는 변경

Jira에서는 매일 많은 변경이 발생합니다:

  • 수십에서 수백 건의 PR이 병합됩니다.

  • Feature flag 변경이 수천 건 이루어집니다.

  • 인프라와 의존 관계도 지속적으로 변화합니다.

  • 고객은 사용량을 늘리거나 줄이고, 자동화를 추가하며, 타사 도구를 설치할 수 있습니다.


이러한 변경 하나하나는 성능을 악화시킬 수 있는 작은 위험을 가지고 있으며, 그중 일부는 소수의 테넌트에만 영향을 미칩니다:

예를 들어, 일부 대규모 엔터프라이즈 고객이나 특정 구성과 데이터 조합을 가진 테넌트가 여기에 해당합니다.

이러한 상황이 발생할 때마다, 문제가 누적되지 않도록 반드시 이를 감지하고 회귀 오류를 해결해야 합니다.

“글로벌” 모니터링만으로는 충분하지 않은 이유

대부분의 성능 모니터링 시스템은 집계 지표를 기반으로 구성됩니다:

  • 환경, 샤드(shard) 또는 대규모 고객 집단(XL customer cohort) 단위의 SLO

  • 수백 개 테넌트에서 한 번에 계산된 퍼센타일(예: p90)

  • 환경 또는 고객 집단 단위로 집계된 프론트엔드 지표(예: 페이지 로딩 성능을 나타내는 TTVC, time to visually complete)


이러한 지표들은 전체적인 상태를 파악하는 데는 유용하지만, 우리가 중요하게 생각하는 문제들을 간과할 수 있습니다:

많은 회귀는 소수의 매우 큰 테넌트에만 영향을 미치기 때문에, 고객 집단 단위로 집계된 지표에서는 완전히 드러나지 않는 경우가 많습니다.

고정 임계값만으로는 충분하지 않은 이유

그렇다면 왜 각 테넌트마다 SLO를 설정하고 이를 초과하는 경우를 감지하기보다, “성능 회귀(regression)”를 찾아야 할까요?

테넌트 간 편차가 크다는 점을 고려하면, 이렇게 접근했을 때 어떤 일이 발생하는지 아래 예시를 통해 다음과 같은 상황이 발생합니다.



문제 2가지:

  1. 임계값보다 성능이 지속적으로(또는 항상) 낮은 테넌트는 계속해서 알림이 발생합니다.

  2. 성능이 “매우 좋은 상태”(임계값보다 훨씬 낮은 수준)에서 “좋은 상태”(임계값보다 약간 낮은 수준)로 떨어진 테넌트는 알림이 전혀 발생하지 않습니다.


임계값을 매우 높게 설정하거나(성능이 가장 낮은 테넌트보다 높게), 또는 매우 낮게 설정하면(가장 빠른 테넌트보다 높게), 이 문제들 중 하나는 해결할 수 있지만, 고정 임계값만으로는 두 가지를 동시에 해결할 수는 없습니다.

설정한 기준

따라서 이번 프로젝트의 목표는 다음과 같습니다:

전체 지표에는 문제가 없어 보이더라도, 특정 백엔드 엔드포인트에서 개별 테넌트나 소규모 테넌트 그룹의 성능 저하를 감지하는 것


이를 위해 다음 세 가지가 필요합니다:

  • 대규모 환경에서 수집되는 테넌트별·엔드포인트별 지표

  • 각 테넌트의 과거 데이터와 비교하는 감지 파이프라인

  • “무언가 느려졌다”는 사실을 바탕으로 “유력한 원인”을 빠르게 파악하는 방법


탐지부터 대응까지: 하나의 성능 회귀 사례 전 과정

구체적인 사례를 통해, 실제 운영 환경에서 발생한 성능 회귀를 살펴보겠습니다:

  1. 집계된 지표로는 감지되지 않았던 백엔드 성능 저하를 탐지

  2. 담당 팀에 알림 전달

  3. 문제의 원인이 된 feature flag를 정확히 식별하는 자동화된 원인 분석(RCA)

  4. 고객 불만이 제기되기 전에 대응이 이루어지도록 지원


2025년 10월 말경, Jira 백엔드의 한 feature flag가 운영 환경 전반에 걸쳐 점진적으로 적용되기 시작했습니다.

일부 테넌트에서는 이 영향으로 이슈 뷰와 보드에서 사용되는 두 개의 백엔드 동작에서 지연 시간이 크게 증가했습니다.

반면, 나머지 테넌트에는 거의 영향을 주지 않았기 때문에, 다른 많은 성능 회귀와 마찬가지로 집계된 지표에서는 거의 드러나지 않았습니다.


이 문제는 상위 20개 테넌트에서 감지되었고, 해당 백엔드 엔드포인트를 담당하는 내부 팀에 JSM(Jira Service Management) 알림이 전달되었습니다.

알림 로직은 통계적 공정 관리(SPC) 기법을 기반으로 합니다:

  • 각 (테넌트, 엔드포인트) 조합에서 전체 트래픽의 10% 이상을 차지하는 이상 사용자(outlier users)를 식별
    → 이 단계는 알림 품질을 높이는 데 매우 중요하며, 이를 제외하지 않으면 단일 소스에서 발생한 일시적인 트래픽 급증으로 인해(다른 사용자들의 지연 시간에는 영향을 주지 않더라도) 성능 저하 신호가 다수 발생할 수 있음

  • 각 (테넌트, 엔드포인트) 조합에서 이상 사용자(outlier)를 제외한 뒤, 메트릭 데이터 레이크를 기반으로 일별 p90 지연 시간을 계산

  • 동일한 엔드포인트에서의 각 테넌트 과거 데이터를 기반으로 구성된 기준선(중앙값 및 표준편차)과 현재 p90을 비교해, 성능 저하가 발생한 (테넌트, 엔드포인트) 조합을 식별

  • 유사한 성능 저하를 테넌트 및/또는 엔드포인트 기준으로 그룹화하고, JSM(Jira Service Management) Operations에 알림을 전달

Rovo Dev CLI를 활용한 자동화된 원인 분석(RCA)

알림을 통해 문제를 인지할 수 있지만, 여전히 해결해야 할 큰 문제가 하나 있습니다:

성능 회귀의 원인을 진단하고 규명하는 일은 생각보다 훨씬 어렵습니다.

하나의 성능 회귀를 조사하는 데 며칠이 걸리기도 하며, 데이터 부족이나 도메인 지식의 한계로 인해 많은 경우 끝내 원인을 찾지 못하기도 합니다.

Jira에서 성능 회귀 원인 파악이 어려운 이유

이러한 어려움은 Jira의 규모와 매일 이루어지는 수많은 변경에서 비롯됩니다.

Jira는 여러 복잡한 레포지토리와 서비스 전반에 걸쳐 수천 명의 엔지니어가 개발에 참여하고 있습니다.

매일 수십에서 수백 건의 PR과 수천 건의 커밋, 그리고 수천 건의 feature flag 변경이 운영 환경에 반영됩니다.

또한 수백만 개에 달하는 Jira 테넌트는 각각 고유한 데이터 특성, 트래픽 패턴, 성능 특성을 가지며 이 역시 지속적으로 변화합니다.

여기에 더해 성능 데이터 자체에 노이즈가 많아 문제를 더 복잡하게 만듭니다.

이로 인해 성능 회귀가 정확히 언제 시작됐는지 특정하기 어렵고, 이 시점은 테넌트마다 다를 수 있습니다.

이러한 요인들이 겹치면서 성능 회귀의 근본 원인을 추적하기는 매우 어려운 작업입니다.


이를 AI로 해결할 수 있는 방법을 실험했습니다.

알림이 생성되면 시스템은 Rovo Dev CLI 기반의 근본 원인 분석 에이전트를 실행합니다.

이 에이전트는 다음과 같은 작업을 수행합니다:

  • 다단계 계획에 따라 동작하며, 각 성능 회귀 이후 새로운 도메인 지식과 조사 패턴을 반영해 계획을 지속적으로 조정합니다.
    이를 통해 기존 수동 조사 과정에서 축적된 상세한 맥락과 구체적인 패턴을 활용합니다.

  • 데이터 레이크에 저장된 high-cardinality 운영 환경 메트릭을 대상으로 SQL 쿼리를 작성합니다.

  • Jira를 구동하는 소스 코드와 최근 Git 이력에 대해 읽기 전용 접근 권한을 가집니다.


동작 방식을 자세히 살펴보기 전에, 해당 성능 회귀에 대해 에이전트가 생성한 원인 분석 요약은 다음과 같습니다:


Feature flag replace-metrics-check-ff는 2025-10-30 23:42 UTC에 배포되었습니다.
이 변경으로 인해 모든 데이터베이스 쿼리의 핵심 경로에서 Tenant Context Service(TCS)에 대한 호출이 추가되었습니다.

이 호출은 동기식으로 수행되며 캐싱이 적용되지 않습니다.

해당 코드 변경(커밋 07d429ba99)은 feature flag 체크를 EditionService.getProductEdition() 호출로 대체했습니다.

이 과정에서 TcsHttpClient.get()을 통해 TCS API에 대한 블로킹 호출이 발생합니다.

이로 인해 TCS 클라이언트 실행 시간이 1016% 증가했으며(프로파일러 기준 1.37시간 → 15.30시간), 이는 관측된 지연 시간 증가와 직접적으로 연관됩니다.

또한 이 호출은 모든 데이터베이스 연결과 쿼리마다 수행되므로, 그 영향이 요청 전체 라이프사이클 전반으로 증폭됩니다.


이번 회귀 분석에서 에이전트가 어떤 과정을 거쳤는지 살펴보겠습니다:

1. 영향 범위 요약 및 타임라인 수집

에이전트는 알림에 포함된 모든 테넌트의 지연 시간 데이터를 확인하고, 이를 바탕으로 영향이 시작된 시점을 파악하기 위해 타임라인을 구성합니다.

이 정보는 이후 다른 신호와의 상관관계를 분석하는 데 활용됩니다.


2. 샘플링 프로파일러 데이터 분석

Jira에는 백엔드에서 시간이 어디에 소비되는지(클래스, 메서드, 테넌트, 엔드포인트 등 기준) 측정하고, 그 데이터를 데이터 레이크로 전송하는 자체 샘플링 프로파일러가 있습니다.


다른 데이터와 마찬가지로, 에이전트는 데이터 레이크에 저장된 데이터를 SQL로 조회할 수 있습니다.

이를 통해 성능 회귀 전후의 프로파일을 비교하고, 실행 시간이 증가한 특정 메서드로 범위를 좁혀갈 수 있습니다.


이번 사례에서는 프로파일러 데이터를 통해 특정 메서드(TcsHttpClient.get())가 영향을 받은 테넌트에서 하루 기준 1.37시간에서 15.3시간으로 증가했으며, 성능 회귀가 발생한 시점과 동일한 시각부터 시작된 것으로 확인되었습니다.

조사 대시보드 중 하나에서 가져온 차트로, 특정 테넌트에서 발생한 성능 회귀와 상관관계를 보여주며 TcsHttpClient.get()에서 소요 시간이 시간 단위로 증가하는 양상(하단의 빨간색/마룬 영역)을 나타냅니다.


3. Feature flags

다음으로 에이전트는 feature flag 평가 데이터를 살펴봅니다:

  • 데이터 레이크에는 요청 단위의 flag 평가 결과가 성능 메트릭과 함께 기록됩니다.

  • 이를 통해 특정 테넌트와 백엔드 엔드포인트에서 flag 변경 시점을 정확히 파악할 수 있습니다.
    (프로덕션 환경에서는 flag가 점진적이고 무작위로 롤아웃되기 때문입니다)

  • 에이전트는 성능 회귀와 강한 상관관계를 보이는 flag 변경을 찾기 위해 SQL 쿼리를 작성하고, 여러 영향을 받은 테넌트의 시점을 교차 검증합니다.


세 개의 후보 flag가 도출되었으며, 그중 replace-metrics-check-ff가 여러 영향을 받은 테넌트에서 시간 단위까지 강한 상관관계를 보이며 가장 두드러졌습니다.

조사 대시보드 중 하나에서 가져온 차트로, 영향을 받은 테넌트 중 하나에서 해당 flag의 지연 시간 데이터를 보여줍니다.

에이전트는 이 차트를 생성하는 데 사용된 요청 단위의 원시 데이터에 접근할 수 있습니다.


4. 소스 코드 분석

이 단계에서 전통적인 하드코딩 기반 흐름과 비교해 에이전트의 장점이 드러납니다.

이미 의심되는 feature flag를 식별한 상태에서 에이전트는 각 feature flag의 사용처를 검색하며 실제 변경 내용을 분석하기 시작합니다.


replace-metrics-check-ff의 경우, 다음과 같은 변경이 이루어졌습니다.

pseudocode of the old path
// pseudocode of the old path
boolean shouldEmitMetrics(String rds) {
    return queryStatsig(SLO_METRICS_ENABLED, Map.of("rds", rds));
}


다음과 같이 변경되었습니다:

pseudocode of the new path
// pseudocode of the new path
boolean shouldEmitMetrics(String tenantId) {
    Edition edition = editionService.getProductEdition(tenantId);
    return edition == ENTERPRISE;
}


에이전트는 editionService.getProductEdition(tenantId)의 호출 트리를 분석한 결과, 어느 단계에서도 캐싱 없이 7개의 메서드 호출 체인을 거쳐 프로파일러 데이터에서 확인된 TcsHttpClient.get() 메서드로 직접 연결됨을 확인했습니다.


5. 전체 흐름 정리

에이전트는 근본 원인에 대한 충분히 강한 근거를 확보했으며, 남은 작업은 요약 보고서를 작성해 Confluence에 저장하는 것이었습니다.

엔지니어들은 이를 검토한 뒤, 영향을 받은 고객이 문제를 인지하기 전에 몇 시간 내로 해당 flag를 다시 비활성화했습니다.

조사 계획에는 일반적으로 몇 가지 단계(코드 배포, 데이터베이스 메트릭 등)가 더 포함되지만, 이번 사례에서는 필요하지 않았습니다.


이를 통해 배운 점

1. 성능 회귀 감지는 절반에 불과합니다

이 프로젝트 초기에는 주로 데이터 엔지니어링 문제로 접근했습니다. 어떻게 하면 대규모 데이터를 안정적이고 효율적으로 처리할 수 있을지에 초점을 맞췄습니다.

이 부분도 당연히 어려웠지만, 이 프로젝트의 가장 큰 과제는 아니었습니다. 핵심은 알림 발생에서부터 대응까지 이어지는 과정이었습니다.

이 시스템에서 실질적인 가치를 얻기 위해서는 단순히 알림을 생성하는 것만으로는 충분하지 않습니다. 알림이 적절한 팀에 전달되고, 실제로 조사가 이루어지며, 최종적으로 대응까지 이어지도록 해야 합니다.

이는 엔지니어링 문제이면서 동시에 비즈니스 협업 문제이기도 합니다.

엔지니어링 측면:

성능 회귀의 근본 원인을 빠르게 파악하기 위해서는 적절한 데이터와 도구를 갖추는 것이 중요하며, 이 때문에 자동화된 RCA가 초기 예상보다 훨씬 더 중요해졌습니다.

성능 회귀를 조사하기 어렵다면 팀은 이를 진행하지 않게 되고, 결과적으로 성능 회귀는 해결되지 않습니다.

자동화된 RCA와 함께, feature flag 변경을 찾기 위한 Databricks 대시보드와 같은 다양한 “수동” 도구도 구축했으며, 이 중 많은 도구가 이후 자동화된 RCA 단계로 발전했습니다.

이 전체 과정은 성능 회귀를 발견하고, 조사하고, 도구를 개선하는 반복적인 순환 구조로 이루어졌으며, 조사 과정에 깊이 관여하지 않았다면 적절한 도구를 구축하기 어려웠을 것입니다.

비즈니스 협업 측면:

성능 회귀 알림을 하나의 중앙 팀이 모두 처리하는 방식은 장기적으로 확장하기 어렵기 때문에, 알림을 관련 Jira 팀에 자동으로 할당할 수 있는 방법이 필요했습니다.

이를 위해 모든 Jira 엔드포인트와 소스 파일에 대해 특정 팀에 소유권을 지정한 최근 작업이 큰 도움이 되었으며, 이를 통해 각 알림을 항상 적절한 팀에 할당할 수 있게 되었습니다.

또한 성능 회귀를 방지하는 것과 개발 속도를 지나치게 저해하지 않는 것 사이에서 적절한 균형을 찾는 것도 필요했습니다.

때로는 소규모 성능 회귀가 발생하더라도 중요한 버그를 먼저 수정해 배포하고, 이후에 성능을 개선하는 것이 더 나은 선택일 수 있습니다.


2. 좋은 평가 데이터셋은 복잡한 에이전트를 구축하는 데 매우 중요합니다

처음에 근본 원인 분석 에이전트를 개발할 때는 단기적인 실험으로 생각하고 주로 일회성 수동 실행과 출력 확인 방식으로 테스트했습니다. 하지만 결국 이 방식이 개발에 큰 걸림돌이 된다는 것을 깨달았습니다.

변경 사항이 상황을 개선하는지 파악하기가 너무 어려웠고, 특정 시점에 개발 중인 단일 시나리오에만 과적합되는 경우가 너무 많았습니다.


이로 인해 에이전트를 보다 일관되게 테스트하기 위한 평가 프레임워크를 구축하게 되었으며, 이는 에이전트 개발 과정에서 가장 중요한 작업이었습니다.


에이전트를 보다 현실적으로 평가하기 위해, 합성 데이터가 아닌 실제 운영 환경에서 발생한 성능 회귀를 기반으로 시나리오를 구성했습니다.

이를 통해 실제 조사에서 중요한 다양한 요소들을 반영할 수 있습니다.

예를 들어 노이즈가 많은 메트릭, 계절성 및 트래픽 변화, 상관관계를 가지는 신호, 그리고 겹치는 코드 변경 등이 있습니다.

에이전트는 메트릭에 대해 임의의 SQL을 실행하고 코드도 자유롭게 분석할 수 있기 때문에, 이 부분에서 타협할 수 없습니다.

평가 시나리오는 알림부터 타임라인, 코드, 배포에 이르기까지 전체 흐름을 모두 다루어야 합니다.


각 시나리오에 기록되는 내용은 다음과 같습니다:

  • 알림 시스템 입력 정보: 성능 회귀 발생 시점, 영향을 받은 엔드포인트, 그리고 테넌트

  • 성능 회귀 발생 며칠 후 시점의 커밋 해시: 에이전트가 안정적인 코드베이스 상태를 기준으로 분석할 수 있도록 합니다.

  • 사람이 검증한 기준 정보: 실제 근본 원인에 대한 간결한 설명과 상세한 평가 노트이며, 에이전트에는 제공되지 않고 오직 평가에만 사용됩니다.


초기에는 생성된 RCA 보고서를 키워드 검색(예: 실제 근본 원인에 해당하는 feature flag 키)으로 평가했습니다.

하지만 이 방식은 곧 한계에 부딪혔습니다.

에이전트가 발견한 모든 신호를 보고서에 나열하는 것만으로도 높은 점수를 받게 되었고, 실제 근본 원인에 대한 이해나 판단은 제대로 평가되지 않았습니다.

이를 해결하기 위해, 각 시나리오에 대해 기록된 실제 근본 원인과 평가 노트를 기준으로 각 실행 결과를 평가하는 LLM-as-a-judge 방식을 도입했으며, 그 결과 평가 품질이 크게 향상되었습니다.

생성된 요약 보고서를 바탕으로 평가를 진행하고, 다음 두 가지 기준으로 점수를 부여합니다:


  1. 재현율(Recall): 요약이 성능 회귀의 근본 원인과 핵심 신호를 정확히 찾아냈는가?

  2. 정확도(Precision): 요약이 잘못되었거나 관련 없는 근본 원인을 포함하지 않았는가?


다음은 평가 하네스(evaluation harness)에서 전체적으로 어떻게 구성하는지입니다:


다이어그램: 에이전트의 벤치마킹/평가 흐름을 보여줍니다


각 시나리오는 병렬로 실행되며, 일관성을 검증하기 위해 필요에 따라 여러 번 실행되기도 합니다.

실행 전에 해당 시점의 올바른 커밋 기준으로 코드 저장소를 체크아웃합니다.

이후 에이전트를 실행하고, 그 결과를 평가자(judge)로 검증한 뒤, 모든 결과를 하나의 보고서로 통합합니다.


향후 계획

테넌트별 통계 기반 탐지와 AI 기반 원인 분석(RCA) 에이전트를 결합함으로써, 성능 회귀 대응을 즉흥적인 대응(firefighting)에서 반복 가능하고 자동화된 워크플로로 전환했으며, Jira 전반으로 확장 가능한 구조를 만들었습니다.

이 시스템은 이제 전사적 지표로는 포착되지 않는 성능 회귀를 지속적으로 탐지하고, 가장 가능성 높은 근본 원인을 팀에 제시하며, 고객이 문제를 체감하기 전에 대응을 배포할 수 있도록 돕습니다.


다음 단계에서는 이 시스템을 더 넓고 깊게 확장할 예정입니다.

모든 Jira 엔드포인트로 적용 범위를 확대하고, 인프라 신호부터 제품 수준의 컨텍스트까지 더 풍부한 데이터를 RCA에 통합하며, 탐지–조사–대응 간 피드백 루프를 더욱 강화할 것입니다.

Jira 팀들이 전반적인 성능 개선을 지속적으로 추진하는 만큼, 이 시스템 역시 이에 발맞춰 성능 회귀를 조기에 탐지하고, 이를 명확하게 설명하며, 팀이 이를 해결할 수 있는 직접적인 경로를 제공하는 것을 목표로 합니다.


  • No labels