[사건의 발단] "결제가 너무 느려요 !!!!!"
평화롭던 서비스에 조금씩 비상이 걸리기 시작했다.
특히 이벤트 기간이나 저녁 피크 시간대만 되면 "결제 완료 페이지로 넘어가는 데 한 세월이다"라는 고객 불만이 속출했다.
1. 장바구니에서 결제페이지로 진입
2. 결제페이지에서 쿠폰 선택하여 적용 후 결제 시도
3. 결제 처리
4. 결제 및 주문 관련 대이터 세팅
(이 사이에서 결제 지연 이슈 발생 !!!)
5. 결제완료 페이지 진입
심지어 결제완료 페이지로 진입하기까지의 시간이 최대 146초(2분 26초)로 너무 길어지자,
고객들이 오류인 줄 알고 '새로고침'이나 '뒤로가기'를 누르고 주문을 다시 시도하는 바람에 중복결제까지 발생하는 심각한 상황이었다.
[원인 분석] 서버 사양 문제일까?
처음에는 서버나 DB의 성능 부족이 의심되었다.
부장님께서 로직이나 관련된 쿼리를 확인해주셨을 때 별 다른 특이점은 없는 것으로 보여, AWS Auto Scaling으로 서버 대수를 늘리거나 사양을 높이는 방안을 클라이언트에 제안할 것을 고려하셨다.
하지만 내가 AWS 콘솔에서 ALB와 RDS 지표를 확인해본 결과, 트래픽 피크치에서도 CPU 사용률이나 메모리 점유율은 안정적이었다.
그리고 쿠폰을 사용한 고객들만 결제지연 이슈가 발생했고, 쿠폰을 사용하지 않은 고객들은 결제지연 이슈가 발생하지 않은 점도 의문이었다.
그래서 무작정 결제 관련 로그를 한달동안 들여다보기 시작했다.
쏟아지는 CS 문의에 내가 수동으로 체크해서 중복 결제를 처리해주는 것도 힘들었지만, 무엇보다 이 이슈를 해결하지 못하면 우리 회사에 대한 클라이언트의 신뢰감이 땅 끝으로 꺼질 것만 같았다.
저때 웹 프로젝트를 신입으로 입사해서 맡은 지 거의 6개월 됐던 때였던 것 같은데
그땐 간단한 CRUD만 할 줄 알았지 이런 트러블슈팅은 처음이었고 누군가 나서서 도와줄 상황도 되지 않았기에
내가 이걸 해결할 수 있을까 의문이 들기도 했지만 한편으로는 해결하고 싶다는 간절한 마음으로 로그를 몇 번이고 보고, 시간 남을 때마다 혹은 짬내서 보고, 집에 가서도 로직을 봤던 것 같다.
지금 생각해도 너무 아찔한 순간 TOP 3위 안에 드는 것 같다.
[이슈 발생 원인] 컬럼 하나에 인덱스가 없었던 것
결제 로그와 로직, 쿼리 모두 하나하나 뜯어보고 추적한 결과, 범인은 의외의 곳에서 발견되었다.
바로 특정 쿠폰을 사용하기 전에 한 번 더 사용 이력 여부를 조회하는 SELECT 문이었다.
-- 문제의 쿼리
SELECT *
FROM CUSTOMER_COUPON
WHERE ORDER_ID = #{orderId}
유저들의 쿠폰함 데이터가 쌓여가는 CUSTOMER_COUPON(가칭) 테이블.
데이터가 수집만건 이상 쌓여가고 있었는데, 정작 조회 조건인 ORDER_ID(가칭/주문 아이디) 컬럼에 인덱스가 없었던 것이다 !
인덱스가 없으니 DB는 매 결제마다 수만 건의 데이터를 처음부터 끝까지 다 뒤지는 Full Table Scan을 하고 있었던 것이었다.
데이터가 적은 테스트 DB에서는 멀쩡하다가, 데이터가 방대한 운영 DB에서만 결제지연 현상이 발생했던 이유가 바로 여기 있었던 것이다.
[해결 및 모니터링] 평균 로딩 약 16,438배 시간 단축의 기적
부장님께 원인과 해결책을 발견하자마자 말씀드렸던 것 같다.
원인은 특정 쿠폰 사용 이력 조회 SELECT 쿼리문에서 조회 조건인 주문 아이디 컬럼의 인덱스가 부족해서 생긴 것이다.
해결책은 CUSTOMER_COUPON 테이블 내 ORDER_ID 컬럼에 인덱스를 부여하는 것이라고.
인덱스를 추가한 결과, 상황은 종료되었다.

