diff --git a/docs/ai-instruction.md b/docs/ai-instruction.md index d0f355e3..c5133ca8 100644 --- a/docs/ai-instruction.md +++ b/docs/ai-instruction.md @@ -55,7 +55,7 @@ GPT Actions가 이미 연결된 환경은 `queryAction(action=...)`을 사용하 - 상품 검색: `search_products`, 매장 검색: `find_stores`, 재고: `check_inventory`에 `service`를 전달합니다. 지원 서비스별 필수 인수는 입력 스키마를 따릅니다. - 상품 상세·가격·진열 위치: `get_product_details`에 `service`와 `operation`을 전달합니다. - 주변 장소·영화관: `find_places`, 영화·시간표·잔여석: `get_showtimes`에 `service`와 필요한 `operation`을 전달합니다. -- 유가·주유소: `get_fuel_info`, 인기 검색어·기획전: `get_catalog`의 `operation`을 선택합니다. +- 유가·주유소: `get_fuel_info`, 인기 검색어·기획전: `get_catalog`의 `operation`을 선택합니다. 올리브영 오특(오늘의 특가)은 `get_catalog`에 `service=oliveyoung`, `operation=today_deals`를 전달합니다. - 가격 비교: `compare_products`를 사용합니다. - 요청 제출: 사용자가 명시적으로 개발자 전달을 요청한 경우에만 `submit_request`에 `requestType=developer`, `request` 객체를 전달합니다. 오류 발생만으로 자동 제출하지 않습니다. - 일본 다이소는 `service=daiso_jp`의 상품·매장 검색 및 온라인 구매 가능 여부만 지원합니다. 매장 재고는 미지원이고 가격은 JPY입니다. 한국 KRW와 섞지 않습니다. 롯데마트는 지원 중단, MINISO는 미지원입니다. diff --git a/docs/mcp-tools.md b/docs/mcp-tools.md index f5383387..3ad1a71d 100644 --- a/docs/mcp-tools.md +++ b/docs/mcp-tools.md @@ -27,13 +27,17 @@ 일본 상세: `get_product_details {"service":"daiso_jp","operation":"product","id":"4550746075917"}`. 일본 매장별 재고는 지원하지 않습니다. +올리브영 오특: `get_catalog {"service":"oliveyoung","operation":"today_deals"}` + 요청 제출: `submit_request {"requestType":"developer","request":{"title":"문서 개선","description":"개선할 내용을 적습니다","type":"docs"}}`. 현재 개발자 요청 저장만 지원합니다. 다른 요청 유형은 거절하며 요청자의 의도 없이 제출하지 않습니다. 이 도구의 이름과 요청 구분은 미래 유형 확장을 위해 범용으로 유지합니다. 매개변수는 기존 작업의 이름과 형식을 사용합니다. operation은 같은 서비스에 작업이 여러 개인 경우 필수입니다. 예를 들어 CGV 시간표는 service=cgv, operation=timetable, playDate=YYYYMMDD이며 seats 작업은 지원하지 않습니다. 미지원 조합과 알 수 없는 인수·오타는 조회 전에 거절합니다. 공개 스키마에 있지만 선택한 서비스/작업에서 쓰지 않는 옵션은 실행을 막지 않고 응답의 추가 안내와 `_meta.ignoredArguments`로 미적용 사실을 알립니다. 미적용 조건을 충족했다고 안내하면 안 됩니다. 기본값은 선택한 작업의 기본값만 적용합니다. tools/list의 입력/출력 스키마를 참고하세요. ### 카탈로그와 매장 재고 검증 -`get_catalog`는 세븐일레븐의 공개 콘텐츠 조회입니다. `operation`은 필수이며 `popwords`(인기 검색어) 또는 `snapshot`(상품·이슈·기획전)을 지정합니다. `includeIssues`와 `includeExhibition`은 `snapshot` 전용입니다. 인기 검색어 원본 목록이 비어 있으면 `available=false`이며 외부 오류와 구분합니다. 원본 차단·중계 실패는 오류로 반환하며 빈 성공으로 바꾸지 않습니다. +`get_catalog`는 공개 콘텐츠 조회입니다. `operation`은 필수입니다. `service`를 생략하면 기존 호출과 같이 세븐일레븐이며 `popwords`(인기 검색어) 또는 `snapshot`(상품·이슈·기획전)을 지정합니다. `includeIssues`와 `includeExhibition`은 `snapshot` 전용입니다. 인기 검색어 원본 목록이 비어 있으면 `available=false`이며 외부 오류와 구분합니다. 원본 차단·중계 실패는 오류로 반환하며 빈 성공으로 바꾸지 않습니다. + +`service=oliveyoung`, `operation=today_deals`는 올리브영 오특(오늘의 특가) 화면의 `brandDeals`(오늘의 브랜드 특가)와 `todayDeals`(오늘의 특가 전체 목록)를 한국 날짜 기준으로 반환합니다. 가격은 조회 시점 화면 기준이며 `priceFrom=true`는 옵션별 최저가입니다. 실시간 재고가 아니므로 재고는 상품명으로 `check_inventory`(service=oliveyoung)를 조회합니다. 원본 차단·형식 변경은 빈 목록이 아니라 오류입니다. 다이소 `check_inventory`에서 `storeLimit`은 `pageSize`와 같은 매장 수 조건입니다. 함께 전달하면 두 값이 같아야 합니다. `productLimit`은 상품 후보 수이며 여러 상품의 재고를 모두 조회하는 옵션이 아닙니다. 결과의 `selectedProduct`가 재고 조회 기준 상품입니다. @@ -45,6 +49,8 @@ 기존 44개 호출 계약은 유지합니다. compare_products는 공개 이름이 그대로이며 나머지 43개 구형 이름은 deprecated 별칭입니다. 구형 이름도 동일한 / 및 /mcp의 tools/call로 호출할 수 있고 기존 인수/결과/오류 의미를 유지합니다. 성공 또는 반환된 오류 응답의 _meta.deprecated=true와 _meta.replacement는 이동할 공개 도구를 안내합니다. SDK 입력 검증 단계에서 거절된 요청에는 이 추가 정보가 없을 수 있습니다. tools/list와 공개 발견 목록에는 구형 별칭을 노출하지 않습니다. +공개 도구 통합 이후 추가한 내부 작업 `oliveyoung_get_today_deals`는 처음부터 공개 목록에 등록하지 않았으며 `get_catalog`로만 안내합니다. 구형 별칭과 같은 방식으로 호출은 가능하지만 새 연동에서는 사용하지 않습니다. + REST 경로와 CLI 명령은 변경하지 않습니다. 구형 별칭을 삭제하거나 다시 공개 목록에 등록하지 마세요. 새 연동은 아래 오른쪽 도구만 사용합니다. | 기존 이름 | 공개 도구 | service | operation | @@ -89,8 +95,8 @@ REST 경로와 CLI 명령은 변경하지 않습니다. 구형 별칭을 삭제 | `opinet_get_lowest_price_stations` | `get_fuel_info` | | lowest | | `opinet_search_stations_around` | `get_fuel_info` | | around | | `opinet_get_station_detail` | `get_fuel_info` | | detail | -| `seveneleven_get_search_popwords` | `get_catalog` | | popwords | -| `seveneleven_get_catalog_snapshot` | `get_catalog` | | snapshot | +| `seveneleven_get_search_popwords` | `get_catalog` | seveneleven | popwords | +| `seveneleven_get_catalog_snapshot` | `get_catalog` | seveneleven | snapshot | | `compare_products` | `compare_products` | | | | `submit_developer_request` | `submit_request` | | | diff --git a/docs/oliveyoung-today-deals-analysis.md b/docs/oliveyoung-today-deals-analysis.md new file mode 100644 index 00000000..15e6d419 --- /dev/null +++ b/docs/oliveyoung-today-deals-analysis.md @@ -0,0 +1,47 @@ +# 올리브영 오특 네트워크 분석 + +올리브영 오특(오늘의 특가) 화면의 데이터 출처와 응답 구조를 기록합니다. 구현은 `src/services/oliveyoung/todayDeals.ts`, 고정 경로와 응답 판정은 `src/services/oliveyoung/htmlRoute.ts`에 있습니다. + +## 확인 방법 + +2026-10-24와 2026-10-26(Asia/Seoul)에 Playwright 화면 브라우저로 `https://www.oliveyoung.co.kr/store/main/getHotdealList.do`를 열고 네트워크 요청을 기록했습니다. Cloudflare 보안 확인은 사람이 직접 통과했으며 자동으로 우회하지 않았습니다. 같은 날 화면에 표시된 목록과 파싱 결과의 상품명, 순서, 가격, 할인율, 혜택 표시를 대조했습니다. 이 결과는 확인 당시 관측값이며 원본 정책에 따라 바뀔 수 있습니다. + +## 데이터 출처 + +| 화면 섹션 | 요청 | 응답 | +| ------------------ | ---------------------------------------------------------------------------------------------------------------- | ---------------------- | +| 오늘의 브랜드 특가 | `GET /store/main/getHotdealList.do` | 페이지 HTML (약 147KB) | +| 오늘의 특가 | `GET /store/main/getHotdealPagingListAjax.do?date=YYYYMMDD&pageIdx=N&fltCondition=02&fltDispCatNo=&prdSort=rank` | 상품 카드 HTML 조각 | +| coming soon | 페이지 HTML 안의 배너 | 상품명과 이미지만 있음 | + +- JSON API는 확인하지 못했습니다. 두 응답 모두 HTML입니다. +- `date`는 한국 날짜이며 페이지 스크립트도 같은 값을 보냅니다. 오특은 한국 자정에 바뀝니다. +- 목록 조각은 10개씩 내려오며 마지막 다음 페이지는 공백만 있는 응답입니다. 2026-10-26에는 10, 10, 7개로 27개였습니다. +- 브랜드 특가 카드는 페이지 HTML에 처음부터 포함됩니다. 2026-10-26에는 4개였습니다. +- coming soon은 상품번호와 가격이 없어 구현하지 않았습니다. 사용자 관측 기준으로 대략 한국 시간 9시부터 표시됩니다. + +## 상품 카드 구조 + +두 섹션은 같은 `