// FlightSearchRequest.kt:7-25data class FlightSearchRequest( val sort: SortType? = null, val filter: FilterCriteria? = null) : PageRequest(page = 1, size = 20)data class FilterCriteria( val byAirline: List<String>? = null, val byStop: List<LayoverFilterType>? = null, val byStopPoint: List<String>? = null, val byExcludeOutboundTimeSlot: TimeSlot? = null, val byExcludeInboundTimeSlot: TimeSlot? = null, val byFlightTimes: List<String?>? = null, val byExcludeCodeShare: Boolean = false, val byCardPromotion: List<String>? = null,)
응답 상태 코드
HTTP Status
PollingStatus
설명
202 Accepted
PENDING
검색 진행 중
200 OK
COMPLETE / NO_DATA
검색 완료
500 Internal Server Error
ERROR
검색 실패 (예외 발생)
2.5 검색 상태 확인
기본 정보
항목
값
HTTP Method
GET
URL Pattern
/flights/{listKey}/status
메서드
getCacheKeyStatus()
소스 위치
FlightSearchController.kt:335-342
응답 코드
200 OK
Response
{ "status": "OK"}
3. Request/Response 구조
3.1 검색 초기화 응답
{ "key": "550e8400-e29b-41d4-a716-446655440000"}
소스: FlightSearchController.kt:297-303
3.2 검색 결과 응답 (FlightSearchPageView)
// FlightSearchView.kt:20-99data class FlightSearchPageView( val contents: List<FlightItemView>, val page: PageInfo, val status: PollingStatus, val filterData: FilterDataView? = null, val sortData: SortDataView? = null, val lowestPrice: Long? = null, val tripType: TripType? = null,)
FlightItemView 구조
// FlightSearchView.kt:102-155data class FlightItemView( val listKey: UUID, val detailKey: String, val avail: Int, val id: String, val tag: FlightTagView?, val adultPrice: Long, val totalPrice: Long, val schedules: List<ScheduleSummaryView>, val badges: List<BadgeView>, val fares: List<FlightFareView>,)
PageInfo 구조
// PageView.kt:10-31data class PageInfo( val currentPage: Int, val pageSize: Int, val totalCount: Int)
3.3 에러 응답 (ErrorView)
// ErrorView.kt:3-27data class ErrorView( val status: Int, val code: String, val title: String?, val message: String?, val messageArguments: List<*>?,)
sequenceDiagram
participant Client
participant Controller as FlightSearchController
participant LocationService
participant UseCase as StandardFlightSearchUseCase
participant FlightSearchService
participant Repository as FlightSearchRepository
Client->>Controller: GET /flights/search/...
Controller->>LocationService: getLocationInfo(iata, type)
LocationService-->>Controller: LocationInfo
Controller->>Controller: SearchInfo 생성
Controller->>Controller: searchInfo.validate()
Controller->>UseCase: init(searchInfo, criteria, useRecommendation)
UseCase->>UseCase: CacheKeyGenerator.getFlightSearchCacheKey()
UseCase->>Repository: savePolling(listKey, PENDING)
UseCase->>UseCase: CoroutineScope(Dispatchers.IO)
Note over UseCase: 비동기 검색 시작
UseCase-->>Controller: listKey (UUID)
Controller-->>Client: {"key": "uuid"}
Note over UseCase,FlightSearchService: 백그라운드에서 검색 진행
UseCase->>FlightSearchService: searchFlights(...)
FlightSearchService-->>UseCase: List<FlightItem>
UseCase->>Repository: savePolling(listKey, COMPLETE)
소스: StandardFlightSearchUseCase.kt:84-101
5.2 검색 결과 조회 플로우
sequenceDiagram
participant Client
participant Controller as FlightSearchController
participant FlightSearchService
participant AirlineService
participant AirportService
Client->>Controller: POST /flights/{listKey}
Controller->>FlightSearchService: getFlightSearch(listKey)
FlightSearchService-->>Controller: FlightSearch
alt status == PENDING
Controller-->>Client: 202 Accepted (FlightSearchPageView.ofPending)
else status == ERROR
Controller->>Controller: throw InternationalSearchException
else status == COMPLETE/NO_DATA
Controller->>AirlineService: getAirlinesMap(airlineSet)
Controller->>AirportService: getAirportsMap(airportSet)
Controller-->>Client: 200 OK (FlightSearchPageView.ofComplete)
end
소스: FlightSearchController.kt:306-333
5.3 검색 흐름 상세
flowchart TD
A[검색 요청] --> B[LocationService.getLocationInfo]
B --> C[SearchInfo 생성]
C --> D{validate}
D --> |실패| E[MethodArgumentInvalidException]
D --> |성공| F[StandardFlightSearchUseCase.init]
F --> G[UUID 생성 및 PENDING 저장]
G --> H[비동기 검색 시작]
H --> I[FlightSearchService.searchFlights]
I --> J[AirConsoleService.findSearchCondition]
J --> K[AdapterClient.getFareItineraries]
K --> L[스케줄 필터링]
L --> M[PricingClient.getActivePricingPrinciples]
M --> N[FlightItem 생성]
N --> O{useRecommendation?}
O --> |Yes| P[RecommendationService.findScoreMap]
O --> |No| Q[결과 저장]
P --> Q
Q --> R[FlightSearch.complete 저장]
data class SearchInfo( val adult: Int, val child: Int, val infant: Int, val freeBaggageOnly: Boolean, val cabins: Set<CabinType>, val originDestinationLocationInfos: List<OriginDestinationLocationInfo>, val multiTicket: MultiTicket? = null, val useCache: Boolean,)
8.2 OriginDestinationLocationInfo
OriginDestinationLocationInfo.kt:11-30:
data class OriginDestinationLocationInfo( val origin: LocationInfo, val destination: LocationInfo, val date: LocalDate,)
8.3 LocationInfo (Sealed Class)
OriginDestinationLocationInfo.kt:32-93:
sealed class LocationInfo(val type: LocationType) { abstract val iata: String abstract val airportIatas: Set<String> abstract val cityIata: String abstract val countryCode: String abstract val zoneId: ZoneId data class City(...) : LocationInfo(LocationType.CITY) data class Airport(...) : LocationInfo(LocationType.AIRPORT)}
8.4 FlightSearch
FlightSearch.kt:10-80:
data class FlightSearch( val status: PollingStatus, val messageKey: MessageKey? = null, val message: String? = null, val flightItems: List<FlightItem> = emptyList(), val defaultSortType: SortType = SortType.PRICE, val tripType: TripType? = null, val airlineSet: Set<String> = emptySet(), val airportSet: Set<String> = emptySet(), val searchInfoKey: String? = null,)
8.5 FlightItem
FlightItem.kt:21-329:
data class FlightItem( val listKey: UUID, val supplier: String, val scheduleKey: String, val validatingCarrier: String, val schedules: List<Schedule>, val fares: List<FlightFare>, var score: BigDecimal?, var tags: List<RecommendationTag>?, val tripDirectionType: TripDirectionType?, val prepayment: Boolean?, val groupKey: String = "",)
8.6 Schedule
FlightItem.kt:598-676:
data class Schedule( val key: String = "", val flightTime: String, val departure: String, val arrival: String, val departureAt: LocalDateTime, val arrivalAt: LocalDateTime, val stopPoints: List<String>, val addDay: Int, val stop: Int, val avail: Int, val freeBaggage: FreeBaggage?, val segments: List<Segment>,)
8.7 FlightFare
FlightItem.kt:331-480:
data class FlightFare( val id: String, val lookUpKey: String = "", val funnel: Funnel, val avail: Int, val detailKey: String, val passengerFares: List<PassengerFare>, val representative: Boolean? = null, val naverCardType: String? = null, val cardPromotionName: String? = null, val cardPromotionId: Long? = null, val promotionPrincipleId: Long? = null, val tags: List<String> = emptyList(), var lowestAdultTotalPrice: Long? = null, var lowestTotalPrice: Long? = null,)