Repository navigation
Releases: yakisoba0728/korail-mobile-api
Release list
v4.0.0 — 조회 전용 API로 기능 축소
4.0.0 — 조회 전용 API로 기능 축소
한국철도공사(코레일) 측의 소스코드 삭제 또는 저장소 비공개 요청에 대응하여 기존 기능을 로그인 없는 조회 14개로 축소했습니다. 3.x와 호환되지 않습니다.
유지한 기능
- 운행 스케줄, 좌석배정용 열차 목록, 전체 역·판본·운행일·환승역·자유석 안내
- 서비스 상태·앱 캐시·공통 코드·단말 검증값·승무원 호출 사유
- 일반 부가서비스 메뉴와 지원 역 조회
제거한 기능
로그인·세션·DynaPath·NetFunnel, 일반 직통·환승 검색과 운임, 예약·발권·결제·환불, 계정·승차권·패스·체크인·공항버스 운행·좌석 조회와 관련 구현·모델·예제·의존성을 제거했습니다.
메인의 문서 디자인은 유지하고 API와 예제를 조회 전용 범위에 맞췄습니다. 지원 경로 제한, 쿠키 미전송, 자동 재시도·리다이렉트 없음, 오류와 원문 보존을 검사합니다.
설치와 문서
python -m pip install --upgrade korail-mobile-api버전 고정: korail-mobile-api==4.0.0
검증 범위
오프라인 테스트 142개, 분기 커버리지 96.93%. GitHub CI는 Python 3.11–3.14와 최소 의존성 조합, 설치된 wheel, 문서와 workflow를 검사합니다. 유지 범위의 실서버 관측은 2026-10-25의 3.0.0 무인증 설정이며 4.0.0 자체의 실서버 검증이 아닙니다.
v3.0.0
[3.0.0] - 2026-10-24
2.x와 호환되지 않는 변경을 한 번에 모은 판입니다. 옛 이름의 별칭은 없습니다. 바뀐 이름·인자·import 경로의 전체 표와 고치는 방법은 3.0으로 옮기기에 있습니다.
추가
KorailInvalidInputError: 요청 전 입력 검사의 거절입니다.KorailProtocolError이자ValueError라 기존except도 잡습니다.- 모든 라이브러리 예외의
request_sent: 요청을 전송 계층에 넘긴 뒤 전송·응답 해석에 실패하면True, 요청 전에 거절했으면None입니다. 상태를 바꾸는 메서드에서는 서버가 처리했을 수 있다는 note도 붙습니다. KorailTransportError.status_code: 2xx가 아닌 HTTP 응답의 상태 코드입니다. 네트워크 단계 실패는None입니다.KorailClient의with문 지원: 블록이 끝나면close만 부르고 서버 로그아웃은 하지 않습니다.HoldReference(*, pnr_no, journey_count, journey_sequence=None, change_no=None)와ReservationHoldResponse.reference, PNR·여정 수만 요구하는HoldReference.from_raw(raw).cancel_unpaid_hold가 홀드 대신 받으며 같은 값이면 같은 요청을 보냅니다.- 조회 결과를 옮기는 팩토리:
OriginalTicketReference.from_ticket(원표 반환일을 판매일로 사용),FreeSeatCarRequest.from_train,MergeSeatsInquiryRequest.from_train,AirportBusSeatInventoryQuery.from_schedule. - 간편 API:
korail.tickets.all(page_no, *, mode, boarding_date_from, boarding_date_to),korail.tickets.detail,KorailClient.login과 같은 키워드 옵션을 받는Korail.login. DynapathRequestContext의body(보낼 본문 바이트)와app_version.OriginalTicketReference.from_sale_ticket(ticket): 전체sale_date의 ASCII 8자리를 그대로 복사해 수령자·PBP 조회에 사용합니다. 기존from_ticket은 MMDD 원표 반환일을 계속 사용하며 날짜 역할을 자동 선택하지 않습니다.Korail.logged_in의 네 로그인 옵션 전달,reservations.cancel의HoldReference·check_first=True,reservations.create의seats·seat_attribute_code전달. 기존 기본값·명시적 지정좌석 예약 종류·요청 횟수와 무재시도 정책을 유지합니다.
변경
- 공개 import 경로는 패키지 루트(
korail_mobile_api)뿐입니다. 구현은 내부 패키지_core/와_domains/<도메인>/{models,forms,parsers}.py로 옮겼고,device.py·live.py는config.py에,error_messages.py는errors.py에 합쳤습니다.korail_mobile_api.models·read_payloads·device같은 2.x 하위 모듈은 없습니다. 대기열 로거 이름korail_mobile_api.netfunnel·korail_mobile_api.netfunnel_safety는 그대로입니다. KorailClient메서드 38개의 이름을 바꿨습니다. 목록은list_, 한 건은get_, 읽기 전용 가능 여부 확인은check_로 시작합니다(예:get_reservation_history→list_reservations,get_ticket_list→list_tickets,get_refund_commission→get_refund_fee,get_limousine_schedules→list_airport_bus_schedules). 간편 API는reservations.find→reservations.get,tickets.refund_fee→tickets.refund_quote입니다. API 문서의 옛 메서드 앵커는 새 절로 이어집니다.- 모델 이름: 공개
Limousine*클래스 7개는AirportBus*,TrainSearchQuery.departure_station_code·arrival_station_code는departure_station·arrival_station입니다. 같은 전송 키를 읽는 응답 필드는 한 이름을 써서 응답 모델 25개의 필드 47개 이름이 바뀌었습니다(예:TrainSearchMetadata.product_no→goods_no,TrainScheduleStop.planned_departure_time→departure_time,ProductReservation.payment_deadline→settlement_deadline). - 공개 입력·응답 모델과 설정 dataclass는 모두
frozen=True, kw_only=True라 키워드 인자로만 만듭니다.raw는 선언한 모델의 마지막 필드이며repr()에 나오지 않습니다(비교 제외는 같음).KorailSession.jsessionid, 입력 모델의 반환 비밀번호·이름·전화번호·생년월일·고객번호,DynapathTokenSettings.device_id,KorailConfig.advertising_id도repr()에서 숨깁니다. - 2.x에서 pickle한 응답·입력 모델,
KorailConfig(안의DynapathConfig포함),KorailDeviceProfile은 읽을 수 없습니다. 예외 pickle은 생성자를 거치지 않는 형식으로 바뀌었고 2.x가 만든 pickle도 읽습니다. - 요청 전 입력 거절은
KorailInvalidInputError입니다. 입력 모델·폼 검사, 로그인 입력,refund의 수수료 응답 검사, 간편 API가 직접 내던ValueError가 해당합니다. 없는 키워드 등 Python 호출 시그니처 위반은 계속TypeError입니다. - 만들 때 거절하는 입력 모델:
PassScheduleRequest(None·비문자열 필드),CardPayment(카드 형식,card_type은str),PaidTicket(필수 식별자 다섯),FreeSeatCarRequest·MergeSeatsInquiryRequest(열차 식별값),AirportBusScheduleQuery·AirportBusSeatInventoryQuery(필수 식별값),PriceFareQuoteRequest(goods_no일관성). 올바른 입력의 요청 바이트는 같습니다. - 요청 전 검사 추가:
get_train_schedule·list_seat_cars·get_seat_inventory는 비었거나None인 열차 번호·운행일·역 코드·운행 순서를,list_tickets의boarding_date_from·boarding_date_to는 빈 문자열이나 ASCII 숫자 8자리가 아닌 값을 거절합니다. - DynaPath 헤더는
DynapathConfig.allowlist_paths만으로 정합니다. 기본 목록에서 요청 바이트는 같습니다. - 잘못된 동적 입력의 조기 거절: 검색 query·환승역 Sequence·실제 bool 옵션, 취소
check_firstbool, 병합 중간역 ASCII 숫자 문자열, 환불 열차번호·좌표 문자열, MaaS 반환번호 Sequence, 버스 상품번호 문자열을 검사합니다. 정상 목록의 순서·중복, 빈 선택값 생략, 저수준 인원 범위 정책은 유지합니다. 환불 숫자 좌표의 문서 밖 자동 문자열화는 제거했습니다. - DynaPath header 이름은 nonempty ASCII HTTP field-name token, 공급자 토큰은 CTL 없는 ASCII 문자열 또는 None이어야 합니다. None 생략·빈 header·printable ASCII는 유지합니다. v1 필수값의 실제 문자열과 env 기기값·양수 크기도 기존 profile 의미에 맞춰 검사하며 Unicode 사실값·custom UA의 build ID 생략을 유지합니다.
- 필수 모델 생성자 인자 누락을 mypy·Pyright도 거절하도록 표준 dataclass metadata로 표현합니다. runtime 생성자·기본값·필드 순서·pickle 경로는 유지합니다.
TransferItinerary.legs는 두 원소 튜플, commuter factory는Sequence[int]를 받아 튜플로 보관합니다.timeout의 기존 None 허용도 annotation에 반영합니다.
제거
get_notice:get_app_data().notice를 쓰세요. 공지가 없으면None이며 요청은 같습니다.register_discount_card와DiscountCardPurchaseRequest·DiscountCardSectionRequest·DiscountCardAdditionalUser·DiscountCardPurchaseResponse. 실서버에서 확인하지 못했고 라이브러리로 결제·취소할 수 없는 구매만 만들었습니다.DiscountCardTicket:extend_discount_card는 같은 네 값을OriginalTicketReference로 받고 같은 요청을 보냅니다.reserve_merge(job_type=)(항상MERGE_STANDING),recalculate_price(add_to_cart=)와 2.6.2의ReservationHoldResponse.cart_addition·cart_addition_error(재계산 뒤add_to_cart를 따로 호출),search_trains_with_transfer_fallback(continuation=).- 항상
None이던DiscountCardScheduleResponse.following_page_exists, 쓰이지 않던CartItem.usage_window. 공개 메서드는 85개에서 83개입니다. - 미지원 호출 기록
_maas_unsupported·_social_login_unsupported·_travel_search_unsupported와 그 호출만 쓰던 빌더·파서·모델은tests/records/로 옮겨 wheel에 넣지 않습니다. sdist에는 테스트와 함께 들어갑니다.
수정
- 페이지·쪽 크기의 거대 정수 문자열 변환 실패를 원래
ValueErrorcause가 있는 요청 전KorailInvalidInputError로 처리합니다. 값 노출·전역 한도 변경·새 페이지 범위 제한은 없습니다.PaidTicket.from_refund_detail·StationRefundExecutionRequest.from_verification도 잘못된 응답 모델을 bareAttributeError대신 같은 입력 오류로 거절합니다. - 문서의 미전송 판정을
raw=None대신 입력 거절 유형과request_sent로 구분하고, 재계산한 최신 홀드를 선택 장바구니 호출 전에 보존합니다. 실제 문서 블록을 합성 실패 응답으로 실행하는 회귀를 추가했습니다. - 일부 여정만 정산 좌석이 있거나 선언 여정 수와 행 수가 모순된 홀드는 부분합 대신
received_amount=None입니다. raw·PNR·취소 참조와 total-only/all-no-settlement 유효 총액 fallback을 보존하며 자동 재조회하지 않습니다. 완전한 좌석 합과 명시 총액의 모순은 계속 오류입니다. - 수신 후 도메인 파싱 실패의 sent/raw/cause 표시와 JSON decoder ValueError·RecursionError cause를 보존합니다. 순수 파서·요청 전 거절은 network-neutral이며 queue 반납 시점·상태 우선순위·변경 무재전송은 유지합니다. 공급자는 준비된 실제 URL·본문을 한 번 읽고 closed/invalid URL에서는 호출되지 않습니다.
- 로그인 중단 시 정리와 login/logout/세션 만료의 원예외 보존을 보완합니다. JSESSIONID는 대표 ticket-list URL에 적용되는 nonempty 값을 요구하고 정상 다중 Path를 허용합니다. 추가 요청이나 모든 API·원격 인증 보장은 없습니다.
- 직접 입력의 문자열 아닌 객체 키를 즉시 검사하되 중첩 raw는 재귀 검사하지 않습니다. 상속
from_raw는 envelope-only이며 필수 도메인 인자가 부족하면 원래 TypeError를 cause로 가진 ProtocolError입니다.ProductDetailResponse.detail_raw·DynapathRequestContext.body는 repr에서만 숨깁니다. - 오류 표시의 미완결 비교식·블록 시작 경계를 보존하고 build-time 메시지 입력의 중복 키를 거절합니다. catalog literal은 바꾸지 않았으며 표시 텍스트는 HTML sanitizer 결과가 아닙니다.
- CI가 설치 검증한 동일 배포 파일을 수동 게시 workflow에 전달하고 별도 재빌드를 제거합니다. normalized wire pin의 재생성 진입점을 없애고 독립 literal byte 회귀와 Griffe docs-job 회귀를 추가합니다. mypy 선언 하한을 설정 오류 코드를 지원하는 1.18.1로 맞춥니다.
-8204안내를 기존 FAIL 모델 반환 정책과 구분하고 개발 버전 설치·공항버스 검증·MaaS 인증·판매일 식별자 설명을 바로잡습니다. 생성 문서의next_page()와 코드 들여쓰기를 보존하고 SVG 예제·예약 전략 레퍼런스를 보완합니다. 런타임 오류 정책과 날짜별 기록은 바꾸지 않습니다.cancel_unpaid_hold는 검사한 여정 수를 그대로 보냅니다. 이전에는" 1"을 공백째 보냈습니다.get_common_codes는bytes와 문자열이 아닌 항목을 거절합니다. 이전에는 바이트마다code로 보냈습니다.list_tickets는date객체 같은 값을 거절합니다. 이전에는2026-07-01형태로 보냈습니다.get_ticket_receipt의 빈txt_index는 조용히 빼지 않고get_refund_ticket_detail과 같은 규칙·메시지로 거절합니다.- 문자열이 아닌 출발·도착역, 카드 결제의 홀드가 아닌 값, 환불 수수료 금액의 정수가
AttributeError·TypeError대신 요청 전KorailInvalidInputError입니다. - 공항버스 예약은 9자리를 넘는 잔여석 수를 알 수 없는 값으로 봅니다. 이전에는 매우 긴 숫자에서
ValueError가 났습니다.
안전·검증 한계
- 합성 응답·소켓 차단 환경의 검사와 별도로, 2026-10-23 23:34:34 KST에
3.0.0.dev0개발 wheel의 기본 요청 버전으로 익명 서울→부산 직통 첫 페이지 조회 1회가SUCC/IRG000000, 열차 10개를 반환했습니다(입력·커밋·관측 한계). 한 노선·날짜·시각의 관측일 뿐 출시된 3.0.0의 호환 보증이 아니며, 3.0의 로그인·인증 조회·예약·취소·결제·환불은 실서버 미검증입니다. - 이름과 인자만 바뀐 메서드는 같은 입력에서 2.6.1 캡처의 정규화된 URL·본문 필드·헤더·순서·횟수와 비교합니다(
tests/test_wire_equivalence.py). 이는 SDK 캡처와의 비교이며 모든 인코딩 변형의 바이트 동일성이나 앱·서버 수용의 증거는 아닙니다. 요청 전에 새로 거절하는 입력과 위 수정 항목은 예외입니다. - 기본 요청 버전(
AppVersion=7.0.8·APIVersion=250601003)은 그대로입니다. 2026-10-21부터 보고된-8204(GitHub #32)에 대해 2026-10-23 배포된 2.6.2의 기본 설정으로 로그인 없는 열차 조회가 성공한 기록과 범위는 실서버 확인 현황에 있습니다. repr()에서 숨기는 것은 출력뿐입니다. 속성 값,raw,dataclasses.asdict(), pickle은 가리지 않습니다.request_sent가True인 상태 변경 실패는 서버에서 처리됐을 수 있습니다. 라이브러리는 다시 보내지 않으며, 호출자가 상태를 확인한 뒤에 정해야 합니다.
v2.6.2 — 결제 안전·개인정보 보호와 -8204 대응
- GitHub #32: 2026-10-21부터 기본 요청 버전(AppVersion 7.0.8·Version 250601003)에
-8204("최신 버전으로 업데이트") 응답이 보고됐습니다.-8204를 로그인 포함 모든 경로에서KorailAppUpdateRequiredError로 분류하고 서버 문구를 보존합니다. 앱 리터럴이 아니라 실서버 관측 코드입니다.build_config_from_env()는KORAIL_APP_VERSION·KORAIL_API_VERSION을 읽습니다. 기본 요청 버전은 바꾸지 않았습니다. 기록된 성공은 AppVersion 7.0.10·Version 250722001·2!헤더 조합의 병합 전 작업트리 관측 1건뿐이며, 현재 기본 조합은 실서버에서 확인하지 않았습니다. - 결제 안전:
reserve_merge는job_type=MERGE_STANDING만 받습니다. 다른 값은 입석 플래그를 덮어써 예약대기 홀드가 결제 가능한 결과로 돌아올 수 있었습니다.PriceRecalculationRequest.for_hold()는 예약대기 홀드(payable=False)를 거절합니다.recalculate_price(..., add_to_cart=True)의 장바구니 단계가 라이브러리 예외로 끝나면 이미 반영된 재계산 홀드를 돌려주고 예외를 새 필드ReservationHoldResponse.cart_addition_error에 담습니다. - 개인정보: 네트워크 단계에서 실패한 요청의
KorailTransportError.__cause__.request는 메서드와 쿼리 없는 URL만 남깁니다. 본문(로그인 아이디·변환된 비밀번호·카드 필드), 쿠키, DynaPath 토큰, 쿼리가 오류 수집 도구에 남던 문제를 막습니다. 예외 타입과 identity는 그대로입니다. 모델·raw·asdict·pickle은 여전히 가리지 않습니다. - 요청 전 검사: 값이
None인 요청 필드는 빈 값(key=)으로 보내지 않고KorailProtocolError로 거절합니다. 빈 문자열 생략은 그대로입니다. 비ASCII 숫자, 문자열이 아니거나 ASCII가 아닌 DynaPath 토큰, httpx가 읽지 못하는 대기열 URL, 0·음수·nan인 시간 설정도 요청 전에 거절합니다. 로그인 입력과 열차 검색 승객 수는 서비스 확인·암호 키·역 목록 요청보다 먼저 검사합니다. - DynaPath 차단 판별은 설정의
allowlist_paths를 따릅니다. 간편 API와 클라이언트가 역 목록을 한 번만 받아 함께 씁니다.korail.trains.search(..., continuation=...)는 첫 페이지의depart_after를 요구하고 지난 시각으로 거절하지 않습니다. 검증한 날짜는 다시 포맷하지 않고 그대로 보냅니다. - 기본 DynaPath를 SDK 2.0.1
2!native-unavailable 진단으로 전환합니다. 기본 헤더에 기기값을 합성하지 않고 profile/env로 제공한 값만os·dm·iid에 넣습니다. 명시적 v1 설정·외부 공급자·기존 allowlist·대기열·무재시도 정책은 유지하며 env builder는 v1 전용KORAIL_DYNAPATH_AS_VALUE를 더 이상 읽지 않습니다. 같은 헤더 형식의 실서버 관측은 실행 당시 조건으로 별도 기록합니다. - 테스트: 85개 공개 메서드와 설정 변형이 보내는 요청을 순서까지 v2.6.1 기준으로 고정하고(SDK 캡처, 앱 근거 아님), 순서 의존 테스트·로거 레벨 누수·조용한 skip을 고칩니다. 경고는 실패로 처리하고 CI 액션을 SHA로 고정합니다.
v2.6.1
PriceFareLeg.from_train()으로 조회한 열차의 운임 입력을 만들고,korail.trains.iter_search(..., max_pages=...)로 직통 검색을 선택적으로 이어 읽습니다. 기존 한 페이지 검색·기본 필터는 유지하며, 이어보기는 요청 상한·복합 식별자 중복 제거·진전 없음 중단을 적용합니다.korail.membership.mileage()·coupons()와korail.airport_bus.stops()·search()·seats()를 추가합니다. 기존 조회·파싱·응답 원문을 재사용하고, 정류장 이름·코드의 잘못된 짝이나 필수 편 식별자 누락은 거절합니다. 버스 운행 그룹은 호출자가 명시하며 보호된 기본값을 추측하지 않습니다. 새 간편 흐름은 오프라인 합성 응답으로 검증하며 실서버 성공을 새로 주장하지 않습니다.- 예약 가이드에 검색·예약의 승객 구성을 각각 전달하고 실제 정산액·적용 할인을 확인하는 절차를 보강합니다. 객실 우선 선택 예제에도 같은 승객 구성을 전달하고, 두 예약 예제는 대안임을 명시합니다. 개인정보 출력·원문 보존·대기열·환불 대상 연결·변경 요청 무재전송 정책은 유지합니다.
- CI에 주간 검사, actionlint, 런타임 의존성·비밀·설정의 Trivy 검사와 테스트 보고서 보관을 추가합니다. Dependabot은 Python·문서·Actions 갱신 PR을 만들도록 설정합니다. 설치된 wheel에서도 신규 간편 조회 테스트를 실행하며, 게시·문서 배포는 계속 수동입니다.
v2.6.0 — 환불 안전장치·앱 계약과 에이전트 문서
2.6.0 — 2026-10-19
- README의 버전·설치·검증 범위를 최신화하고 이전 SRT 프로젝트 안내를 짧은 링크로 정리합니다. 에이전트용
AGENTS.md에 코드 지도·작업별 참고 문서·안전 경계·검증 기준을 추가합니다. - 환불 마일리지 비교에서 매우 긴 숫자 문자열이 Python의 정수 변환 한도를 넘으면
ValueError가 나던 문제를 수정합니다. 부호 있는 ASCII int32와 범위 밖·잘못된 값의0처리 정책을 유지하고, 긴 선행 0이 붙은 정상 값은 읽습니다. 전역 변환 한도·응답 원문·수수료 조회 연결·재전송 정책은 바꾸지 않습니다. - 공개 시그니처와 요청 동작을 유지하면서 변경 응답의 원문 보존과 MaaS 요청 생성을 기존 공통 구현으로 정리합니다. 테스트의 중복 전송·준비 코드를 줄이고 18개 기본값 필드의 누락·null·잘못된 타입 검사를 보강합니다. 변경 응답의
raw가 얕은 복사라는 기존 동작을 문서에 명시하며, 설치된 wheel에도 공개 호출·7.0.10 계약·환불 연결 검사를 적용합니다. - 오류 사전만 앱 7.0.10 기준으로 갱신합니다. 일반 결과 코드 10,305개·메시지 17,256개는 같고
WRD000058한국어 안내만 1개월에서 2개월로 바뀝니다. 영어 문구·오류 분류·요청 날짜 제한은 바꾸지 않습니다. - 은행 조회 직접 필드를
Device, Version, Key, AppVersion순서로, 환불·수수료 조회는 공통 필드가 먼저 오도록 정정합니다. 앱 직렬화 근거와의 정합성 수정이며 서버의 순서 민감성·실서버 영향은 미확인입니다. - 환불은
get_refund_commission이 반환한 성공 응답에 비공개로 연결된 조회 대상과 원표 창구번호·반환일·일련번호·비밀번호·동반자 이름·증빙번호가 일치해야 합니다. 직접 생성·직접 파싱한 수수료 응답, 다른 승차권의 응답, 원표 반환일이 없는 입력은 요청 전에 거절하는 fail-closed 동작 변경입니다. 자동 수수료 조회나 재시도는 하지 않습니다. PaidTicket에 키워드 전용return_sale_date: str | None = None,companion_name: str = "",companion_certificate_no: str = ""를 추가하고 세 필드는repr에서 숨깁니다.from_refund_detail()은original_sale_date와 동반자 이름·생년월일을 복사하고 현재sale_date는 따로 보존합니다. 수동 생성 시 원표 반환일을 명시해야 합니다.TicketResource.refund_fee(ticket, *, companion=RefundCompanion())를 지원하며 기존get_refund_commission시그니처는 유지합니다.- 좌석배정 조회의
*2이상 번호 그룹은 앱 DTO의 단일 묶음과 다른 기존 SDK 확장임을 명시하고 기능은 유지합니다. - 관측한 7.0.10 계약의 독립 회귀 검사와 실제 조회 기반 환불 연결 검사를 추가합니다. 공통 폼의
AppVersion="7.0.10"명시·None생략도 검사하며, 보호된 기본값이나 실서버 수용을 증명하는 테스트로 취급하지 않습니다. - 7.0.10 정적 검토 범위를 추가합니다. 공개 메서드 85개 행 검토는 전체 wire 계약·모든 분기·실서버 호환 검증이 아닙니다. 해당 정적 검토 당시의 패키지 버전은
2.5.0이며 그 기록을 보존합니다. 이번 패키지 버전은2.6.0이고 요청 기본AppVersion=7.0.8과 APIVersion은 유지합니다.
v2.5.0 — 간편 조회·예약 옵션과 오류 메시지
2.5.0 — 2026-10-07
간편 조회·예약 옵션과 코레일+ 오류 메시지를 추가하고, 연결 정리·타입·조회 구현을 보강했습니다.
-
로그인·초기화·컨텍스트 종료 중 연결 정리도 실패하면 원래 예외를 유지하고 후속 정리 실패를 예외 note에 남깁니다.
close()는 두 연결의 정리를 모두 시도하고 첫 오류를 전달합니다. -
자율 좌석 변경 객실 코드의 공개 타입을 현재 런타임 정책과 같은
str로 넓혔습니다. 정기권 승객 요청은from_response()로만 생성하며, 공개 팩토리·빌더의 런타임 타입 해석을 보완했습니다. -
읽기 파서와 독립 폼 빌더를 도메인별 내부 모듈로 분리했습니다. 기존 공개 import·함수 시그니처·pickle 경로와 요청 모델 위치는 유지합니다.
-
중복 테스트 전송·정리·네트워크 차단을 통합하고 기존 회귀 검사를 기능별 테스트로 옮겼습니다. 정리의 동시 실패, 소비자 타입 계약, 실제 문서 조회·페이지 이동 검사를 보강하고 문서의 연결 수명·실행 날짜·개발 버전 범위·원문 보존 설명을 수정했습니다.
-
앱 7.0.8의 일반 결과 코드 10,305개·메시지 17,256개를 패키지 사전에 포함하고
get_error_message·resolve_error_message를 추가했습니다. 한국어·영어·일본어·중국어와 번역 누락 시 한국어 보완을 지원합니다. -
예외와 응답 모델에
display_message를 추가했습니다. 읽을 서버 메시지를 우선하고 빈 메시지는 사전으로 보완하며, 원문·기존 예외 문자열을 보존합니다. 표시에 HTML을 실행하지 않고 줄바꿈 태그는 개행으로 바꿉니다. -
복원한 서비스 오류
S000·S003과 메시지상 혼잡S001·S002를 서비스 오류로 분류합니다.KorailRateLimitError(BT019·BT023),KorailProcessingError(WRT900900),KorailAlreadyProcessedError(EZZ000014·EVZ000102), 로그인 문맥의KorailAccountLockedError(WRC000390)를 추가했습니다. 성공 응답·세션 만료 판정과 API 자동 재시도 정책은 유지합니다. -
ERR299943("예약할인이 지원되지 않습니다")을KorailNotEntitledError에서KorailReservationRefusedError로 옮겼습니다. 회원 자격 코드WRC000419·WRC800030의 분류는 유지합니다. -
열차 예약의
teenager > 0을 직통·좌석 지정·예약대기·환승·병합·간편 API에서 대기열과 예약 요청 전에KorailProtocolError로 거절합니다. 검색의 청소년 인원 합산은 유지하며, 청소년드림 상품과 일반 승객 코드를 구분해 안내합니다. -
7.0.8 할인 상수 복호화로 확인된 요청·발권 코드와 N카드 요청 코드
153의 근거 설명을 고쳤습니다. 어린이 단독 예약 폼과 청소년 차단 회귀 테스트, 사용자 제공 2026-10-07 승객별 실측 기록을 추가했습니다. 승객 처리의 초기 수정은 오프라인으로 검증했으며, 출시 전 추가 실서버 검증 범위는 아래 기록에 구분했습니다. -
CardPayment의 모든 입력 필드를repr()·str()에서 숨깁니다. 생성자, 필드 값, 결제 전 검증과 실제 결제 폼은 유지합니다. -
보호 경로의 일반 응답 봉투가 아닌 이용제한 응답에서 문자열
code="-2000"도KorailDynaPathError로 분류합니다. HTTP 상태와 무관하게 원문을 보존하며 자동 재시도하지 않습니다. 기존 정수 차단 코드와 경로 범위는 유지합니다. -
간편 열차 검색에
include_no_seats·include_waiting_list필터를 추가했습니다. 기본값은 전체 결과이며, 필터 전 목록을 보존해 다음 커서와 마지막 출발 시각 계산을 유지합니다. -
TrainSummary에 좌석·예약대기 가용 여부, 실제 날짜를 사용하는 소요 시간과 한 줄 요약을 추가했습니다. -
KorailReserveOption으로 일반실·특실 우선 선택 또는 객실 제한을 지원합니다. 객실은 즉시 예약 전에 선택하고 요청 후 다른 객실 재시도나 자동 예약대기는 하지 않습니다. -
간편 API에 역 이름 집합
stations.names()와 직접 기존 예약 조회reservations.find(pnr)를 추가했습니다. -
출력 개인정보·오류 분류·필터와 페이지 이동·객실 선택 회귀 테스트 및 독립 Android 암호화 기준값 9개를 추가했습니다. 신규 동작의 기본 계약은 오프라인 합성 테스트로 검증했습니다.
-
2026-10-07 출시 전
main을 코레일+ 7.0.8 설정으로 실서버 추가 검증했습니다. 공개·회원 조회, 매진 필터, 날짜 기반 열차 요약과 일반실·특실 우선 임시 예약을 확인했습니다. 성인 1명 일반실·어린이 1명 특실 홀드를 각각 생성해reservations.find()의 식별자·금액 보존을 확인하고 모두 취소했으며, 예약 이력은 전후 0건입니다. HTTP 105건은 모두 200이었고 카드 결제·환불은 실행하지 않았습니다. 예약대기 전용 행과 서버 커서의 실제 후속 조회는 이번 응답에서 관측하지 못했습니다.
v2.4.0 — KORAIL 요청 전용 프록시
2.4.0 — 2026-10-02
KorailConfig.proxy를 추가했습니다. KORAIL API 요청과 대기열 요청을 같은 프록시(http,https,socks5,socks5h)로 보내며 같은 프로세스의 다른 HTTP 요청에는 영향을 주지 않습니다(#15). 기본값None은 기존처럼 httpx의 환경변수 프록시(HTTPS_PROXY등)를 따르고, 값을 지정하면 환경변수 프록시보다 우선합니다.- 잘못된 프록시 URL은 설정을 만들 때
ValueError로 거절합니다. URL의 자격 증명은 오류 메시지와repr에 싣지 않습니다.proxy와 사용자transport를 함께 넘기면ValueError가 발생합니다. - SOCKS 프록시용 선택 설치
korail-mobile-api[socks]를 추가했습니다. 필수 의존성과 최소 버전은 그대로입니다.https프록시는 httpx 0.25.0 이상,socks5h는 httpx 0.28.0 이상이 필요하며 낮은 버전에서는 클라이언트를 만들 때 거절합니다. build_config_from_env가KORAIL_PROXY를 읽어proxy에 넣습니다. 비어 있으면 지정하지 않습니다.- 오류 처리 문서에 로그인의
-8202차단과 데이터센터·VPN 대역 안내를 더하고, README에 클라우드 서버 질문을 추가했습니다. - 프록시를 거친 실서버 요청은 이번 버전에서 확인하지 않았습니다. 프록시 연결과 요청 경로는 합성 테스트로 확인했습니다.
v2.3.0 — 기존 예약 가져오기
앱이나 다른 도구에서 만든 기존 예약을 예약번호로 불러와 카드 결제용 홀드로 사용할 수 있습니다.
hold = client.get_reservation_hold(pnr_no)
print(hold.received_amount)
payment = client.pay_with_card(hold, card) # 실제 카드 결제KorailClient.get_reservation_hold(pnr_no)를 추가했습니다. 앱이나 다른 도구에서 잡은 기존 예약의 상세를 읽어 카드 결제용 홀드를 반환합니다. 실제 창구번호·작업번호·여정과 정산액을 보존하고, PNR 불일치·필수값 누락·명시된 결제 플래그 오류·금액 불일치·0원 예약을 거절합니다. 새 예약이나 결제는 실행하지 않습니다.- 2026-09-29 실서버에서 예약 상세가
h_payment_flg를 생략하는 것을 확인해, 누락은None으로 보존하고 명시된 경우에만Y를 요구하도록 수정했습니다. 수정 후 실제 기존 예약 조회와 로컬 결제 폼의 식별자·정산액 보존을 확인했습니다. 시험용 임시 예약은 취소했으며 카드 결제 요청은 보내지 않았습니다. - 기존 예약 결제 가이드와 합성 테스트를 추가했습니다. N카드 예약 복원과 이번 흐름의 실제 카드 결제는 별도 검증하지 않았습니다.
- 환승·복수 좌석의 정산액 합과 서버 총액을 대조하고, 과도하게 큰 금액을 포함한 파싱 오류에는 전체 상세 응답을 보존합니다. 조회 실패나 결제 실패를 자동 재전송하지 않습니다.
- README, 예약·결제 API, 간편 API 안내, 오류 처리, 실서버 확인 현황과 배포 절차를 갱신했습니다. 기존 공개 API의 입력·반환형과 Python 3.11 이상 지원은 유지합니다.
설치
pip install --upgrade korail-mobile-api==2.3.0검증
Python 3.11~3.14 및 3.11 최소 의존성 조합에서 각각 2,211개 테스트가 통과했습니다. 별도 wheel 설치 환경의 회귀 테스트 68개, Ruff, Mypy strict, Pyright, 문서 strict 빌드와 배포 파일 메타데이터 검사도 통과했습니다.
기존 예약 상세 조회는 실서버에서 확인했습니다. 카드 결제는 로컬 폼 생성까지만 검사했으며, 실제 결제 요청과 N카드 예약 복원은 별도 검증하지 않았습니다.
v2.2.0 — 간편 API와 배포 검증
기존 KorailClient를 유지하면서 자주 쓰는 조회·예약 흐름을 더 간단히 사용할 수 있게 한 릴리스입니다. 코레일+ 안드로이드 앱 7.0.8의 요청 계약을 기준으로 합니다.
pip install --upgrade korail-mobile-api변경 사항
- 선택형
Korail간편 API에with문, KSTdatetime열차 검색, 역 목록 캐시·검증, 예약·승차권 리소스를 추가했습니다. 예약 생성 뒤 상세 조회는 명시적으로 호출합니다. TrainSearchQuery.include_nearby_stations로adjStnScdlOfrFlg의N/Y를 선택할 수 있습니다. 기본 요청은 이전과 같은N입니다.KorailDeviceProfile과build_config_from_profile로 DynaPath 기기값, 대기열 User-Agent, OS·화면 값을 일관되게 설정할 수 있습니다.- PyPI 수동 배포 전에 태그·패키지 버전 일치와 해당 태그의 CI 통과를 확인합니다. CI에는 분기 포함 커버리지 90% 하한을 추가했습니다.
검증 범위
오프라인 테스트 2,142개, 분기 포함 커버리지 92.12%, Python 3.11~3.14 CI, 타입 검사, 문서 빌드와 배포 파일 검사를 통과했습니다. 비로그인 실서버 조회에서는 인접역 표시 N과 Y 모두 SUCC/IRG000000을 받았으나, 검색 결과 차이는 확인하지 못했습니다. 자세한 내용은 변경 이력과 간편 API 가이드를 참고하세요.
v2.1.0 — 코레일+ 7.0.8 대응
코레일+ 안드로이드 앱 7.0.8에서 확인한 요청 계약을 반영한 릴리즈입니다.
pip install --upgrade korail-mobile-api변경 사항
- API
Version과 별도의AppVersion=7.0.8을 기본 요청에 싣습니다.KorailConfig.app_version=None으로 생략할 수 있습니다. - 메인 캐시 요청의 공통 필드와
srtCheckYn=Y, 은행 조회의 직접 필드를 7.0.8에 맞췄습니다. - 예약 상세 여정의
h_run_dt를run_date로 제공합니다. - 7.0.8 공개 메서드 검증표와 익명화한 근거를 추가했습니다.
검증 범위
공개 메서드 84개 중 실서버 응답 파싱 59개, 서버 거절 확인 10개, 전제 자료 부족으로 미실행 13개, 로컬 메서드 2개입니다. 이번 버전에서 카드 결제·환불 성공 경로는 재검증하지 않았습니다. CI에서 Python 3.11~3.14 테스트, 타입 검사, 배포 파일·문서 빌드를 통과했습니다.