장애 대응 보고서 및 부하 테스트

1. 개요

  • 문서 목적

    • 해당문서는 콘서트 좌석 예약 시스템의 API 성능 테스트 및 장애 대응 과정, 개선 방안을 정리한 보고서이다.

  • 시스템 개요

    • 대기열(Queue) 처리로 30초의 인위적 지연이 존재하지만, 이는 병목 요소가 아닌 의도된 대기임을 전제한다.

  • 성능 테스트 개요

    • 테스트 대상 API

      1. POST /tokens/issue (토큰 발급)

      2. GET /tokens/status (대기열 상태 조회)

      3. GET /concerts/:id/dates/available (일정 조회)

      4. GET /concerts/:id/seats/available (좌석 조회)

      5. POST /reservations/:id/reserve-seats (좌석 예약)

      6. POST /reservations/:id/payment (결제)

    • 테스트 시나리오

      1. 사용자별 토큰 발급

      2. 대기열 30초(인위적 지연)

      3. 콘서트 일정 및 좌석 조회

      4. 좌석 예약결제 요청

      5. 각 API 단계별 응답 시간, 에러율 측정

    • 테스트 환경

      • 도구: k6 스크립트(integration-test.js), Grafana 대시보드

      • 가상 유저(VU): 최대 300

      • 목표 지표: 응답 시간(AVG, P95, P99), 에러율, 처리량(RPS), 커스텀 메트릭(reserve_time, payment_time, 등)


2. 장애 발생 및 원인 분석

2.1. 전체 시스템 장애 발생 시나리오

  1. 일부 API에서 성능 저하가 감지

  2. 원인 분석

    1. 동시성 처리 미흡

      • 기존 Redis Lock만으로는 다수의 동시 요청이 들어올 때 락 경합이 발생하여 응답 지연 및 실패가 증가

      • ReservationFacade의 예약/결제 로직에서 락 적용은 있었으나, 추가적인 낙관적 락 도입이 필요

    2. 쿼리 부하 및 인덱스 부재

      • 예약/결제 관련 DB 쿼리에서 인덱스가 없던 부분이 있어, 풀 스캔 및 비효율적 쿼리 실행이 원인

    3. 캐시 전략

      • 좌석 조회 및 일정 조회에서 캐시 적용이 미흡하여 동일 데이터에 대해 반복적으로 DB 접근이 발생

    4. 토큰 관리 방식 문제

      • 기존에 토큰 관리를 DB에서 수행하던 방식은 응답 지연 및 동시성 문제를 야기

전체 시스템 지표 (개선 전)


3. 장애 해결 과정

3.1. 전체 시스템 개선 조치

✔️ 토큰 관리 개선

  • 기존 DB에서 관리되던 토큰을 Redis로 전환하여, 빠른 조회 및 상태 변경이 가능하도록 개선

  • RedisTokenRepository, RedisTokenQueueRepository, TokenService 등을 활용해 Redis 기반 토큰 관리 체계를 구축

✔️ 동시성 처리 최적화

  • 기존 Redis Lock 외에 낙관적 락(Optimistic Locking) 도입을 검토 및 적용하여, 동시 예약/결제 요청 시 락 경합을 최소화

  • ReservationFacade의 예약 및 결제 로직에서 락 적용을 강화

✔️ 쿼리 부하 개선

  • DB 쿼리 실행 계획(EXPLAIN ANALYZE)을 분석하여 비효율적인 쿼리를 최적화하고, Batch 처리 및 Lazy Loading 기법을 도입

  • 예약/결제 관련 쿼리에서 불필요한 풀 스캔을 방지

✔️ 인덱스 최적화

  • 기존 인덱스가 없던 부분에 대해 인덱스를 추가하여 쿼리 성능을 개선

    • concert_schedule 테이블: concert_id, is_sold_out 복합 인덱스 추가

    • seat 테이블: concert_id, schedule_date 복합 인덱스 추가

    • reservation 테이블: user_id, status 복합 인덱스 추가

✔️ 캐시 적용 강화

  • ConcertService에서 좌석 조회 시 @Cacheable을 활용하여 동일 데이터에 대한 반복 조회를 방지

  • Redis를 통한 토큰 관리와 함께 캐시 전략을 보완하여, 전체 시스템 응답 속도를 향상


4. 성능 테스트 시나리오 및 결과

