지뢰요소 디버깅 연습문제

arch-cross-cutting pattern-pitfalls pattern-incident

이 노트의 사용법

이 문서는 air-intl-adapter에서 실제로 사고가 나는 지점(landmines)을 “장애 시나리오”로 재구성한 디버깅 훈련 모음이다. 전 문항이 debug 유형이며, 운영에서 마주칠 법한 증상을 먼저 주고 신입이 직접 조사 순서를 세워 보게 한다. 푸는 법: ① 증상만 보고 “내가 콜이라면 어디부터 로그를 깔까”를 적는다. ② 조사 순서 → 근본원인 → 예방을 스스로 정리한다. ③ [!answer]- 정답 보기를 펼쳐 파일경로·라인·예외 타입·전파 경로까지 맞췄는지 대조한다.

이 시스템의 사고는 메시지큐가 아니라 4개 경로로만 표면화된다(중요): ①동기 예외→RestExceptionHandler, ②서킷 OPEN→검색 fallback 200 [], ③fire-and-forget 코루틴→AdapterCoroutineExceptionHandler(Sentry 로깅만), ④Slack 수동 경보(best-effort). → landmines §0, error-handling, async-coroutines, resilience-and-events


0. 디버깅 근육 6 + α (이 문서가 다루는 함정)

#시나리오대표 함정핵심 노트
1GDS 세션 누수 → 전체 예약 마비stateful 세션 미종료(Amadeus/Sabre)landmines §1, amadeus-pitfalls, sabre-pitfalls
2”발권 성공인데 결제/PNR 안 닫힘”fire-and-forget 보상취소 유실async-coroutines, landmines §2
3검색 결과 0건인데 장애인가 정상인가서킷 OPEN 200 [] vs isSearchable vs pmap 부분실패resilience-and-events, landmines §7
4외화 운임이 100배 / 1원 안 맞음통화 decimals 미적용, tax+fuelCharge 이중계상landmines §5, lufthansa-pitfalls, amadeusndc-pitfalls
5T’way 결제만 전 건 인증 실패SEED 인증/암호화 경로 깨짐tway-pitfalls, landmines §1·§6
6재발행이 자꾸 “실패”로 보임202+폴링키 흐름 오해, ERROR 재던짐common-operations, landmines §10
7코루틴 예외가 흔적도 없이 사라짐withAsync 핸들러 부재, pmap swallowasync-coroutines, error-handling
8Sentry에 안 잡힘 / Slack이 안 옴.capture() 누락, 자동 Slack 없음error-handling, landmines §4

디버깅 제1원칙 — "이건 어느 표면화 경로인가?"

증상을 받으면 가장 먼저 4개 경로 중 어디로 드러난 사고인지 분류하라. 5xx면 ①(동기예외), 200 []이면 ②(서킷 OPEN) 또는 검색 부분실패, “API는 성공인데 뒤가 안 맞음”이면 ③(fire-and-forget), Sentry/Slack은 자동이 아니라 조건부/수동이다. 이 분류만으로 조사 범위가 1/4로 줄어든다.


문제 1 — [debug] “오후부터 Amadeus 예약·발권·취소가 전부 막혔다”

오후 2시경부터 Amadeus(/internals/AMADEUS/booking, /ticketing, /cancel)가 전부 실패하기 시작했다. 검색(/search)은 정상이다. 에러 메시지는 GDS 측 “no more sessions available / session limit exceeded” 류다. 재배포하면 잠깐 풀렸다가 다시 막힌다.

증상: 비검색 Amadeus 오퍼레이션 전량 실패, 검색은 정상, 재배포 후 일시 회복.

시작점: supplier/amadeus/application/AmadeusBookingService.kt, support/protocol/StatefulBuilder.kt(있다면), landmines §1


문제 2 — [debug] “취소 API는 200인데 실제 PNR이 안 닫혔다 / 결제 환불이 안 됐다”

발권 실패 케이스에서 고객은 취소/환불 성공 응답(200)을 받았다. 그런데 며칠 뒤 정산에서 고아 PNR미환불 결제가 발견됐다. 어떤 건은 멀쩡하고, 어떤 건만 이런 불일치가 난다. 재현이 들쭉날쭉하다.

증상: 동기 응답은 성공인데 후속 보상(취소/결제취소)이 누락. 산발적 재현.

