Dida 외부 API 연동 정리
Dida 외부 API 연동 정리
Dida(디다) 외부 API를 연동하는 프로젝트의 API 목록 및 처리 프로세스를 정리한다.
프로젝트 구조 개요
- 언어/프레임워크: Java / Spring Boot
- HTTP 클라이언트: RestTemplate(Static), WebClient(Realtime)
- 인증: ClientID + LicenseKey (
Header에 포함, 설정 파일에서 관리) - Base URL 설정:
channel.dida.webClient.baseUrl(application properties)
모든 Dida API 요청은 RequestUtils를 통해 공통 헤더(ClientID, LicenseKey)를 포함한 요청 Map을 구성해서 전송한다.
API 분류
전체 API는 크게 두 가지로 분류된다.
- Static Data API (
/api/static): 주기적(주 1회 등)으로 Dida 기준 데이터를 가져와 DB에 저장하는 배치성 API - RealTime API (
/api/realtime): 호텔 검색, 예약, 취소 등 실시간 처리 API
1. Static Data API
컨트롤러: StaticDataController (/api/static)
1-1. 국가코드 업데이트
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/static/country-update |
| Dida API | channel.dida.Api.CountryList |
| 처리 요약 | Dida에서 전체 국가 목록 조회 후 DB(dida_country) upsert |
프로세스
- Dida
CountryListAPI 호출 (파라미터 없음) - 응답 JSON에서
Countries배열 파싱 →List<CountryDto>변환 staticDataDao.updateCountryCode()로 DB 일괄 업데이트
1-2. 도시코드 업데이트
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/static/city-update |
| Dida API | channel.dida.Api.CityList |
| 처리 요약 | Dida에서 전체 도시 목록 조회 후 10,000건씩 분할 DB 저장 |
프로세스
- 요청 파라미터:
IncludeSubCity: true - 응답 JSON에서
Cities배열 파싱 →List<CityDto>변환 - 전체 목록을 10,000건 단위로 분할하여 반복
staticDataDao.updateCityCode()호출- 데이터 규모가 크기 때문에 페이징 처리
1-3. 침대타입 업데이트
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/static/bedtype-update |
| Dida API | channel.dida.Api.BedTypeList |
| 처리 요약 | Dida 침대타입 코드 목록 조회 후 DB 저장 |
프로세스
- Dida
BedTypeListAPI 호출 (파라미터 없음) - 응답 JSON에서
BedTypes배열 파싱 →List<BedTypeDto>변환 staticDataDao.updateBedTypeList()로 DB 업데이트
1-4. 숙소카테고리 업데이트
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/static/property-category-update |
| Dida API | channel.dida.Api.PropertyCategoryList |
| 처리 요약 | 숙소 유형(호텔/리조트 등) 코드 목록 조회 후 DB 저장 |
프로세스
- Dida
PropertyCategoryListAPI 호출 (파라미터 없음) - 응답 JSON에서
PropertyCategorys배열 파싱 →List<PropertyCategoryDto>변환 staticDataDao.updatePropertyCategoryList()로 DB 업데이트
1-5. 호텔 Static 정보 업데이트 (주 1회)
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/static/hotel-static-information |
| Dida API | channel.dida.Api.HotelStaticInformation |
| 처리 요약 | 약 수십만 건의 호텔 기본정보(HotelSummary) 신규 데이터만 DB insert |
프로세스
- 요청 파라미터:
IsGetUrlOnly: true,StaticType: "HotelSummary" - Dida로부터 압축(gzip) byte 응답 수신 → JSON 파싱 →
List<PropertyDto>변환 - 1,000건 단위로 분할 후 MyBatis
ExecutorType.BATCH로 고속 insertsqlSessionBatchInsertPropertiesMapper 사용
- 신규 숙소만 insert (upsert 아님)
1-6. 객실타입 업데이트 (주 1회)
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/static/room-type-information |
| Dida API | channel.dida.Api.HotelStaticInformation |
| 처리 요약 | 약 616만 건의 객실타입(RoomType) 신규 데이터만 DB insert |
프로세스
- 요청 파라미터:
IsGetUrlOnly: true,StaticType: "Roomtype" - Dida 응답 파싱 →
List<RoomTypeDto>변환 - 1,000건 단위 분할 +
parallel()병렬 처리로 MyBatis Batch insert- 병렬 처리 적용 후 처리 시간 약 50% 단축 (순차 1,289초 → 병렬 593초)
2. RealTime API
컨트롤러: RealTimeController (/api/realtime)
HTTP 클라이언트: WebClient (비동기 논블로킹)
2-1. 호텔별 최저가 조회
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/realtime/search-property |
| Dida API | channel.dida.webClient.PriceSearchList |
| 처리 요약 | 자사 호텔코드 리스트로 각 호텔의 최저가 조회 |
프로세스
- 요청으로 받은 자사 호텔코드로 DB에서 Dida 호텔ID 목록 조회
- Dida API 제한(호텔 최대 50개/요청)에 따라 50개 단위로 분할
Flux.parallel()로 분할된 목록을 병렬로 DidaPriceSearchListAPI 호출- 요청 파라미터:
CheckInDate,CheckOutDate,Nationality,Currency: USD,LowestPriceOnly: true,IsRealTime.Value: false(캐시 데이터)
- 요청 파라미터:
- 전체 응답 병합 후 호텔별 최저가(
PropertyLowPriceDto) 리스트 반환 - 에러 응답이 있는 경우 전체 실패 처리
2-2. 호텔상세 객실요금 조회
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/realtime/search-rateplan |
| Dida API | channel.dida.webClient.PriceSearchList |
| 처리 요약 | 숙소 상세 진입 시 투숙정보 기반 객실별 요금 및 RatePlan 조회 |
프로세스
- 자사 상품 ID로 DB에서 Dida 호텔정보 조회
- Dida
PriceSearchListAPI 호출 (단일 호텔,IsRealTime.Value: true— 실시간 조회) - 응답
RatePlanList처리 시:- 중국어 RatePlan 제외 (정규식 한자 필터링)
- 당일
SearchBlock테이블 기준으로 이전에 실패한 RatePlan 제외 InventoryCount >= 요청 객실수조건 필터RoomTypeID가 없는 RatePlan 제외
- 필터 통과한 RatePlan 목록 →
RatePlanDto.SearchRoomRatePlan변환 후 반환
2-3. 사전 예약 (PriceConfirm)
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/realtime/price-confirm |
| Dida API | channel.dida.webClient.PriceConfirm |
| 처리 요약 | 예약 전 최종 요금 확정 및 취소 규정 확인, ReferenceNo 발급 |
프로세스
- DB에서 호텔의 국가코드 조회 후 요청에 세팅
dida_price_confirm_log테이블에 요청 전 로그 insert- Dida
PriceConfirmAPI 호출- 요청 파라미터:
CheckInDate,CheckOutDate,Nationality,Currency,PreBook: true,HotelID,RatePlanID,NumOfRooms,OccupancyDetails
- 요청 파라미터:
- 응답 후
dida_price_confirm_log업데이트 - 에러 응답 시:
SearchBlock테이블에 차단 정보 insert (당일 동일 조건 재검색 방지) - 성공 시: 환율 정보 조회 → USD 가격을 KRW로 환산,
ReferenceNo저장 후 반환
2-4. 객실 예약 생성 (CreateBooking)
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/realtime/create-booking |
| Dida API | channel.dida.webClient.CreateBooking |
| 처리 요약 | PriceConfirm에서 발급받은 ReferenceNo로 실제 예약 생성 |
프로세스
dida_reservation_log테이블에 요청 전 로그 insert- Dida
CreateBookingAPI 호출- 요청 파라미터:
CheckInDate,CheckOutDate,NumOfRooms,ClientReference(자사 예약번호),ReferenceNo,Contact(예약자 정보),GuestList(투숙객 정보) - 투숙객 정보 없을 경우 예약자 정보로 대체
- 전화번호에서
(+82)→0변환 처리
- 요청 파라미터:
- 응답 후
dida_reservation_log업데이트 - 에러 시:
SearchBlockinsert 후 실패 반환 - 성공 시 DB 저장:
dida_reservation(예약 메인 정보)dida_reservation_guest(객실별 투숙객 정보)dida_cancellation(취소 수수료 정책)
dida_price_confirm_log에서 이전 PriceConfirm 응답을 조회하여 객실명, 최대인원 등 추가 정보 보완
2-5. 예약 취소 (CancelBooking)
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/realtime/cancel-booking |
| Dida API | channel.dida.webClient.CancelBooking |
| 처리 요약 | 예약 취소 요청 및 취소 수수료 확인, ConfirmID 발급 (유효시간 10분) |
프로세스
- DB에서 해당 BookingID의 예약 상태(
CONFIRMED) 확인 dida_cancel_booking_log테이블에 요청 전 로그 insert- Dida
CancelBookingAPI 호출 (요청 파라미터:BookingID) - 응답에서
ConfirmID, 취소 수수료(Amount) 추출 - DB의 예약 정보에
cancelConfirmId업데이트 ConfirmID를 반환 (이후cancel-confirm에서 10분 이내 사용 필요)
2-6. 예약 취소 확정 (CancelConfirm)
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/realtime/cancel-confirm |
| Dida API | channel.dida.webClient.CancelConfirm |
| 처리 요약 | CancelBooking에서 받은 ConfirmID로 취소 최종 확정 처리 |
프로세스
- DB에서 BookingID 예약 상태(
CONFIRMED) 확인 dida_cancel_confirm_booking_log테이블에 요청 전 로그 insert- Dida
CancelConfirmAPI 호출 (요청 파라미터:BookingID,ConfirmID) - 성공 시
dida_reservation의booking_status를CANCELED로 업데이트
2-7. 예약 취소 + 취소 확정 통합 (CancelConfirmBooking)
| 항목 | 내용 |
|---|---|
| Endpoint | POST /api/realtime/cancel-confirm-booking |
| 처리 요약 | CancelBooking → CancelConfirm 을 순차적으로 한 번에 처리 (사용 권장) |
프로세스
cancelBooking()서비스 호출- 성공 시 응답의
BookingID,ConfirmID로 즉시cancelConfirm()서비스 호출 - 취소 + 확정을 단일 API 호출로 처리 가능하여 클라이언트 편의성 제공
2-8. 예약 조회 (SearchBooking - 자사 예약번호 기준)
| 항목 | 내용 |
|---|---|
| Endpoint | GET /api/realtime/search-booking/{internalBookingId} |
| Dida API | channel.dida.webClient.SearchBooking |
| 처리 요약 | 자사 예약번호로 DB에서 Dida BookingID 조회 후 예약 상세 반환 |
프로세스
- DB에서 자사 예약번호(
internalBookingId)로 DidaBookingID조회 - Dida
SearchBookingAPI 호출 (SearchBy.BookingID파라미터) - 응답
BookingDetailsList[0]파싱:- 예약 상태, 체크인/아웃일, 객실수, 투숙객 목록, 호텔 정보, RatePlan, 취소 정책 등 매핑
- 날짜 포맷 변환:
yyyy-MM-dd HH:mm:ss→yyyy-MM-dd
2-9. 예약 조회 (SearchBooking - Dida BookingID 기준)
| 항목 | 내용 |
|---|---|
| Endpoint | GET /api/realtime/search-booking-didaID/{bookingId} |
| Dida API | channel.dida.webClient.SearchBooking |
| 처리 요약 | Dida BookingID를 직접 입력받아 예약 상세 조회 |
2-8과 동일하나 DB 조회 없이 입력받은 ID를 Dida BookingID로 직접 사용
3. API 목록 요약
Static Data API (/api/static)
| # | Endpoint | Dida API | 설명 | 주기 |
|---|---|---|---|---|
| 1 | POST /country-update |
CountryList | 국가코드 업데이트 | 수시 |
| 2 | POST /city-update |
CityList | 도시코드 업데이트 | 수시 |
| 3 | POST /bedtype-update |
BedTypeList | 침대타입 업데이트 | 수시 |
| 4 | POST /property-category-update |
PropertyCategoryList | 숙소유형 업데이트 | 수시 |
| 5 | POST /hotel-static-information |
HotelStaticInformation (HotelSummary) | 호텔 기본정보 업데이트 | 주 1회 |
| 6 | POST /room-type-information |
HotelStaticInformation (Roomtype) | 객실타입 업데이트 | 주 1회 |
RealTime API (/api/realtime)
| # | Endpoint | Dida API | 설명 |
|---|---|---|---|
| 1 | POST /search-property |
PriceSearchList | 호텔별 최저가 조회 |
| 2 | POST /search-rateplan |
PriceSearchList | 호텔상세 객실요금/RatePlan 조회 |
| 3 | POST /price-confirm |
PriceConfirm | 사전예약 (요금확정, ReferenceNo 발급) |
| 4 | POST /create-booking |
CreateBooking | 객실 예약 생성 |
| 5 | POST /cancel-booking |
CancelBooking | 예약취소 (수수료 확인, ConfirmID 발급) |
| 6 | POST /cancel-confirm |
CancelConfirm | 예약취소 확정 |
| 7 | POST /cancel-confirm-booking |
CancelBooking + CancelConfirm | 취소+확정 통합 처리 (권장) |
| 8 | GET /search-booking/{id} |
SearchBooking | 예약조회 (자사 예약번호) |
| 9 | GET /search-booking-didaID/{id} |
SearchBooking | 예약조회 (Dida BookingID) |
4. 주요 특이사항
SearchBlock (차단 목록)
PriceConfirm 또는 CreateBooking 실패 시 동일 날짜/호텔/RatePlan 조합을 dida_search_block 테이블에 기록한다. 이후 당일 RatePlan 검색 시 해당 항목을 결과에서 제외하여 불필요한 실패 반복을 방지한다.
병렬 처리
최저가 조회(search-property)는 Dida 호텔 50개 제한으로 분할 후 Flux.parallel()로 동시 호출하고, RoomType 배치 저장도 IntStream.parallel()로 병렬 insert한다.
환율 적용
Dida API는 USD로 응답하므로, PriceConfirm 이후 DB의 환율 정보(dida_ex_rate)를 조회해 KRW 환산 금액을 함께 반환한다.
인증
모든 요청의 Body에 Header: { ClientID, LicenseKey } 포함 (RequestUtils.getNotHttpEntity() / getHttpEntity()). 인증 값은 설정 파일에서 관리한다.