아키텍처 온보딩 연습문제

arch-exercises pattern-layered api-internals

이 노트의 사용법

이 노트는 air-intl-adapter아키텍처를 “읽기”에서 “추적/디버깅/확장”으로 끌어올리기 위한 연습문제 모음이다. 각 문제는 trace(흐름 추적) / config(설정 이해) / debug(장애 진단) / extend(기능 확장) 중 하나의 유형이며, 신입이 혼자 풀 수 있도록 시작점 파일을 함께 준다. 푸는 법: ① 먼저 시작 파일을 열어 직접 추적해 본다. ② 답을 적어 본다. ③ [!answer]- 정답 보기를 펼쳐 파일경로·단계까지 맞췄는지 대조한다. 단순히 결론만 맞추지 말고 “어느 파일 몇 번째 단계에서 그 일이 일어나는가”를 짚는 연습이 핵심이다.

선행 학습: system-architecturerequest-flowcaller-callee-mapcommon-operations. 횡단 개념은 async-coroutines, error-handling, resilience-and-events.


0. 이 연습이 단련하려는 6가지 근육

#주제유형단련 포인트관련 노트
1요청 흐름 추적traceHTTP 진입 → 필터 → 컨트롤러 → 서비스 → 클라이언트 → 외부request-flow
2레이어 경계config/trace어느 책임이 어느 레이어에 사는가, 의존 방향system-architecture, caller-callee-map
3공통 DTO 계약trace/extendkey/pnr이 단계를 잇는 끈, View 변환 위치common-operations
4비동기 / 코루틴debugpmap 부분 실패, 디스패처, fire-and-forget 유실async-coroutines
5에러 전파debug예외 타입 → HTTP status, findRootCause, Sentry 조건error-handling
6회복탄력성config/extend서킷브레이커 OPEN, fallback, 재시도 라이브러리 구분resilience-and-events

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

이 어댑터에는 POST /search?supplier=X 같은 단일 진입점이 없다. Triple 예약 시스템이 /internals/{SUPPLIER}/... 경로로 공급사별 컨트롤러를 직접 부른다. 그래서 “요청 추적”은 항상 그 공급사의 {Name}{Op}Controller 에서 시작한다. → system-architecture


문제 1 — [trace] 검색 요청 한 건의 콜 스택을 끝까지 따라가기

POST /internals/AMADEUS/search 요청이 도착했다. HTTP 진입부터 외부 GDS 호출까지 거쳐 가는 모든 레이어의 진입 클래스·메서드를 순서대로 나열하라. (필터 체인 → 컨트롤러 → 서비스 → 코루틴 fan-out → 클라이언트 → OkHttp 전송)

시작점: supplier/amadeus/interfaces/controller/internals/AmadeusSearchController.kt


문제 2 — [config/trace] 책임을 올바른 레이어에 배치하기

아래 5가지 책임은 각각 어느 레이어(interfaces / application / infrastructure / support)에 있어야 하는가? 그리고 그 근거가 되는 실제 클래스를 하나씩 대라.

  1. “이 요청 파라미터가 유효한가” 검증
  2. 검색결과를 Redis에 저장/복원
  3. SOAP 본문을 만들어 OkHttp로 실제 전송
  4. 여러 공급사가 공유하는 코루틴 래퍼·MDC 컨텍스트
  5. 서킷브레이커 부착 + View 변환

문제 3 — [trace/extend] keypnr, 단계를 잇는 두 개의 끈

검색 → 예약 → 발권 → 취소로 이어지는 오퍼레이션에서, 각 단계는 key 또는 pnr 중 어떤 식별자를 입력으로 받는가? 그리고 “검색 결과를 골라 예약을 만들 때” 그 검색 운임이 코드 어디에서 어떻게 복원되는지 추적하라.

시작점: common-operations §1, supplier/amadeus/application/AmadeusBookingService.kt


문제 4 — [debug] 검색 OD 조합 5개 중 2개가 타임아웃이면?

AmadeusFlightSearchService#search가 출발-도착(OD) 조합 5개를 pmap으로 병렬 호출하는데, 그중 2개가 SOAP 타임아웃이 났다. 클라이언트(Triple)는 무엇을 받는가? 만약 5개 전부 실패하면? 그리고 이 동작을 만드는 코드 위치를 짚어라.

시작점: support/util/CoroutineExtensions.kt, supplier/amadeus/application/AmadeusFlightSearchService.kt


문제 5 — [debug] 같은 “검색 실패”인데 왜 어떤 건 500이고 어떤 건 410·200인가

운영 중 다음 3가지 응답을 관찰했다. 각각 어떤 예외/경로에서 나왔고, 호출자(Triple)는 어떻게 대응해야 하는지 진단하라.

(a) 200 OK + 빈 리스트 [] (b) 410 GONE, body {"code":"INVALID_CACHE_KEY"} (c) 500, body {"code":"SEARCH_FAILED"}

시작점: supplier/amadeus/interfaces/controller/internals/AmadeusSearchController.kt, support/exception/RestExceptionHandler.kt, supplier/amadeus/domain/repository/AmadeusFareItineraryRepository.kt


문제 6 — [config] 서킷브레이커를 정확히 이해했는지 점검

application.ymlresilience4j.circuitbreaker.configs.search를 보고 답하라.

  1. slidingWindowSize: 180은 “최근 180건”인가 “최근 180초”인가?
  2. amadeus 서킷이 OPEN일 때 sabre 검색도 막히는가?
  3. 임계값(failureRateThreshold: 35)을 prod에서만 바꾸려면 어느 파일을 고치는가?
  4. 재시도(@Retryable)도 같은 resilience4j 블록에서 설정하는가?

시작점: src/main/resources/application.yml, resilience-and-events §1·§2


문제 7 — [debug] fire-and-forget 코루틴은 어디로 사라지나

예약 실패 시 AmadeusBookingServicecancelService.pnrCancelAsync(pnr)를 부른다. (a) 이 취소 작업의 예외는 어디로 가며 호출자에게 전파되는가? (b) pnrCancelAsync 안의 delay(5000) 도중 애플리케이션이 재배포되면 무슨 일이 생기는가? (c) 이 백그라운드 작업이 던진 예외는 Sentry에 잡히는가?

시작점: supplier/amadeus/application/AmadeusBookingService.kt:179, support/util/CoroutineExtensions.kt, support/exception/AdapterCoroutineExceptionHandler.kt


문제 8 — [extend] 새 공급사 “팬텀항공(PHANTOM)” 추가 설계

가상의 LCC “팬텀항공”을 검색만 지원하도록 추가한다. 만들어야 할 파일/클래스와 등록 지점을 레이어 순서대로 나열하라. 그리고 검색 컨트롤러에 반드시 붙여야 하는 횡단 요소 2가지는?

시작점: supplier/groupair/(가장 작은 모듈, 골격 학습용), system-architecture §3.1



관련 노트