CPU 부하가 보이면 서버를 키우고 싶은 유혹이 있지만, 슬로우 쿼리와 실행계획을 따라가 보니 문제는 테이블 구조와 식별자 정책에 있었습니다. 부하가 데이터 정합성과 스키마 문제에서 비롯된 경우였습니다.
라이브러리 컴포넌트 테이블은 제품의 여러 기능이 기대는 중심 테이블이라, 쿼리 튜닝에서 멈추지 않고 collation·스키마·식별자 정책까지 다시 정리했습니다.
배경
고객사 환경에서 중앙 운영 DB의 CPU 이상(부하)이 관측됐습니다. 슬로우 쿼리에서 시작해 실행계획으로 좁혀 보니, 다수 패키지 생태계의 컴포넌트 정보를 담는 라이브러리 컴포넌트 테이블의 구조가 부하·정합성 문제의 근원이었습니다.
collation 불일치 조인: 같은 값을 저장하는 두 테이블의 collation이 달라(한쪽만 대소문자 구별) 뷰를 통한 조인은 인덱스를 타지 못하고 약 130만 건을 전체 스캔하는데, 테이블을 직접 조인하면 인덱스를 타고 약 6,000건에 그친다는 것을 실행계획으로 확인
문자열(varchar) 타입 컬럼에 JSON을 그대로 저장하던 케이스(예: 라이선스 컬럼)가 있어 조회·가공 시 비효율과 데이터 깨짐을 유발
식별자 문제: 서로 다른 패키지가 같은 키로 충돌하거나, 대소문자 차이로 동일 컴포넌트가 누락되는 케이스가 발생
접근
① 추적슬로우 쿼리 확인 → 실행계획으로 원인 쿼리 분석
→
② 진단collation 불일치로 뷰 조인이 전체 스캔되는 것을 확인
→
③ 전수조사varchar-JSON 저장·식별자 충돌 케이스를 전체 테이블 대상으로 조사
→
④ 재설계스키마·인덱스·식별자 정책 재설계
슬로우 쿼리에서 원인 쿼리를 찾아 실행계획을 비교했습니다. 뷰를 통한 조인은 collation 차이 때문에 인덱스를 타지 못해 약 130만 건을 스캔했고, 같은 조건으로 테이블을 직접 조인하면 약 6,000건에 그쳤습니다. 이어 varchar에 JSON을 저장하던 케이스를 전체 테이블 대상 전수조사해 영향 범위와 깨진 데이터 비율을 파악하고, 식별자 충돌·대소문자 누락 같은 구조적 문제를 정리한 뒤, 어긋나 있던 collation을 통일하고 스키마·인덱스·식별자 정책을 재설계해 부하와 정합성을 동시에 잡았습니다.
결과
근본 원인 분석중앙 운영 DB CPU 부하의 원인을 라이브러리 테이블 구조로 규명
스캔 감소뷰 조인 약 130만 건 전체 스캔 → 테이블 직접 조인 약 6,000건 (실행계획 기준)
정합성 개선식별자 정책 정비로 충돌·누락을 줄이고 데이터 정합성 향상
역할
데이터 엔지니어로서 CPU 부하를 만든 쿼리의 실행 계획부터 확인했습니다. 관련 테이블과 인덱스를 전수 조사한 뒤 스키마, 식별자, 인덱스 수정안을 만들고 구현했습니다. 여러 기능이 함께 쓰는 중심 테이블이어서 최종안은 팀장·CTO 리뷰를 거쳐 정했습니다.
collation 통일, 식별자 정책 정비와 스키마·인덱스 재설계가 핵심 변경점. varchar-JSON 컬럼의 타입 정규화는 이 조사에서 발견해 별도 작업으로 진행.
수집 주기는 데이터의 시급성으로 정했습니다. 취약점 정보는 고객사가 빨리 대비할수록 가치가 있어 20분 주기로 수집하고 1시간 배치와 맞물려 약 1시간 안에 고객사까지 도달, 라이브러리 버전은 새로 나와도 기업이 바로 코드를 고치지 않으므로 4시간 주기로 완화
크롤러별 DAG 분리와 Git-Sync로 DAG 변경 이력 관리
CPU·메모리 요구량에 따라 Pod 자원 할당
rate limit에 맞춘 pool·backoff·재시도 정책
IDC 자원이 부족할 때 WireGuard로 연결한 In-house 워커까지 사용
운영 중 해결한 문제
Pod가 생성되지 않거나 Init 단계에서 멈출 때는 재시작 전에 원인부터 확인했습니다. 노드 inode와 DiskPressure, CoreDNS, kube-proxy, etcd 응답 지연, Git-Sync 권한과 재시도 설정을 순서대로 확인했습니다.
토큰과 키 만료는 사전 알림을 달아 장애가 난 뒤 교체하는 일을 줄였습니다. 특정 서버에 작업이 몰리는 경우에는 스케줄과 자원 요청량을 다시 조정했습니다.
역할을 나눈 방식
각 크롤러의 수집 로직과 데이터 오류는 해당 담당자가 수정했습니다. 저는 여러 크롤러가 함께 쓰는 스케줄링, Kubernetes 자원, 네트워크, DB 연결, 모니터링을 설계하고 운영했습니다. 공통 장애가 생기면 원인을 찾아 담당자가 다시 같은 문제를 겪지 않도록 설정과 런북에 반영했습니다.
시작은 AWS 비용이었습니다. 수집·배포·운영(prod) 데이터가 AWS EC2에 직접 설치한 MySQL 인스턴스 하나에 통으로 들어 있어 데이터가 늘수록 과금이 따라 늘었고, 비용 문제로 그 구성 그대로 사내 범용 PC의 M.2 SSD로 옮겼습니다. 그러자 다른 문제가 생겼습니다. 크롤러가 몰리는 시간대에 DB 쓰기와 디스크 I/O가 겹쳤고, 발열이 올라가면 서버 전체가 멈춰 한 달에 10~20번씩 운영 이슈가 생겼습니다.
syslog, 실행 시간대, 네트워크 상태를 함께 확인해 수집 집중 시간과 장애 시점을 대조했습니다.
먼저 멈추지 않게 만들기
새 서버를 바로 들일 수는 없었기 때문에 수집 스케줄을 먼저 분산했습니다. 동시에 돌던 작업을 시간대별로 나누고, 무거운 작업이 한 장비에 몰리지 않도록 실행 순서를 조정했습니다.
조정 전월 10~20건 수준의 프리징·DB 운영 이슈
스케줄 분산 후월 5건 미만으로 감소
IDC로 옮긴 과정
스케줄 조정은 임시방편이라고 판단했습니다. 서버 도입을 요청하고, 인스턴스 하나가 다 감당하던 구조를 수집 DB·배포 DB·운영 DB로 분리해 수집 부하가 배포·운영 조회를 방해하지 않게 만들었습니다. IDC 환경에 DB primary/replica, 수집 서버, 백업·복구 경로와 모니터링을 다시 구성했습니다.
현황 확인syslog·네트워크·부하 시간대 점검
→
임시 안정화수집 스케줄 분산
→
IDC 구축서버·DB·백업·모니터링 구성
→
이관 검증데이터 정합성 확인 후 전환
이관을 마친 뒤에는 운영(prod) DB가 있는 EC2만 AWS에 남기고 다른 EC2 인스턴스를 정리해 월 AWS 비용을 약 94% 줄였습니다.
결과
DB 운영 장애스케줄 조정으로 월 5건 미만, IDC 전환(2024) 이후 1~2건
부하 간섭 제거수집·배포·운영 DB를 분리해 수집 부하가 조회를 방해하지 않는 구조
반복 비용운영 DB용 EC2 외 인스턴스 정리로 월 비용 약 94% 절감
복구 가능성백업·복원과 정합성 확인을 거친 뒤 전환
제가 맡은 부분
증상 확인과 스케줄 조정, IDC 서버 도입 요청, 데이터 이관과 검증, DB·백업·모니터링 재구성을 맡았습니다. 비용 절감보다 먼저 서비스가 멈추지 않는 순서를 잡는 데 집중했습니다.
팀에서 운영하는 서버가 10~20대로 늘면서, 장애가 생길 때마다 서버에 접속해 DB와 로그를 따로 확인하는 방식이 한계에 닿았습니다. 수집 누락, 수집량 급증, DB replica 지연, 고객사로 나가는 데이터 상태가 서로 다른 화면에 흩어져 있었습니다.
무엇을 한 화면에 모았나
Prometheus와 Grafana를 사용해 서버와 DB 상태를 공통 대시보드로 묶었습니다. 데이터 현황은 PostgreSQL의 시계열 데이터와 연결해 같은 시간축으로 비교했습니다.
서버·DB·수집·고객사 데이터 지표를 모아 같은 시간축으로 비교하고 이상 상태는 알림으로 연결했습니다.
서버 — CPU, 메모리, 디스크, 컨테이너 사용량
DB — read/write, connection, replica 상태와 지연
수집 — 크롤러 실행 여부, 누락, 시간대별 수집량 증감
고객사 데이터 — 배포·동기화 진행률, 오류와 지연
알림과 운영
대시보드에 더해, 임계값을 넘으면 메신저와 이슈 관리 도구로 알림이 가도록 연결했습니다. 토큰 만료, 백업 실패, 데이터 동기화 지연처럼 미리 조치할 수 있는 항목은 장애 전에 알려 주도록 했습니다. 서버와 애플리케이션 로그 수집에는 Vector를 사용했습니다.
결과
10~20대 서버공통 상태를 한 화면에서 확인
DB·수집·배포서로 다른 지표를 같은 시간축으로 비교
선제 대응만료·지연·실패를 알림으로 먼저 확인
제가 맡은 부분
공통으로 볼 지표를 정하고 Prometheus 수집, Grafana 대시보드, PostgreSQL 시계열 조회와 알림을 구성했습니다. 개별 크롤러의 내부 로직은 담당자가 관리했고, 저는 전체 수집량과 누락, DB·서버, 고객사 데이터 흐름을 함께 볼 수 있는 관측 구조를 맡았습니다.