4-1. 성능 테스트 개요

  • 테스트 대상 API

    1. POST /tokens/issue (토큰 발급)

    2. GET /tokens/status (대기열 상태 조회)

    3. GET /concerts/:id/dates/available (일정 조회)

    4. GET /concerts/:id/seats/available (좌석 조회)

    5. POST /reservations/:id/reserve-seats (좌석 예약)

    6. POST /reservations/:id/payment (결제)

  • 테스트 환경

    • 도구: k6 스크립트(integration-test.js), Grafana 대시보드

    • 가상 유저(VU): 최대 300

    • 목표 지표: 응답 시간(AVG, P95, P99), 에러율, 처리량(RPS), 커스텀 메트릭(reserve_time, payment_time, 등)

  • 테스트 시나리오

    1. 사용자별 토큰 발급 (POST /tokens/issue)

    2. 의도적 30초 대기(대기열 처리 – 분석 대상에서 제외)

    3. 예약 가능한 일정 및 좌석 조회

    4. 좌석 예약 요청 (POST /reservations/:id/reserve-seats)

    5. 결제 요청 (POST /reservations/:id/payment)

circle-check

4-1. 전체 시스템 지표 (개선 후)

circle-info

HTTP REQUEST 분석 내용

Grafana Dashboard 의 HTTP REQUEST
  1. /reservations/:id/payment (500)

    1. Count=1로 500 에러가 1건 발생

    2. 단발성 에러(테스트 중 특정 케이스)일 가능성이 높음

  2. /reservations/:id/payment(200)

    1. 다수의 정상 결제가 발생(예: COUNT=100+).

    2. AVG는 수 ms수십 ms 정도로 보이지만, MAX가 최대 7초까지 치솟고, P95/P99 구간에서 37초대가 관측됨

    3. 일부 요청에서 병목이 발생했을 가능성이 크므로 모니터링 필요

  3. /reservations/:id/reserve-seats (200)

    1. 비교적 요청 수(Count)가 적은 편이지만, MIN/AVG/MAX 모두 수 ms 내외로 매우 빠른 응답

    2. 좌석 예약 로직이 생각 외로 빠르게 처리되는 케이스가 많음

  4. concerts/:id/dates/available, /concerts/:id/seats/available

    1. AVG가 ms 단위로 빠르지만, 간헐적으로 MAX가 수 초(최대 6s)까지 올라가는 경우가 존재

    2. 캐시 미스나 DB 일시 부하, 네트워크 지연 등 특정 상황에서의 지연 발생으로 유추

  5. /tokens/issue, /tokens/status

    1. 주로 AVG가 수 ms~수십 ms 수준으로 안정적

    2. 토큰 발급/상태 조회 로직이 Redis를 통한 캐싱/조회로 빠르게 동작하고 있음

circle-info

핵심 지표 분석 내용

  1. Peak RPS: 약 208 RPS로, 트래픽이 몰리는 구간에서 초당 200건 이상의 요청

  2. Max Response Time: 13.7초

  3. Error Rate: 약 2.47% (HTTP Failures: 270건)

  4. VU Max: 동시 접속자 300

  5. Average Response Time: 504.01ms

  6. Total Requests: 약 10910건 처리

대부분 요청은 평균 504ms 내로 처리되지만, 일부 요청이 최대 13.7초까지 지연됨

  • 결제(payment) API: 대다수 요청은 수십 ms ~ 수백 ms이지만, 일부 요청이 7초 이상 지연되어 P95/P99 구간이 높음

  • 예약(reserve-seats) API: 응답 시간이 매우 짧고 안정적

  • 일정/좌석 조회: 평균은 ms대이지만, 캐시 미스나 DB 부하 시 수 초 단위로 지연되는 사례 존재

  • 토큰 발급/조회: Redis 전환 후 대체로 빠르고 안정적


5. 종합 평가 및 결론

5-1. 전체 시스템 성능 요약

  • 안정성: 테스트 결과 HTTP 실패율(http_req_failed)은 약 2.47%로, 성공률은 약 97.5% (개선 필요)

  • 확장성: 최대 300 VU(동시 사용자)에서 안정적으로 작동하였으며, 시나리오 테스트 기준으로는 초당 약 101건의 요청을 처리할 수 있음 (Queue 대기 시간 고려 필요)

  • 응답성: 대부분의 API는 평균 285.73ms의 응답 시간을 보이나, 일부 요청에서는 최대 13.69초까지 지연된 사례 조회

  • 일관성: 평균 응답 시간 대비 P95가 1.24초 등 일부 지연 사례가 존재하나, 전반적으로는 성능 유지

5-2. 최종 결론

  • 토큰 발급, 일정 조회, 좌석 예약, 결제 프로세스 전체 성능 개선

  • 트랜잭션 충돌과 캐싱 부족 문제 해결, 실패율 감소

  • 인덱스 최적화를 통해 주요 API 응답 속도 개선

5-3. 개선 영역

  • 응답 시간 일관성:

    • 일부 API에서 95번째 백분위 응답 시간이 평균보다 크게 높아 개선 필요

  • 에러 처리:

    • 현재 성공률은 약 97.5%로, 에러 원인 분석 필요

Last updated