air-intl-adapter 온보딩 맵 (MOC)
module-dashboard arch-overview api-surface
이 문서의 역할 (Map of Content)
0. 한눈에 보는 시스템
flowchart TD Caller["Triple 예약 시스템<br/>호출자 = 라우팅 결정자"] HTTP["HTTP 진입<br/>/internals/SUPPLIER/resource<br/>중앙 디스패처 없음"] subgraph FilterChain["필터 체인"] F1["1. ContentCachingWrapperFilter"] F2["2. MDCFilter"] F3["3. AdapterLoggingFilter"] F1 --> F2 --> F3 end Controller["NameOpController<br/>interfaces"] Service["NameOpService<br/>application"] Client["NameClient<br/>infrastructure"] Supplier["외부 공급사<br/>SOAP / NDC / REST"] Support["공통 횡단 support<br/>MDC · 코루틴 · 암호화 · 캐시 · 예외 · HTTP"] Resilience["상태/장애 전파<br/>Resilience4j 서킷전이 + 예외 전파<br/>+ Slack 경보 + Datadog 태그<br/>메시지큐 없음"] Caller --> HTTP --> FilterChain FilterChain --> Controller --> Service --> Client --> Supplier Client -.-> Support Support -.-> Resilience
30초 요약 — 이것만 기억하라
- 중앙 디스패처가 없다. 어느 공급사를 쓸지는 호출자(Triple)가 URL로 결정하고,
{Name}{Op}Controller가 진입점이다.- 골격이 11번 반복된다.
Controller → Service → Client3개만 따라가면 어떤 공급사든 흐름이 잡힌다.- 외부 프로토콜만 다르다.
interfaces → application → infrastructure → domain/support레이어는 11개 모듈이 동일하다.- DI는 100% 생성자 주입. “누가 무엇을 호출하나”는 곧 “어떤 클래스 생성자에 무엇이 들어있나”와 같다.
1. 매니페스트 (전체 노트 색인)
모든 학습 노트가 여기서 최소 1회 링크된다. 아래 표 + 공급사 표(§2)가 전체 노트맵이다.
00 대시보드
| 노트 | 설명 |
|---|---|
| onboarding-map | (이 문서) 전체 색인 MOC |
| quick-reference | 빠른 참조 치트시트 (URL/명령/용어) |
01 아키텍처
| 노트 | 설명 |
|---|---|
| system-architecture | 레이어/패키지 구조, 스택 4대 축, 단일 jar 구성 |
| request-flow | 요청 1건의 생애주기 (필터 → 컨트롤러 → 서비스 → 클라이언트 → View) |
| caller-callee-map | 누가 누구를 호출하나 — 생성자 주입 기반 콜그래프, 변경 영향도 |
| common-operations | 5대 핵심 오퍼레이션(Search/FareRule/Booking/Ticketing/Cancel) 공통 흐름 |
02 횡단 관심사 (Cross-cutting)
| 노트 | 설명 |
|---|---|
| interfaces-dtos | 공급사 중립 공통 계약 — request/response DTO와 of(...) 오버로드 |
| support-common | enum 코드매핑·암호화·로깅·HTTP·MDC·캐시 등 횡단 인프라 |
| error-handling | ApiException 계층 + ErrorMessage enum + Sentry/Slack 경보 |
| async-coroutines | 코루틴 래퍼(withBlocking/pmap), 블로킹 경계, 부분실패 처리 |
| resilience-and-events | Resilience4j 서킷/리트라이 + Slack 경보 = 메시지큐 없는 상태전파 |
| configuration-and-infra | Redisson/Redis·OkHttp·AWS Secrets·프로파일·S3 |
14 DevOps
| 노트 | 설명 |
|---|---|
| build-deploy-config | Gradle 빌드, 로컬 셋업, CI/CD 파이프라인, 배포 계정 매핑 |
03~13 공급사별 (각 4노트: overview/operations/protocol/pitfalls)
표 §2 모듈 맵에서
*-overview를 진입점으로 연결한다. 전체 위키링크 목록:amadeus-overview · amadeus-operations · amadeus-protocol · amadeus-pitfalls sabre-overview · sabre-operations · sabre-protocol · sabre-pitfalls galileo-overview · galileo-operations · galileo-protocol · galileo-pitfalls amadeusndc-overview · amadeusndc-operations · amadeusndc-protocol · amadeusndc-pitfalls tway-overview · tway-operations · tway-protocol · tway-pitfalls jinair-overview · jinair-operations · jinair-protocol · jinair-pitfalls koreanair-overview · koreanair-operations · koreanair-protocol · koreanair-pitfalls lufthansa-overview · lufthansa-operations · lufthansa-protocol · lufthansa-pitfalls singaporeair-overview · singaporeair-operations · singaporeair-protocol · singaporeair-pitfalls jejuair-overview · jejuair-operations · jejuair-protocol · jejuair-pitfalls groupair-overview · groupair-operations · groupair-protocol · groupair-pitfalls
연습문제 & 지뢰
| 노트 | 설명 |
|---|---|
| exercises-architecture | 아키텍처 이해 연습문제 |
| exercises-suppliers | 공급사별 흐름 추적 연습문제 |
| exercises-debugging | 장애/디버깅 시나리오 연습문제 |
| landmines | 지뢰 모음 — 컴파일러가 못 잡는 의미적 함정 |
2. 모듈 맵 (11개 공급사 + 횡단)
중요도(★)는 온보딩 학습 우선순위 기준이다 — 규모·고유 패턴·결제/환불 리스크를 종합했다.
규모는 소스 디렉터리 바이트 기준(
src/main/kotlin/.../supplier/{name}).
| 공급사 | 코드 | 타입 | 규모 | 중요도 | 지원 오퍼레이션 | 진입 노트 |
|---|---|---|---|---|---|---|
| Amadeus | 1A | GDS/SOAP (stateful PNR 세션) | 약 3.9 MB / 873 .kt (최대) | ★★★ | Search·Booking·Ticketing·FareRule·Queue·CashReceipt | amadeus-overview |
| Sabre | 1S | GDS/SOAP | 약 3.8 MB / 882 .kt | ★★★ | Search·Booking·Ticketing·FareRule·Queue·CashReceipt | sabre-overview |
| Galileo (Travelport) | 1G | GDS/SOAP (Universal API) | 약 2.5 MB / 525 .kt | ★★★ | Search·Booking·Ticketing·FareRule·Queue·CashReceipt | galileo-overview |
| Amadeus NDC | — | NDC (ART) | 약 1.6 MB / 357 .kt | ★★ | Search·Booking·Ticketing·FareRule·Queue | amadeusndc-overview |
| T’way Air | TW | LCC/REST (SEED 암호화) | 약 1.2 MB / 253 .kt | ★★ | Search·Booking·Ticketing·FareRule·Ancillary·AgencyCredit | tway-overview |
| Jin Air | LJ | LCC/REST | 약 0.7 MB / 114 .kt | ★★ | Search·Booking·Ticketing·FareRule·Ancillary·AgencyCredit | jinair-overview |
| Korean Air | KE | NDC (V21.3) | 약 1.0 MB / 213 .kt | ★★ | Search·Booking·Ticketing·FareRule | koreanair-overview |
| Lufthansa | LH | NDC (V17.2) | 약 0.6 MB / 87 .kt | ★★ | Search·Booking·Ticketing·FareRule·Ancillary | lufthansa-overview |
| Singapore Airlines | SQ | NDC (EDIST 18.1) | 약 0.5 MB / 88 .kt | ★★ | Search·Booking·Ticketing·FareRule·Ancillary | singaporeair-overview |
| Jeju Air | 7C | LCC/REST | 약 0.5 MB / 99 .kt | ★ | Search·Booking·Ticketing·FareRule | jejuair-overview |
| Group Air | — | 그룹/단체 운임 | 약 0.2 MB / 34 .kt (최소) | ★ | Search·Booking·Ticketing·FareRule | groupair-overview |
골격은 가장 작은 모듈부터
supplier/groupair(34 .kt, 최소)는 컨트롤러 4개·서비스·단일 클라이언트로 골격이 가장 얕다. 패턴 학습의 출발점으로 적합하다. 반대로supplier/amadeus(최대, 그중 794개가infrastructure/SOAP 스키마 DTO)는 stateful 세션·결제·환불이 집중된 최종 보스다. → caller-callee-map
횡단(Cross-cutting) / 아키텍처 노트 맵
| 영역 | 핵심 위치 | 노트 |
|---|---|---|
| 레이어/패키지 골격 | com/triple/air/intl/adapter/{interfaces,application,infrastructure,domain,support} | system-architecture |
| 요청 생애주기 | support/filter/*Filter.kt, configuration/WebMvcConfig | request-flow |
| 콜그래프/영향도 | 생성자 주입 전반 | caller-callee-map |
| 공통 오퍼레이션 흐름 | interfaces/request, interfaces/response | common-operations |
| 공통 계약 DTO | interfaces/request, interfaces/response/*View.kt | interfaces-dtos |
| 횡단 인프라 | support/{cache,crypto,filter,util,web,exception} | support-common |
| 에러 정규화 | support/exception/{ApiException,ErrorMessage,RestExceptionHandler}.kt | error-handling |
| 비동기 | support/util/CoroutineExtensions.kt, supplier/sabre/application/SabrePassengerService.kt | async-coroutines |
| 장애 격리/경보 | application/SlackService.kt, @CircuitBreaker/@Retryable | resilience-and-events |
| 인프라/설정 | configuration/*, application*.yml, AWS Secrets | configuration-and-infra |
| 빌드/배포 | build.gradle.kts, Dockerfile, .github/workflows/* | build-deploy-config |
3. API 서피스 — 공급사 × 오퍼레이션 매트릭스
진입점 =
supplier/{name}/interfaces/controller/internals/{Name}{Op}Controller.kt모든 경로는
/internals/{SUPPLIER}/{resource}패턴. 중앙 디스패처 없이 호출자가 이 URL을 직접 친다. ✅=전용 컨트롤러 존재, ◇=Booking 컨트롤러에 흡수(별도 컨트롤러 없음), —=미지원.
| 공급사 | search | bookings | ticketing | fare-rules | queues | cash-receipts | ancillaries | agency-credit | Cancel(=bookings) |
|---|---|---|---|---|---|---|---|---|---|
| AMADEUS | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | ◇ |
| SABRE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | ◇ |
| GALILEO | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | ◇ |
| AMADEUSNDC | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | — | ◇ |
| TWAY | ✅ | ✅ | ✅ | ✅ | — | — | ✅ | ✅ | ◇ |
| JINAIR | ✅ | ✅ | ✅ | ✅ | — | — | ✅ | ✅ | ◇ |
| KOREANAIR | ✅ | ✅ | ✅ | ✅ | — | — | — | — | ◇ |
| LUFTHANSA | ✅ | ✅ | ✅ | ✅ | — | — | ✅ | — | ◇ |
| SINGAPOREAIR | ✅ | ✅ | ✅ | ✅ | — | — | ✅ | — | ◇ |
| JEJUAIR | ✅ | ✅ | ✅ | ✅ | — | — | — | — | ◇ |
| GROUPAIR | ✅ | ✅ | ✅ | ✅ | — | — | — | — | ◇ |
매트릭스에서 읽어야 할 3가지
- 공통 핵심 5종:
search·bookings·ticketing·fare-rules+Cancel은 11개 전부 지원. 이것만 이해하면 어느 공급사든 골격이 잡힌다. → common-operations- Cancel/repricing/retrieve는 별도 컨트롤러가 아니다.
{Name}BookingController안의 메서드다. 예:AmadeusBookingController.cancel(/{pnr}),.expectedCancel(/{pnr}/expected-cancel),.cancelable(/{pnr}/cancelable),.repricing(/{pnr}/repricing),.retrieve(/{pnr})(파일 라인 60·79·93·130·109).- 전유물 패턴: Queue/CashReceipt = GDS 전유물(amadeus/sabre/galileo, amadeusndc는 Queue만). Ancillary/AgencyCredit = LCC 중심(Ancillary는 NDC lufthansa/singaporeair도). → interfaces-dtos
같은 URL, 다른 의미
/{pnr}/repricing이나 retrieve가 같은 경로여도 동작은 공급사마다 다르다. GDS는pnr만으로 조회, NDC(koreanair)는supplierIdentificationKey가 필수다. repricing이 retrieve와 합쳐진 공급사와 별도 호출인 공급사가 섞여 있다. 자세한 함정은 landmines.
4. Getting Started (빌드/실행/테스트)
로컬 셋업 5단계 (검증:
build.gradle.kts,Dockerfile,application.yml)# 1) JDK 21 (Amazon Corretto) 설치 — Dockerfile:1 amazoncorretto:21 기준 # 2) 레포 클론 # 3) AWS(dev) 자격증명 준비 — local 프로파일도 dev Secrets/ElastiCache를 공유함 ./gradlew build # 4) 빌드 (Gradle 8.11 Wrapper) ./gradlew localBootRun # 5) 실행 → 내부적으로 --spring.profiles.active=local,my # 기동 후: http://localhost:8000/swagger-ui (port 8000, application.yml:6)
| 항목 | 값 | 근거 |
|---|---|---|
| 빌드 도구 | Gradle 8.11 Wrapper | gradlew |
| 언어/런타임 | Kotlin 2.0 + Java 21(Corretto), -Xjsr305=strict | build.gradle.kts:16,21,107 |
| 프레임워크 | Spring Boot 3.3.0 | build.gradle.kts:14 |
| 산출물 | 단일 jar air-intl-adapter.jar (11개 공급사 한 프로세스, 개별배포 불가) | settings.gradle.kts:1, Dockerfile:30 |
| 로컬 실행 | ./gradlew localBootRun (local,my 프로파일) | build.gradle.kts:117-124 |
| 포트/문서 | :8000 / /swagger-ui (dev/qa/local만 ON) | application.yml:6, application-local.yml:27 |
my 프로파일 | *-my.* gitignore된 개인 오버라이드 — 없어도 정상 기동 | .gitignore |
| 테스트 | CI는 테스트 제외 빌드만 수행 → 로컬에서 직접 실행 필요 | ci.yml:34, Dockerfile:12 (--exclude-task test) |
CI가 테스트를 안 돌린다
PR 빌드(
ci.yml)와 Docker 빌드(Dockerfile:12) 모두--exclude-task test로 테스트를 건너뛴다. 즉 테스트는 개발자가 로컬에서 직접 돌려야 회귀를 잡는다. 빌드/배포 상세는 build-deploy-config, 빠른 명령 모음은 quick-reference.
5. 태그 인덱스 (규칙)
모든 노트는 H1 다음 줄에 태그를 단다. 태그로 동일 관심사를 가로질러 탐색한다.
| 태그 패턴 | 의미 | 예시 |
|---|---|---|
#module-<name> | 공급사/영역 식별 | #module-amadeus, #module-sabre, #module-dashboard |
#arch-* | 아키텍처 관점 | #arch-overview, #arch-layers, #arch-callgraph |
#pattern-* | 재사용 구현 패턴 | #pattern-stateful-session, #pattern-coroutine, #pattern-circuit-breaker |
#api-* | API 서피스/오퍼레이션 | #api-surface, #api-search, #api-booking |
#config-* | 설정/인프라 | #config-redis, #config-secrets, #config-profile |
#test-* | 테스트/연습/디버깅 | #test-exercises, #test-debugging |
6. 온보딩 경로 (추천 읽기 순서)
"아키텍처 → 흐름 → 횡단 → 공급사 → 연습 → 지뢰" 순으로 좁혀가라.
- 큰 그림 — system-architecture → request-flow → caller-callee-map
- 레이어·요청 생애주기·콜그래프를 머릿속에 박는다
- 공통 계약·흐름 — common-operations → interfaces-dtos
- 5대 오퍼레이션과 공통 DTO(of 오버로드)를 익힌다
- 횡단 인프라 — support-common → error-handling → async-coroutines → resilience-and-events → configuration-and-infra
- enum 코드매핑·예외정규화·코루틴·서킷·Redis/Secrets
- 공급사 깊이파기 — groupair-overview → amadeus-overview
- groupair-overview: 가장 작은 골격으로 시작
- amadeus-overview: 최대·stateful·결제 = 최종 보스
- 이후 담당 공급사 overview/operations/protocol/pitfalls 4종
- 손으로 연습 — exercises-architecture → exercises-suppliers → exercises-debugging
- 함정 학습 — landmines
- 컴파일러가 못 잡는 의미적 변경 위주
(수시 참조) quick-reference · build-deploy-config
신입이 가장 먼저 체감할 함정 3가지 (상세는 landmines)
- JVM 기본 시간대가 UTC로 강제됨 —
AirIntlAdapterApplication.kt:13@PostConstruct fun init() = TimeZone.setDefault(TimeZone.getTimeZone("UTC")). 모든 시간 값은 UTC 기준으로 읽어야 한다(국제선 다중 시간대 함정). 변환은application/CalculateTimezoneService.kt의calculateToUTC(...).- 변경 영향도는 위치로 1차 판정 —
support/·application(루트)·domain/repository에 있으면 전(全) 공급사 의심. 유일한 공유 베이스클래스support/web/ClientSupport(23개 클라이언트 상속)는 blast radius가 전체다.- 시그니처 불변·의미만 바뀌는 변경(캐시 TTL, 타임존 계산)은 컴파일러가 못 잡으니 가장 위험하다.
7. 관련 기존 문서 (외부 분석 자료)
이 어댑터가 호출하는 외부 공급사 API 자체를 더 깊이 본 분석 문서들. 본 온보딩 노트(어댑터 내부 코드)와 상호 보완 관계다.
| 문서 | 내용 |
|---|---|
| amadeus-gds | Amadeus GDS(SOAP/ART) API 정밀 분석 — search/booking/ticketing/pricing/cancel/refund/queue 7종 하위 문서 |
| sabre-gds | Sabre GDS API 정밀 분석 — 동일 7종 하위 문서 |
| galileo-gds | Galileo(Travelport Universal API) 정밀 분석 — 7종 하위 문서 |
| singaporeair-ndc | Singapore Airlines NDC(EDIST) 정밀 분석 — reissue 샘플 포함 7종 |
다음 행동
- 코드를 처음 연다면 → system-architecture
- 특정 공급사 장애 대응 중이라면 → 해당
*-pitfalls+ error-handling + resilience-and-events- 빌드/배포가 막혔다면 → build-deploy-config + configuration-and-infra
- 빠른 URL/용어/명령이 필요하면 → quick-reference