공급사 온보딩 연습문제

pattern-layered api-internals test-exercises

이 노트의 사용법

이 노트는 11개 공급사 모듈을 “읽기”에서 “추적·디버깅·확장”으로 끌어올리는 연습문제 모음이다. exercises-architecture가 레이어/요청흐름 같은 공통 골격을 단련했다면, 이 노트는 공급사별 프로토콜 차이(GDS SOAP 세션 / NDC 폴링 / LCC SEED 암호화) 가 코드에 어떻게 드러나는지를 짚는다. 푸는 법: ① 시작점 파일을 직접 열어 추적한다. ② 답을 적는다. ③ [!answer]- 정답 보기를 펼쳐 파일경로·클래스/메서드·단계까지 맞췄는지 대조한다. “결론”이 아니라 “어느 파일 몇 번째 단계에서 그 일이 일어나는가” 를 맞히는 것이 핵심이다.

선행 학습: common-operations → 대표 공급사 *-overview*-protocol*-pitfalls. 횡단 개념은 async-coroutines, error-handling, resilience-and-events.


0. 이 연습이 단련하려는 근육과 공급사 매핑

공급사 = 프로토콜 클래스 + 특이점

같은 6개 오퍼레이션(Search/Booking/Ticketing/FareRule/Queue/CashReceipt)을 노출해도, 프로토콜 클래스마다 구현이 근본적으로 다르다. 아래 표의 “특이점”이 곧 출제 포인트다.

클래스공급사특이점 (출제 포인트)대표 노트
GDS/SOAP (stateful)amadeus(1A), sabre(1S), galileo(1G)PNR 세션 상태(Start→InSeries→End), EOT(End Of Transaction)amadeus-protocol, sabre-protocol, galileo-protocol
NDCamadeusndc, koreanair(V21.3), lufthansa(V17.2), singaporeair(EDIST 18.1)무상태 OrderCreate/OrderReshop, 재발행=Reshop, 비동기 폴링lufthansa-protocol, koreanair-protocol, singaporeair-protocol
LCC/RESTtway, jinair, jejuairSEED 암호화 인증, Ancillary/AgencyCredit, 취소 코루틴tway-protocol, jinair-protocol, jejuair-protocol
그룹운임groupair가장 작은 모듈, 단체 예약groupair-overview

중앙 디스패처가 없다는 사실을 항상 기억하라

POST /search?supplier=X 같은 단일 진입점은 없다. Triple 예약 시스템이 /internals/{SUPPLIER}/... 경로로 공급사별 {Name}{Op}Controller 를 직접 호출한다. 그래서 공급사 추적은 항상 supplier/{name}/interfaces/controller/internals/{Name}{Op}Controller.kt 에서 시작한다. → system-architecture, caller-callee-map


문제 1 — [extend] 신규 공급사 “XYZ”를 추가하려면 어디를 손대야 하나

신규 LCC 공급사 XYZ(REST, Search/Booking/Ticketing/FareRule 지원)를 추가하라는 요청을 받았다. 코드/설정에서 반드시 건드려야 하는 위치를 빠짐없이 나열하라. (힌트: enum, 패키지 레이어, 컨트롤러 경로 규칙, 설정 프로퍼티, 서킷브레이커 인스턴스)

시작점: support/enums/Supplier.kt, configuration/Properties.kt, src/main/resources/application.yml


문제 2 — [trace] Amadeus 예약(Booking) 한 건의 세션 흐름 추적

POST /internals/AMADEUS/bookings 가 도착했다. AmadeusBookingService.book() 내부에서 TOPAS 세션이 어떤 상태 단계(Start/InSeries)를 거치며 어떤 GDS 액션을 부르는지 순서대로 나열하라. 특히 PNR 저장 시 경고(warning) 처리 로직이 왜 두 번 호출될 수 있는지 설명하라.

시작점: supplier/amadeus/application/AmadeusBookingService.kt (book), supplier/amadeus/support/util/StatefulBuilder.kt


문제 3 — [config/debug] Tway SEED 인증은 어떻게 동작하나 — 그리고 두 종류의 SEED를 구분하라

Tway 검색 호출이 401/인증 실패로 떨어진다. TwayClient.retrieveRoute().authenticate(...) 가 어떤 값을 어떻게 만드는지 추적하고, 이 코드베이스에 존재하는 “두 가지 SEED 메커니즘” 을 구분해 설명하라. (어느 것이 외부 jar이고 어느 것이 자체 구현인가)

시작점: supplier/tway/infrastructure/TwayClient.kt, support/util/SeedEncryptor.kt, support/util/ReflectionUtils.kt, libs/TwaySEED.jar


문제 4 — [trace] Lufthansa NDC 재발행(Reissue)이 왜 “폴링” 응답인가

POST /internals/LUFTHANSA/ticketing/addition(재발행) 의 응답이 즉시 결과가 아니라 202 ACCEPTED + 키다. 왜 이런 비동기 폴링 구조이고, 클라이언트는 결과를 어떻게 받는지 단계별로 추적하라. NDC OrderReshop과 어떻게 연결되는가?

