Q1. DB가 느릴 때 첫 대응은 스케일아웃 아닌가요?
답변
아닙니다. 실무에서는 보통 아래 순서가 안전합니다.
- 측정: 슬로우쿼리, 락 대기, 커넥션 풀 고갈 여부 확인
- 쿼리/인덱스: EXPLAIN으로 Full Scan, filesort, temporary 제거
- 캐시: 반복 조회 핫키를 캐시로 흡수
- 비동기화: 집계/후처리를 큐로 분리
- 스케일: 마지막에 레플리카/샤딩 검토
Q2. 왜 이 순서가 중요한가요?
답변
원인 검증 없이 스케일아웃하면 비용만 늘고 문제는 남습니다.
- 쿼리 한두 개가 병목이면 서버를 늘려도 그대로 느립니다.
- 락 경합 문제면 노드 증가가 오히려 경쟁을 키울 수 있습니다.
즉, 병목 위치를 증거로 특정한 뒤 확장해야 합니다.
Q3. 측정 단계에서 어떤 숫자를 한 화면에 모아야 하나요?
답변
장애가 난 뒤 평균 응답 시간만 보면 원인을 놓치기 쉽습니다. 요청량, 지연, 포화, 오류를 같은 시간축으로 비교해야 합니다. 최소한 아래 지표를 5~15분 단위로 확인합니다.
| 관점 | 먼저 볼 지표 | 해석할 때의 질문 |
|---|---|---|
| 사용자 경험 | API p95/p99, 타임아웃률 | 특정 엔드포인트만 느린가, 전체가 느린가? |
| DB 작업 | 상위 쿼리의 호출 수·평균/최대 시간·rows examined | 호출량이 늘었나, 쿼리 1회가 느려졌나? |
| 경합 | lock wait, deadlock, long transaction | 오래 열린 트랜잭션이 쓰기 경로를 막는가? |
| 연결 | active/idle connection, pool wait, pool timeout | DB가 아니라 애플리케이션 풀에서 대기하는가? |
| 자원 | CPU, IOPS, 디스크 지연, 버퍼 캐시 적중률 | CPU/디스크 포화가 쿼리 계획 문제와 함께 나타나는가? |
이때 평균값만으로 배포 여부를 결정하지 않습니다. 예를 들어 평균 80ms라도 p99가 4초이고 pool timeout이 발생하면, 소수의 장기 쿼리가 커넥션을 점유하는 상황일 수 있습니다. 대시보드의 스파이크 시각과 배포·배치·인덱스 생성 시각을 함께 남기면 다음 장애에서 추측 비용을 크게 줄일 수 있습니다.
Q4. 실전에서는 어떻게 원인을 좁히나요?
답변
예를 들어 주문 조회 API의 p95가 180ms에서 2.4초로 증가했고, DB CPU는 45%로 여유가 있지만 커넥션 풀 대기가 늘었다고 가정해 보겠습니다. 이 경우 인스턴스를 바로 늘리기보다 다음처럼 가설을 검증합니다.
- 범위를 자릅니다. 엔드포인트·테넌트·리전·읽기/쓰기 경로별로 지연을 나눠 봅니다. 전체 장애인지 특정 고객 데이터의 편향인지 구분합니다.
- 상위 쿼리를 재현 가능한 형태로 찾습니다. 슬로우 로그와 APM trace에서 정규화된 SQL, 바인드값의 분포, 호출 수를 확인합니다. 개인정보나 민감 값은 로그에 남기지 않습니다.
- 실행 계획을 비교합니다. 운영에서 임의의 쓰기 쿼리를 실행하지 않고, 동일한 통계·인덱스를 가진 스테이징에서
EXPLAIN/EXPLAIN ANALYZE를 비교합니다. 예상 행 수와 실제 행 수 차이가 크면 통계·조건 선택도·복합 인덱스 순서를 의심합니다. - 장기 트랜잭션을 찾습니다. 인덱스가 있어도
idle in transaction, 배치성 업데이트, 누락된 커밋이 락을 붙잡으면 읽기·쓰기가 연쇄로 밀릴 수 있습니다. - 가장 작은 변경부터 실험합니다. 페이지네이션 상한, N+1 제거, 조건에 맞는 인덱스처럼 되돌리기 쉬운 변경을 canary로 적용하고 p95·오류율·write 지연을 기준선과 비교합니다.
핵심은 “느린 SQL 하나”를 찾는 것보다 사용자 지연을 설명하는 인과관계를 만드는 일입니다. 호출량 급증이 원인이라면 인덱스만 추가해도 충분하지 않고, 캐시·요청 제한·비동기화의 조합이 필요할 수 있습니다.
Q5. 인덱스나 캐시를 적용할 때의 안전장치는 무엇인가요?
답변
인덱스는 읽기를 빠르게 만들 수 있지만 쓰기 비용과 저장 공간을 증가시킵니다. 따라서 새 인덱스는 대상 쿼리의 필터·조인·정렬 순서와 일치하는지 확인하고, 대형 테이블에서는 DB 엔진의 온라인 DDL 조건과 락 영향을 먼저 검토합니다. 적용 뒤에는 대상 조회 p95뿐 아니라 insert/update 지연, 복제 지연, 디스크 사용량을 같이 관찰합니다.
캐시는 “DB가 느리다”는 이유만으로 붙이지 않습니다. 값이 얼마나 오래 허용되는지(TTL), 변경 시 무엇이 무효화하는지, 장애 시 DB로 동시에 몰리는 cache stampede를 어떻게 막는지를 정해야 합니다. 짧은 TTL·요청 병합·단일 키 재계산 잠금처럼 단순한 보호장치를 먼저 두고, 캐시 미스 시에도 서비스가 정상 응답하는지 확인합니다.
되돌림 기준도 배포 전에 정합니다. 예를 들어 canary에서 write p95가 기준선보다 20% 이상 악화하거나 오류율이 증가하면 인덱스/기능 플래그를 되돌리고, 캐시 데이터 불일치가 허용 범위를 넘으면 TTL을 줄이거나 해당 키를 우회합니다. 성능 개선 숫자만 보고 정합성 위험을 승인하지 않는 것이 원칙입니다.
Q6. 면접에서 어떻게 답하면 좋아요?
답변
- 결론: “저는 먼저 측정하고, SQL/인덱스를 고친 뒤 캐시/비동기, 마지막으로 스케일합니다.”
- 근거: “대부분 병목은 구조적 원인이라 수평 확장 전에 제거할 수 있습니다.”
- 사례: “슬로우쿼리 1개 튜닝으로 p95가 크게 줄고, 이후 캐시로 안정화했습니다.”
- 트레이드오프: “캐시는 정합성 복잡도가 증가하므로 TTL/무효화 전략을 같이 설계했습니다.”
Q7. 자주 실수하는 포인트는?
답변
- APM/슬로우로그 없이 감으로 병목 추정
- 인덱스 추가 후 write 성능 악화 검증 누락
- 캐시 도입 후 무효화 정책 부재
- 비동기화 후 멱등성/재처리 설계 누락
추가로, 실행 계획을 한 번 보고 “인덱스를 탔다”고 끝내는 실수도 많습니다. 실제 트래픽의 조건값 분포, 통계 갱신 시점, 복제본 지연에 따라 계획이 달라질 수 있으므로 배포 전후의 같은 지표를 비교해야 합니다.
Q8. 장애 중 15분 체크리스트를 주세요
답변
- p95/p99, QPS, 에러율 확인
- 상위 슬로우 쿼리 5개 확인
- 락 대기/데드락 로그 확인
- 캐시 적중률, 스탬피드 유무 확인
- 큐 적체(consumer lag) 확인
- 배포·배치·스키마 변경 시각과 지연 시작 시각 대조
- 장기 트랜잭션과 pool wait 상위 요청 확인
- 완화 조치의 중단 기준(p95, 오류율, write 지연) 기록
- 조치 전·후 대시보드 링크와 가설을 장애 기록에 남김
요약
- DB 병목 대응은 기술 나열이 아니라 우선순위 프레임이 핵심입니다.
- 측정 없는 스케일아웃은 비용 증가로 끝나기 쉽습니다.
- 면접에서는 “왜 그 순서인지"를 설명하면 실무 감각이 드러납니다.
💬 댓글