시작점: supplier/amadeus/application/AmadeusBookingService.kt:179, AmadeusCancelService.kt:311, support/util/CoroutineExtensions.kt, landmines §2


문제 3 — [debug] “특정 공급사만 검색 결과가 0건이다 — 장애인가 정상인가?”

대시보드에서 어떤 공급사의 검색 결과가 한동안 0건으로 보인다. 다른 공급사는 정상. 5xx는 없고 응답코드는 전부 200이다. 같은 0건이라도 원인이 4가지나 된다고 한다. 어떻게 구분하나?

증상: 한 공급사 검색이 200 []. 5xx 없음.

시작점: supplier/amadeus/interfaces/controller/internals/AmadeusSearchController.kt:73, interfaces/request/SearchRequest.kt:26, support/util/CoroutineExtensions.kt:62, landmines §7·§10


문제 4 — [debug] “유럽 노선 운임이 100배로 찍히거나 1원씩 안 맞는다”

Lufthansa/Singapore 등 유럽·동남아 노선에서 운임이 비정상적으로 크게(약 100배) 표시되거나, 검색가와 발권가가 미세하게 어긋난다는 신고가 들어왔다. 국내선·KRW 노선에서는 멀쩡하다.

증상: 외화(EUR/USD/SGD) 노선 운임 100배 부풀림 또는 미세 오차. KRW 노선은 정상.

시작점: lufthansa Offer.kt:182/DataList.kt:163, amadeusndc Passenger.kt, landmines §5


문제 5 — [debug] “T’way 결제만 전 건 인증/암호화 실패한다”

T’way(/internals/TWAY/...)에서 다른 오퍼레이션은 되는데 카드결제가 들어가는 발권/부가결제(/book/ModifyBooking) 만 전 건 실패한다. 어떤 환경에서는 빌드 자체가 깨진다. 또 개인카드 고객만 NPE로 죽는 케이스도 있다.

증상: T’way 결제 경로 전 건 실패, 일부 환경 빌드 실패, 개인카드 NPE.

시작점: supplier/tway/infrastructure/request/CardInfo.kt, build.gradle.kts:67, Dockerfile, tway-pitfalls, landmines §1·§6


문제 6 — [debug] “재발행(reissue)이 자꾸 실패로 보이는데 실제로는 진행 중이다”

Triple 쪽에서 “Korean Air 재발행 API를 부르면 즉시 202가 오는데, 그걸 실패로 처리하고 있다” “또는 결과를 한 번만 조회하고 안 보이면 실패로 친다”는 보고. 어떤 건은 실제 ERROR인데 조용히 넘어간다.

증상: 재발행이 동기 응답을 안 주고 202를 줌. Pending을 실패로 오해. ERROR 누락.

시작점: supplier/koreanair/interfaces/controller/internals/KoreanairTicketingController.kt:53, support/util/PollingUtils.kt, common-operations, landmines §10


문제 7 — [debug] “코루틴에서 던진 예외가 흔적도 없이 사라진다”

병렬 처리 로직을 직접 withAsync로 짠 뒤부터, 한 코루틴이 던진 예외가 호출자에게 안 가고 로그에도 없고 Sentry에도 없다. 어떤 때는 형제 코루틴까지 통째로 죽는다. pmap을 쓸 때와 동작이 다르다.

증상: 코루틴 예외 유실 또는 형제 동반 취소. withAsync 직접 사용 시에만 발생.

시작점: support/util/CoroutineExtensions.kt:28-50, support/exception/AdapterCoroutineExceptionHandler.kt, async-coroutines, error-handling


문제 8 — [debug] “장애가 분명한데 Sentry에 안 잡히거나, 멀쩡한 게 노이즈로 잡힌다”

운영 중 두 정반대 현상이 동시에 보고됐다. (a) 카드 거절(한도초과 등)이 분명히 났는데 Sentry에 안 올라온다. (b) 단순 외부 타임아웃이 INTERNAL_SERVER_ERROR로 Sentry를 도배한다. 응답 code는 또 따로 논다.

증상: 분류된 비즈니스 실패는 Sentry 미보고, 비-ApiException은 Sentry 과보고, 응답/로그 예외 불일치.

시작점: support/exception/RestExceptionHandler.kt, support/web/ClientSupport.kt:62, support/exception/Exceptions.kt, error-handling, landmines §4



관련 노트