| 날짜 | 결제완료 페이지 로딩 시간(초) | ||
| 최소값 | 최대값 | 평균값 | |
| 인덱스 작업 전 (서버 1, 2 전체) | 29.1 | 146.3 | 52.6 |
| 인덱스 작업 후 (서버 - 1) | 0.002 | 0.003 | 0.0032 |
| 인덱스 작업 후 (서버 - 2) | 0.003 | 0.005 | |
2~3배 이상의 주문량이 몰리는 이벤트 기간에도 결제 지연은 단 1건도 발생하지 않았다.
지연이 사라지니 자연스럽게 고객의 중복 결제 액션도 사라졌고, 시스템은 다시 안정화되었다.
이번 장애 대응을 통해 배운 점
- 지표는 거짓말하지 않는다 : AWS Cloud Watch 탭을 통해 ALB 및 RDS를 모니터링 한 결과, 자원 부족의 이유는 아닐 것 같다는 느낌을 받았고, 이는 단순히 서버 성능을 개선해달라고 클라이언트에 요청을 보내기 전 로그와 로직을 꼼꼼히 분석해야 한다는 결심을 굳혀주었다.
- 인덱스의 중요성 : 설계 당시에는 데이터가 적어 문제가 없더라도, 서비스가 성장함에 따라 인덱스 하나가 서비스 전체의 생사를 결정할 수 있음을 배웠다.
- 로그 추적과 로직 분석의 힘 : 결제 로그와 로직 분석을 끝까지 살펴보았던 과정이 결국 해결의 실마리가 되었다.
인덱스 하나 때문에 3개월간 고통 받았다니 ..
이를 통해 새로 쿼리를 작성할 때도 쿼리 실행할 때의 성능을 고려하여 작성하려 노력하게 되었다.
한창 통신사 할인 이벤트 하고 있었을 때라 트래픽 제일 몰리는 때에 터졌던 이슈의 아찔함은 이루 말할 수 없었다.
나 혼자서만 이 프로젝트를 담당하게 된 것이라 도움을 줄 사람도, 해결해줄 사람도 결국 나 자신밖에 없어서 느꼈던 좌절감도.
결국 원인과 해결책을 찾았음에도 인덱스를 추가하기 전까지 '이걸로 해결이 안되면 어쩌지?'라는 막연한 불안감도.
하지만 원인을 찾기까지 거의 아무것도 몰랐고 아무 경험도 없던 내가, 어찌되었든 원인과 해결책을 찾았다는 뿌듯함.
이제 앞으로 코드를 작성하거나 개선할 때 단순히 기능만 되게 만드는 것이 아닌, 성능과 예외사항을 고려하면서 작성하자는 한 단계 더 나아간 마음가짐으로 로직 퀄리티를 신경쓰게 되었고, 이로 인해 내 실력 또한 성장하게 되었다.
남들이 보기엔 별 거 아닐 수 있지만 처음으로 실무에서 뭔가를 해냈다는 뿌듯함을 느꼈던 사건이었다.
'[Project] > 업무일지' 카테고리의 다른 글
| [PUTTY] 한글 깨짐 현상 해결하기 (0) | 2026.03.20 |
|---|---|
| 같은 EC2인데 왜 운영체제(OS)가 다를까? (Amazon Linux vs CentOS) (1) | 2026.03.12 |
| [Java/SpringBoot] Apache Commons Lang의 보안 허점, 직접 만든 커스텀 HTML Escape 메서드로 해결하기 (0) | 2026.03.11 |
| [AWS/CloudWatch/RDS] 가용메모리 및 CPU 사용률 지표 확인 (1) | 2025.10.23 |
| [에러 핸들링] 파라미터 내 처리 불가 데이터 삽입 시 톰캣 기본 에러페이지 내 서버 버전 미노출 처리 (0) | 2025.09.17 |