정산 배치가 반복해서 멈춘 건 결국 기술 부채 때문이었나?
결론부터: 그렇다. 다만 "레거시라서"가 아니라 부채가 변경 시간과 장애 복구 시간을 동시에 늘리는 임계점을 넘었기 때문이다. 코드가 오래됐다는 느낌은 1년 전부터 있었지만, 그게 비용으로 찍힌 건 세 번째 장애 이후였다.
핵심만 먼저 적는다.
- 부채는 '있다/없다'가 아니라 "이 변경에 평소보다 몇 배의 시간이 드는가"로 봐야 신호가 보인다.
- 평균 지표만 보면 늦게 알아챈다. p95·p99, 재작업 PR 비율, 롤백 횟수를 같이 봐야 한다.
- 즉시 리팩터링·부분 마이그레이션·현상 유지의 비용을 비교한 문서가 있어야 다음 결정이 빨라진다.
- 재발 방지는 "다음엔 조심하자"가 아니라 병합 조건과 배포 전 체크리스트로 못 박아야 유지된다.
올해 초, 야간 정산 배치가 3주 사이 세 번 멈췄다. 평소 12분이면 끝나던 배치가 두 번째 장애 때는 47분, 세 번째는 타임아웃으로 종료됐다. 정산팀은 다음 날 오전 업무를 못 열었고, 고객 문의가 쌓였다. 첫 번째 장애는 "트래픽이 늘어서"로 덮었다. 세 번째에서야 원인을 제대로 추적했다.
트래픽 증가 가설은 왜 틀렸나?
틀렸다기보다 설명력이 부족했다. 전월 대비 거래 건수는 18% 늘었을 뿐인데, 배치 처리 시간은 네 배 가까이 늘었다. 증가율이 안 맞으니 다른 원인을 찾아야 했다.
쿼리 로그를 뜯어보니 정산 모듈에 지난 2년간 추가된 기능마다 조회 쿼리가 하나씩 더 붙어 있었다. 할인 정책, 포인트 적립, 환불 예외 처리가 각각 별도 쿼리로 구현되면서 거래 1건당 쿼리 수가 3개에서 11개로 늘어 있었다. 각 기능은 그 시점에 "일단 동작하게" 머지됐고, 인덱스 리뷰는 한 번도 없었다. 2025년 AWS에서 GCP로 DB를 옮긴 사례 연구는 쿼리 실행시간 15% 단축, 지연시간 20% 감소를 보고했는데, 이 수치는 엔진·인스턴스·쿼리 분포가 명시돼야 해석 가능하다는 단서가 붙어 있다(출처). 우리도 같은 함정에 빠질 뻔했다 — 쿼리 수가 늘었다는 사실만으로 "느려졌다"를 설명하려 했지, 데이터셋 크기와 동시 접속 수를 같이 보지 않았다.
세 번이나 반복된 건 코드 문제였나, 프로세스 문제였나?
둘 다였지만 비중은 프로세스 쪽이 컸다. 첫 번째 장애 때 핫픽스로 쿼리 하나에 인덱스를 붙였다. 두 번째 장애 때는 다른 쿼리가 범인이어서 또 핫픽스를 했다. 근본 원인인 "쿼리별 인덱스 리뷰 없음"은 이슈로만 등록돼 있었고 우선순위에서 두 번 밀렸다.
이 구간이 주니어와 미들의 경계라고 본다. 주니어 단계에서는 이슈를 등록하는 데서 멈춘다. 미들 단계부터는 이 부채가 특정 기능의 변경 시간과 장애 위험에 얼마나 영향을 주는지 측정해야 한다. 우리 팀은 이슈 등록까지는 했지만 "이 부채 때문에 평균 몇 분이 더 걸린다"는 숫자가 없어서, 매번 다른 긴급 작업에 밀렸다.
병목이 쿼리인지 배치 설계인지는 어떻게 확정했나?
스테이징 환경에 운영과 동일한 데이터셋 크기(거래 약 420만 건)를 복제하고, 동일한 동시 처리 조건에서 EXPLAIN ANALYZE로 쿼리 11개를 전수 조사했다. 그중 3개 쿼리가 풀스캔을 타고 있었고, 이 3개가 전체 배치 시간의 68%를 차지했다. 인덱스를 추가한 재현 테스트에서는 해당 3개 쿼리의 실행시간이 평균 2.1초에서 0.3초대로 줄었다. 나머지 8개 쿼리는 영향이 미미해 우선순위에서 제외했다.
이 과정에서 중요했던 건 "느려졌다"가 아니라 "68%가 3개 쿼리에서 발생한다"는 분해였다. 2025년 클라우드 네이티브 전환 사례도 250개 핵심 트랜잭션을 90일간 관측해 평균 응답시간이 200ms에서 피크 부하 시 2.5초까지 악화된 지점을 특정했는데, 전환 후 약 180ms로 돌아왔다고 보고한다(출처). 다만 이 수치는 특정 금융 서비스 환경에 한정되고, p95·p99나 오류율까지는 공개되지 않아 우리는 평균값만으로 성공을 선언하지 않기로 했다.
재발 방지로 무엇을 바꿨고 어떤 지표로 확인했나?
세 가지를 바꿨다. 첫째, 정산 모듈에 쿼리를 추가하는 PR은 EXPLAIN 결과 첨부를 병합 조건에 넣었다. 둘째, 테스트 커버리지 80% 초과와 순환 복잡도 10 미만을 병합 조건으로 걸었다. 이는 AI 생성 코드가 늘면서 코드 중복과 결함률이 반복적으로 관찰됐다는 2026년 프리프린트 연구가 제시한 조건과 같은데, 이 연구는 아직 동료심사를 거치지 않은 문헌고찰이라 보편 기준이 아니라 참고 기준으로만 썼다(출처). 셋째, 변경 리드타임·변경 실패율·롤백 횟수·재작업 PR 비율·복구시간을 대시보드에 올렸다. 코드 지표만으로는 부채가 줄었는지 알 수 없고, 결과 지표로 측정해야 한다는 2026년 연구의 관점을 따른 것이다(출처).
지표로 확인한 결과는 이렇다. 정산 배치 재작업 PR 비율은 변경 적용 전 35%에서 적용 후 2개월 평균 14%로 낮아졌고, 같은 기간 롤백은 0건이었다. 다만 관측 기간이 2개월로 짧아 계절성 영향은 아직 배제하지 못한다.
같은 함정을 피하려면 기본값을 무엇으로 삼아야 하나?
평균값 하나로 "좋아졌다"고 말하지 않는 걸 기본값으로 삼았다. 부채를 발견하면 이슈 등록에서 멈추지 않고, 그 부채가 어떤 변경에 몇 분·몇 퍼센트의 비용을 더 발생시키는지부터 적는다. 리더십에 투자를 요청할 때는 2026년 IBM 자료가 제시한 것처럼, 기술 부채 대응을 사업계획에 반영한 기업의 예상 ROI가 그렇지 않은 경우보다 29% 높았다는 조사 결과를 근거로 들되, 이는 기업 조사 기반 경영 지표이지 우리 조직에 그대로 적용되는 수치는 아니라는 점을 함께 말한다(출처). 2026년 기준으로 우리 팀은 "느려진 것 같다"는 보고 대신 재작업 PR 비율과 롤백 횟수를 먼저 묻는 걸 당연한 절차로 바꿨다.
핵심 정리
- 부채는 '있다/없다'가 아니라 특정 변경이 평소보다 몇 배의 시간·위험을 발생시키는지로 판단한다.
- 평균 응답시간만으로는 장애를 설명하지 못한다. 쿼리별·구간별 분해와 재현 테스트로 원인을 좁혀야 한다.
- 재발 방지는 코드 수정이 아니라 병합 조건과 대시보드 지표(변경 리드타임, 재작업 PR 비율, 롤백 횟수)로 고정해야 유지된다.
- 외부 연구 수치(ROI 29%, 응답시간 180ms, 쿼리 15% 단축 등)는 측정 조건이 다르므로 우리 조직의 보장치로 쓰지 않는다.
- 주니어는 부채를 발견하고, 미들은 영향을 측정하고, 시니어는 선택지의 비용을 비교해 문서로 남긴다.