검사 유입이 집중될 때 발생하는 조회 지연을 개선하고, 이후 복제본 직접 쓰기로 발생한 장애를 복구·보완한 사례입니다.
DB 구성: Master(쓰기용 원본 DB) / Slave(조회용 복제 DB)
<aside>
대량 조회를 분리하고, 복제 장애 때 사용자 조회를 먼저 복구했습니다.
조회 개선 시점: 2025.09
구현 방식: Spring 트랜잭션 속성에 따른 DB 라우팅
대량 조회는 Slave로 보내고, 쓰기와 복제 경로는 유지했습니다. 복제 장애 때는 조회 경로를 Master로 전환했습니다.
사용자 제보를 받고 DB 잠금·인덱스·로그를 점검했지만 원인을 특정할 만한 이상은 찾지 못했습니다. 운영 DB 덤프를 개발 PC에 복원했을 때는 조회가 빠르게 응답했습니다.
이후 월요일 검사 유입으로 INSERT·UPDATE가 많아지는 시간대에 지연이 발생한다는 점을 확인했습니다. 이미 구축돼 있던 Slave에서는 같은 지연 현상이 나타나지 않았습니다.
이 비교를 바탕으로 쓰기 집중과 조회 지연의 연관성을 좁히고, 대량 조회를 분리하기로 했습니다. 특정 잠금이나 I/O 경합을 확정 원인으로 판단한 것은 아닙니다.
Master와 Slave의 복제 구성은 이미 구축돼 있었습니다. 기존 Slave에서 조회가 원활한 것을 확인한 뒤, 대량 조회가 Slave를 선택하도록 애플리케이션의 라우팅 코드를 수정했습니다.
@Transactional(readOnly = true)로 지정한 조회에서 AOP가 현재 트랜잭션의 읽기 전용 여부를 확인하고, 라우팅 데이터소스가 Slave를 선택하도록 구성했습니다. DB의 직접 쓰기를 막는 설정은 별도로 적용했습니다.
평상시에는 트랜잭션 속성으로 DB를 선택하고, 복제 중단 시에는 장애 대응으로 조회 경로를 Master로 변경했습니다. 저장 직후 데이터가 Slave에 반영되기 전의 조회 처리는 아래 보완 과제에 정리했습니다.
개선 효과는 DB에서 특정 쿼리를 직접 실행해 걸린 시간을 측정하는 방식으로 확인했습니다.
| 측정 대상 | 변경 전 | 변경 후 |
|---|---|---|
| DB에서 직접 실행한 특정 쿼리 | 지연 발생 시 약 2~3분 | 500ms 미만 |
근거 범위: 위 수치와 아래 장애 시각·조회 전환 시간은 당시 측정·운영 경험에 대한 본인 회고입니다. 측정 원본·정확한 SQL·반복 횟수·동일 부하 조건과 장애 발생일은 재확인하지 못했습니다. 검사 1,000건·1~2분은 최초 사용자 제보이며, 표의 특정 쿼리 측정과 구분합니다. 화면 전체 응답시간이나 평균 성능을 나타내는 수치는 아닙니다.