시작점: supplier/lufthansa/interfaces/controller/internals/LufthansaTicketingController.kt (reissue/checkReissue), support/util/PollingUtils.kt, supplier/lufthansa/application/LufthansaTicketingService.kt (reissue)


문제 5 — [trace] Sabre Queue 처리: 조회와 제거가 왜 세션 토큰을 매번 열고 닫나

GET /internals/SABRE/queues(조회)와 PUT /internals/SABRE/queues(제거)의 내부 동작을 추적하라. 특히 remove()repeat(queueCount) 루프로 PNR을 하나씩 넘기며(QR/I) 처리하는 이유와, 세션 토큰 생명주기를 설명하라.

시작점: supplier/sabre/application/SabreQueueService.kt, supplier/sabre/interfaces/controller/internals/SabreQueueController.kt


문제 6 — [debug] 코루틴 병렬 검색에서 “일부만 성공”하면 응답은 어떻게 되나

운영 중 Amadeus 검색이 “결과가 비거나(빈 리스트) 가끔 SEARCH_FAILED 예외”로 갈린다. AmadeusFlightSearchService.search()pmap { ... }.onFailure { ... }.getOrEmpty() 가 부분 실패를 어떻게 다루는지, 그리고 컨트롤러의 서킷브레이커 fallback과 어떻게 맞물리는지 설명하라.

시작점: supplier/amadeus/application/AmadeusFlightSearchService.kt (search), support/util/CoroutineExtensions.kt (pmap/onFailure/getOrEmpty/getOrThrow), supplier/amadeus/interfaces/controller/internals/AmadeusSearchController.kt


문제 7 — [debug] Jejuair 취소가 “조건부 재시도”하는 이유와 위험

JejuairCancelService.cancel(pnr)@Retryable(... exceptionExpression = "@jejuairCancelService.shouldRetry(#root)")조건부 재시도한다. 그런데 calculateCancelFee 호출이 부수효과(side effect)를 갖는다는 주석이 있다. 무한/중복 취소 위험을 어떻게 통제하는지, 그리고 어떤 예외는 재시도하면 안 되는지 추론하라.

시작점: supplier/jejuair/application/JejuairCancelService.kt


문제 8 — [config/extend] LCC 부가 기능: Tway AgencyCredit과 Ancillary 딥링크

Tway는 다른 GDS에 없는 AgencyCredit(대리점 크레딧 잔액)과 Ancillary 딥링크를 노출한다. GET /internals/TWAY/agency-credit 의 경로/응답 구조를 추적하고, Ancillary 딥링크가 SEED 인코딩을 어디서 쓰는지 설명하라. 이런 “공급사 고유 오퍼레이션”을 추가할 때 공통 계약(common-operations)과 어떻게 공존하나?

시작점: supplier/tway/interfaces/controller/internals/TwayAgencyCreditController.kt, supplier/tway/application/TwayAgencyCreditService.kt, supplier/tway/infrastructure/ancillary/TwayAncillaryDeepLink.kt


문제 9 — [trace] Sabre 코루틴 사용처: APIS 변경이 runBlocking 안에서 무엇을 순서대로 하나

Sabre는 비동기/코루틴이 집중된 모듈 중 하나다. SabrePassengerService.changeApis(pnr, validatingCarrier, passengers)runBlocking { ... } 안에서 기존 SSR/OSI 삭제 → APIS 재생성 → EOT 를 어떻게 순서 보장하는지, 그리고 왜 세션을 finally로 닫는지 추적하라.

시작점: supplier/sabre/application/SabrePassengerService.kt


문제 10 — [debug] “어느 공급사 모듈인지” 5초 만에 식별하기

장애 알림에 /internals/SINGAPOREAIR/ticketing 5xx 로그만 있다. 코드에서 이 요청을 처리하는 컨트롤러 → 서비스 → 클라이언트를 규칙만으로(파일을 일일이 grep하지 않고) 어디서 찾을지 즉시 말하라. 또 이 모듈이 NDC EDIST라는 사실에서 무엇을 예상해야 하나.

시작점: 디렉터리 규칙 supplier/{name}/{layer}/...


문제 11 — [extend] Galileo FareRule을 병렬 조회로 바꾸려면

GalileoFareRuleService 가 여러 운임에 대해 FareRule을 순차 조회해 느리다. 이를 pmap 병렬로 바꿀 때 (1) 어떤 공통 유틸을 쓰고 (2) 부분 실패를 어떻게 다룰지, (3) Galileo의 stateful 세션 특성상 주의할 점을 설계하라.

시작점: supplier/galileo/application/GalileoFareRuleService.kt(이미 pmap 사용처 존재), support/util/CoroutineExtensions.kt


정리

관련 노트: exercises-architecture, exercises-debugging, common-operations, onboarding-map, quick-reference, landmines