FlightSearchController DFS (Detailed Functional Specification)

문서 정보

  • 서비스명: air-intl-search (국제 항공 검색 서비스)
  • 컨트롤러: FlightSearchController
  • OpenAPI 출처: openapi.yaml paths /flights/search/**, /flights/{listKey}/**
  • 작성일: 2026-03-04

목차


개요

FlightSearchController는 국제 항공권 검색 기능을 제공하는 REST API 컨트롤러입니다. 다음과 같은 검색 유형을 지원합니다:

  • 편도(One-way): 1개 구간
  • 왕복(Round-trip): 2개 구간 (출발지와 도착지가 동일)
  • 다구간(Multi-city): 2~4개 구간 (자유로운 여정 구성)

검색은 비동기 폴링(Polling) 방식으로 동작하며, 검색 초기화 API로 listKey를 받은 후 결과 조회 API로 검색 결과를 가져옵니다.


API 엔드포인트 목록

1. 검색 초기화 API

검색 유형HTTP MethodURL PatternoperationId
편도GET/flights/search/{originType}:{origin}-{destinationType}:{destination}/{outboundDate}searchOneWayTripFlightsListKey
왕복GET/flights/search/{originType}:{origin}-{destinationType}:{destination}/{outboundDate}/{inboundDate}searchRoundTripFlightsListKey
다구간(2구간)GET.../search/{oT1}:{o1}-{dT1}:{d1}/{date1}/{oT2}:{o2}-{dT2}:{d2}/{date2}searchMultiCity2SegFlightsListKey
다구간(3구간)GET.../search/.../{date1}/.../{date2}/.../{date3}searchMultiCity3SegFlightsListKey
다구간(4구간)GET.../search/.../{date1}/.../{date2}/.../{date3}/.../{date4}searchMultiCity4SegFlightsListKey

2. 검색 결과 / 상태 API

HTTP MethodURL PatternoperationId설명
POST/flights/{listKey}getFlights검색 결과 조회
GET/flights/{listKey}/statusgetCacheKeyStatus검색 키 유효성 확인

상세 스펙

1. 편도 항공편 검색 키 발급

GET /flights/search/{originType}:{origin}-{destinationType}:{destination}/{outboundDate}

Path Parameters

이름타입설명예시
originType출발지 위치 유형AIRPORT
originstring출발지 IATA 코드ICN
destinationType도착지 위치 유형CITY
destinationstring도착지 IATA 코드NRT
outboundDatedate출발일 (ISO 8601)2026-04-01

Query Parameters (공통)

이름타입필수설명
cabinsArray<>O좌석 등급 (복수 선택 가능)
adultint32O성인 인원 수 (≥1)
childint32X소아 인원 수 (기본: 0)
infantint32X유아 인원 수 (기본: 0)
freeBaggageOnlybooleanX무료 수하물 포함 항공편만 (기본: false)
useCachebooleanX캐시 사용 여부 (기본: true)

Response

상태 코드설명응답 스키마
200검색 키 발급 완료{ key: uuid }
400잘못된 요청ErrorView
500서버 내부 오류ErrorView

Response Examples

시나리오: ICN→NRT 왕복, 성인 2 / 소아 1, 이코노미

GET /flights/search/AIRPORT:ICN-AIRPORT:NRT/2026-04-15/2026-04-22?cabins=ECONOMY&adult=2&child=1

성공 응답 (200)
{
  "key": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}
에러 응답 (400)
{
  "status": 400,
  "code": "INVALID_PARAMETER",
  "title": "잘못된 요청",
  "message": "출발일은 오늘 이후여야 합니다.",
  "messageArguments": []
}

2. 왕복 항공편 검색 키 발급

GET /flights/search/{originType}:{origin}-{destinationType}:{destination}/{outboundDate}/{inboundDate}

편도와 동일한 path/query parameters에 inboundDate (귀국일, date)가 추가됩니다.


3-5. 다구간 항공편 검색 키 발급 (2/3/4 구간)

각 구간마다 originTypeN, originN, destinationTypeN, destinationN, dateN 파라미터를 path에 포함합니다. Query parameters는 편도와 동일합니다.


6. 항공편 검색 결과 조회

POST /flights/{listKey}

Parameters

위치이름타입필수설명
pathlistKeyuuidO검색 키

Request Body

FlightSearchRequest

{
  "page": 1,
  "size": 20,
  "sort": "RECOMMENDATION",
  "filter": {
    "byAirline": ["KE", "OZ"],
    "byStop": ["DIRECT"],
    "byExcludeCodeShare": false
  }
}

Responses

상태 코드설명응답 스키마
200검색 완료
202검색 진행 중 (폴링 필요)
400잘못된 요청ErrorView
500서버 내부 오류ErrorView
550검색 실패 (커스텀)ErrorView

Response Examples

시나리오: ICN→NRT 왕복, 성인 2 / 소아 1, 이코노미

POST /flights/f47ac10b-58cc-4372-a567-0e02b2c3d479 Request Body: { "page": 1, "size": 20, "sort": "RECOMMENDATION", "filter": {} }

진행 중 응답 (202 PENDING)
{
  "contents": [],
  "page": {
    "currentPage": 1,
    "pageSize": 20,
    "totalCount": 0
  },
  "status": "PENDING",
  "filterData": null,
  "sortData": null,
  "lowestPrice": null,
  "tripType": "ROUND_TRIP"
}
완료 응답 (200 COMPLETE)

KE 직항 (LOWEST_PRICE 태그, 일반/프로모션 운임 2개) + 7C 경유 1회 (PUS, 프로모션 없음)

{
  "contents": [
    {
      "listKey": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "detailKey": "KE-ICN-NRT-20260415-Y-1",
      "avail": 9,
      "id": "KE-ICN-NRT-20260415-Y-1",
      "tag": {
        "type": "LOWEST_PRICE",
        "title": "최저가"
      },
      "adultPrice": 443900,
      "totalPrice": 1256700,
      "schedules": [
        {
          "carrier": { "code": "KE", "name": "대한항공", "logoUrl": null },
          "carrierText": "대한항공",
          "departure": "ICN",
          "arrival": "NRT",
          "departureDateTime": "2026-04-15T10:00:00",
          "arrivalDateTime": "2026-04-15T12:30:00",
          "stop": 0,
          "totalFlightTime": "PT2H30M",
          "addDay": 0,
          "freeBaggage": { "unit": "개", "allowance": 1 }
        },
        {
          "carrier": { "code": "KE", "name": "대한항공", "logoUrl": null },
          "carrierText": "대한항공",
          "departure": "NRT",
          "arrival": "ICN",
          "departureDateTime": "2026-04-22T14:00:00",
          "arrivalDateTime": "2026-04-22T16:40:00",
          "stop": 0,
          "totalFlightTime": "PT2H40M",
          "addDay": 0,
          "freeBaggage": { "unit": "개", "allowance": 1 }
        }
      ],
      "badges": [],
      "fares": [
        {
          "id": "KE-ICN-NRT-20260415-Y-NORMAL",
          "avail": 9,
          "detailKey": "KE-ICN-NRT-20260415-Y-1",
          "adultPrice": 463900,
          "promotionPrincipleId": null,
          "cardPromotionName": null,
          "tags": [],
          "identityType": "ADULT"
        },
        {
          "id": "KE-ICN-NRT-20260415-Y-PROMO",
          "avail": 9,
          "detailKey": "KE-ICN-NRT-20260415-Y-1",
          "adultPrice": 443900,
          "promotionPrincipleId": 1001,
          "cardPromotionName": "신한카드 할인",
          "tags": ["CARD_PROMOTION"],
          "identityType": "ADULT"
        }
      ]
    },
    {
      "listKey": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "detailKey": "7C-ICN-NRT-20260415-Y-1",
      "avail": 4,
      "id": "7C-ICN-NRT-20260415-Y-1",
      "tag": null,
      "adultPrice": 385200,
      "totalPrice": 1085600,
      "schedules": [
        {
          "carrier": { "code": "7C", "name": "제주항공", "logoUrl": null },
          "carrierText": "제주항공",
          "departure": "ICN",
          "arrival": "NRT",
          "departureDateTime": "2026-04-15T08:00:00",
          "arrivalDateTime": "2026-04-15T12:40:00",
          "stop": 1,
          "totalFlightTime": "PT4H40M",
          "addDay": 0,
          "freeBaggage": null
        },
        {
          "carrier": { "code": "7C", "name": "제주항공", "logoUrl": null },
          "carrierText": "제주항공",
          "departure": "NRT",
          "arrival": "ICN",
          "departureDateTime": "2026-04-22T15:30:00",
          "arrivalDateTime": "2026-04-22T18:10:00",
          "stop": 0,
          "totalFlightTime": "PT2H40M",
          "addDay": 0,
          "freeBaggage": null
        }
      ],
      "badges": [],
      "fares": [
        {
          "id": "7C-ICN-NRT-20260415-Y-NORMAL",
          "avail": 4,
          "detailKey": "7C-ICN-NRT-20260415-Y-1",
          "adultPrice": 385200,
          "promotionPrincipleId": null,
          "cardPromotionName": null,
          "tags": [],
          "identityType": "ADULT"
        }
      ]
    }
  ],
  "page": {
    "currentPage": 1,
    "pageSize": 20,
    "totalCount": 45
  },
  "status": "COMPLETE",
  "filterData": {
    "airlines": {
      "FSC": [
        { "code": "KE", "name": "대한항공", "logoUrl": null },
        { "code": "OZ", "name": "아시아나항공", "logoUrl": null }
      ],
      "LCC": [
        { "code": "7C", "name": "제주항공", "logoUrl": null }
      ]
    },
    "stopPoints": [
      {
        "code": "PUS",
        "name": "부산(김해)",
        "layovers": ["ONE"]
      }
    ],
    "layovers": ["DIRECT", "ONE"],
    "outboundFlightTimes": { "min": "PT2H30M", "max": "PT4H40M" },
    "inboundFlightTimes": { "min": "PT2H30M", "max": "PT2H40M" },
    "flightTimes": [
      { "min": "PT2H30M", "max": "PT4H40M" },
      { "min": "PT2H30M", "max": "PT2H40M" }
    ],
    "cardPromotions": [
      { "code": "NORMAL", "name": "일반" },
      { "code": "1001", "name": "신한카드 할인" }
    ]
  },
  "sortData": {
    "options": [
      "RECOMMENDATION",
      "DIRECT",
      "PRICE",
      "FLIGHT_TIME",
      "OUTBOUND_DEPARTURE_TIME",
      "OUTBOUND_ARRIVAL_TIME",
      "INBOUND_DEPARTURE_TIME",
      "INBOUND_ARRIVAL_TIME"
    ],
    "defaultSort": "RECOMMENDATION"
  },
  "lowestPrice": 385200,
  "tripType": "ROUND_TRIP"
}
데이터 없음 응답 (200 NO_DATA)
{
  "contents": [],
  "page": {
    "currentPage": 1,
    "pageSize": 20,
    "totalCount": 0
  },
  "status": "NO_DATA",
  "filterData": null,
  "sortData": null,
  "lowestPrice": null,
  "tripType": "ROUND_TRIP"
}

7. 검색 키 유효성 확인

GET /flights/{listKey}/status
상태 코드설명응답
200캐시 키 유효{ status: "OK" }
404리소스 없음ErrorView
500서버 내부 오류ErrorView

Response Examples

시나리오: 검색 키 유효성 확인

GET /flights/f47ac10b-58cc-4372-a567-0e02b2c3d479/status

성공 응답 (200)
{
  "status": "OK"
}
에러 응답 (404)
{
  "status": 404,
  "code": "NOT_FOUND",
  "title": "리소스 없음",
  "message": "검색 키가 존재하지 않거나 만료되었습니다.",
  "messageArguments": []
}

비동기 폴링 플로우

Client                              Server
  │                                    │
  ├─ GET /flights/search/...  ────────►│  검색 키 발급
  │◄── 200 { key: uuid }  ────────────┤
  │                                    │
  ├─ POST /flights/{listKey} ─────────►│  결과 조회 (1차)
  │◄── 202 { status: PENDING, ... } ──┤  진행 중
  │                                    │
  ├─ POST /flights/{listKey} ─────────►│  결과 조회 (2차)
  │◄── 200 { status: COMPLETE, ... } ─┤  완료
  │                                    │

데이터 모델

FlightSearchRequest

필드타입기본값설명
pageint321페이지 번호
sizeint3220페이지 크기
sort-정렬 기준
filter-필터 조건

FilterCriteria

필드타입설명
byAirlineArray<string>항공사 코드 필터
byStopArray<>경유 횟수 필터
byStopPointArray<string>경유지 코드 필터
byExcludeOutboundTimeSlot가는편 제외 시간대
byExcludeInboundTimeSlot오는편 제외 시간대
byOutboundFlightTimestring가는편 최대 비행시간 (deprecated)
byInboundFlightTimestring오는편 최대 비행시간 (deprecated)
byFlightTimesArray<string>구간별 최대 비행시간 목록
byExcludeCodeShareboolean공동운항 제외 (기본: false)
byCardPromotionArray<string>카드 프로모션 필터

FlightSearchPageView

필드타입필수설명
contentsArray<>O검색 결과 목록
pageO페이지 정보
statusO폴링 상태
filterDataX필터 메타데이터
sortDataX정렬 메타데이터
lowestPriceint64X필터 적용 후 최저가
tripTypeX여정 유형

FlightItemView

필드타입필수설명
listKeyuuidO검색 리스트 키
detailKeystringO상세 키 (deprecated)
availint32O잔여 좌석 수 (deprecated)
idstringO항공편 ID (deprecated)
tagX추천 태그
adultPriceint64O성인 1인 최저가
totalPriceint64O전체 합계 가격
schedulesArray<>O구간별 스케줄 요약
badgesArray<>O뱃지 목록 (기본: [])
faresArray<>O운임 옵션 목록

FlightTagView

필드타입필수설명
typeO태그 유형
titlestringO태그 표시 텍스트

FlightFareView

필드타입필수설명
idstringO운임 ID
availint32O잔여 좌석 수
detailKeystringO상세 키
adultPriceint64O성인 1인 가격
promotionPrincipleIdint64X프로모션 정책 ID
cardPromotionNamestringX카드 프로모션명
tagsArray<string>O태그 목록
identityTypeO신분 유형

ScheduleSummaryView

필드타입필수설명
carrierAirlineViewO대표 항공사
carrierTextstringO항공사 텍스트 (공동운항 표시 포함)
departurestringO출발 공항 IATA 코드
arrivalstringO도착 공항 IATA 코드
departureDateTimedate-timeO출발 일시
arrivalDateTimedate-timeO도착 일시
stopint32O경유 횟수
totalFlightTimestringO총 비행시간 (ISO 8601 duration)
addDayint32O도착일 차이
freeBaggageFreeBaggageViewX무료 수하물

BadgeView

필드타입필수설명
descriptionstringO뱃지 설명
colorstringOHEX 색상 코드 (예: 4154FF)

FilterDataView

필드타입필수설명
airlinesMap<CarrierType, Array<AirlineView>>O항공사 유형별 목록
stopPointsArray<>X경유지 목록
layoversArray<>O경유 필터 옵션
outboundFlightTimesO가는편 비행시간 범위 (deprecated)
inboundFlightTimesX오는편 비행시간 범위 (deprecated)
flightTimesArray<>O구간별 비행시간 범위
cardPromotionsArray<>X카드 프로모션

SortDataView

필드타입필수설명
optionsArray<>O정렬 옵션 목록
defaultSortO기본 정렬

DurationRangeView

필드타입필수설명
minstringO최소 비행시간 (ISO 8601 duration)
maxstringO최대 비행시간 (ISO 8601 duration)

CardPromotionFilterView

필드타입필수설명
codestringO프로모션 코드 (숫자 ID 또는 ‘NORMAL’)
namestringO프로모션 명칭

StopPointView

필드타입필수설명
codestringO경유지 공항 IATA 코드
namestringO경유지 표시명
layoversArray<>O경유 필터 (unique)

PageInfo

필드타입필수설명
currentPageint32O현재 페이지
pageSizeint32O페이지 크기
totalCountint32O전체 건수

Enums (참조)

Enum설명
LocationTypeCITY, AIRPORT위치 유형 (CITY=c, AIRPORT=a)
CabinTypeECONOMY, PREMIUM_ECONOMY, BUSINESS, FIRST좌석 등급
SortTypeRECOMMENDATION, DIRECT, PRICE, FLIGHT_TIME, OUTBOUND_DEPARTURE_TIME, OUTBOUND_ARRIVAL_TIME, INBOUND_DEPARTURE_TIME, INBOUND_ARRIVAL_TIME정렬 기준
LayoverFilterTypeDIRECT, ONE, MORE_THAN_TWO경유 필터
TagTypeLOWEST_PRICE, SHORTEST_DISTANCE, POPULAR_DEPARTURE_TIME추천 태그 유형
IdentityTypeADULT, CHILD, INFANT, LABOR, VIETNAM_LABOR, STUDENT, DISABLED, INCLUSIVE_TOUR신분 유형
TimeSlotMORNING (06-12), AFTER_NOON (12-18), NIGHT (18-00), DAWN (00-06)시간대
PollingStatusPENDING, ERROR, COMPLETE, NO_DATA폴링 상태
TripTypeONE_WAY, ROUND_TRIP, MULTI_CITY여정 유형
CarrierTypeFSC, LCC, NONE항공사 유형