@nomadamas/k-skill 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/package.json +1 -1
  2. package/skills/bunjang-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  3. package/skills/catchtable-sniper/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  4. package/skills/coupang-product-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  5. package/skills/daangn-cars-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  6. package/skills/daangn-jobs-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  7. package/skills/daangn-realty-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  8. package/skills/daangn-used-goods-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  9. package/skills/daishin-report-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  10. package/skills/daiso-product-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  11. package/skills/danawa-price-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  12. package/skills/delivery-tracking/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  13. package/skills/express-bus-booking/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  14. package/skills/flight-ticket-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  15. package/skills/foresttrip-vacancy/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  16. package/skills/hankookilbo-news/instruction.md +143 -0
  17. package/skills/hankookilbo-news/skill.json +8 -0
  18. package/skills/hipass-receipt/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  19. package/skills/intercity-bus-booking/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  20. package/skills/job-posting-match/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  21. package/skills/jobkorea-talent-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  22. package/skills/kakao-bar-nearby/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  23. package/skills/kakao-map/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  24. package/skills/kakaotalk-mac/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  25. package/skills/kbl-results/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  26. package/skills/kbo-results/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  27. package/skills/kleague-results/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  28. package/skills/korean-cinema-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  29. package/skills/korean-transit-route/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  30. package/skills/kosis-stats/instruction.md +24 -3
  31. package/skills/kosis-stats/references/kosis-openapi-guide.md +5 -1
  32. package/skills/kosis-stats/scripts/run_kosis_stats.py +1 -1
  33. package/skills/ktx-booking/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  34. package/skills/lck-analytics/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  35. package/skills/lotto-results/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  36. package/skills/market-kurly-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  37. package/skills/myrealtrip-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  38. package/skills/naver-ad-performance/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  39. package/skills/naver-blog-research/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  40. package/skills/naver-blog-research/scripts/naver_search.py +6 -1
  41. package/skills/naver-news-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  42. package/skills/naver-shopping-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  43. package/skills/ohou-today-deal/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  44. package/skills/olive-young-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  45. package/skills/popbill/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  46. package/skills/saramin-talent-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  47. package/skills/srt-booking/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  48. package/skills/store-longevity-radar/instruction.md +91 -0
  49. package/skills/store-longevity-radar/scripts/store_longevity_radar.py +230 -0
  50. package/skills/store-longevity-radar/skill.json +8 -0
  51. package/skills/ticket-availability/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  52. package/skills/toss-securities/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  53. package/skills/used-car-price-search/references/TRADEMARK-LEGAL-STATEMENT.md +9 -0
  54. package/skills/gangnamunni-clinic-search/instruction.md +0 -113
  55. package/skills/gangnamunni-clinic-search/skill.json +0 -9
@@ -54,10 +54,12 @@ GET https://kosis.kr/openapi/statisticsSearch.do
54
54
  &searchNm=인구&resultCount=20&startCount=1
55
55
  ```
56
56
 
57
- 응답 필드(주요): `ORG_ID`, `ORG_NM`, `TBL_ID`, `TBL_NM`, `STAT_ID`, `STAT_NM`, `VW_CD`, `MT_ATITLE`, `STRT_PRD_DE`, `END_PRD_DE`, `LINK_URL`.
57
+ 응답 필드(주요): `ORG_ID`, `ORG_NM`, `TBL_ID`, `TBL_NM`, `STAT_ID`, `STAT_NM`, `VW_CD`, `MT_ATITLE`, `PRD_SE`, `STRT_PRD_DE`, `END_PRD_DE`, `LINK_URL`.
58
58
 
59
59
  데이터 조회는 `ORG_ID` + `TBL_ID` 조합을 다음 단계에서 사용한다.
60
60
 
61
+ ⚠️ **`search` 의 `PRD_SE` 를 §3.3 의 `prdSe` 요청 파라미터로 그대로 쓰지 말 것.** 두 필드는 코드 체계가 다르다 — `DT_1IN0001`(총조사인구 총괄)은 `search` 가 `PRD_SE=A` 를 돌려주지만 실제 데이터 조회는 `prdSe=F` 로만 성공하고 `A`·`Y`·`IR` 은 모두 코드 `30`(결과 없음)이다. `STRT_PRD_DE`~`END_PRD_DE` 도 수록 범위일 뿐 간격(주기)을 알려주지 않는다. 요청용 주기는 `statisticsExplData.do`(helper 의 `explain` 서브커맨드) 의 조사주기 항목에서 확인하거나, §3.3 표의 코드를 좁은 슬라이스로 프로브해 확정한다.
62
+
61
63
  ### 3.2 통계표 메타데이터 (`statisticsData.do?method=getMeta`)
62
64
 
63
65
  통계표의 분류·항목·단위·국문/영문명 등을 조회한다.
@@ -97,6 +99,8 @@ GET https://kosis.kr/openapi/Param/statisticsParameterData.do
97
99
  | `F` | 다년(2,3,4,5,10년) | `YYYY` |
98
100
  | `IR` | 부정기 | `YYYY` 또는 `YYYYMMDD` |
99
101
 
102
+ `prdSe` 를 틀리면 `startPrdDe`/`endPrdDe`/`objL*` 이 전부 맞아도 응답은 항상 코드 `30`(결과 없음)이고, 메시지만으로는 주기 문제인지 구분되지 않는다. 5년 간격 총조사처럼 연 단위로 보이는 표가 `F`(다년)인 경우가 흔하므로, `statisticsExplData.do` 로 조사주기를 확인하거나 최소 슬라이스로 `Y` → `F` → `IR` → `M`/`Q`/`S` 순으로 프로브해 확정한 뒤 본 조회를 한다.
103
+
100
104
  분류 파라미터는 `objL1` ~ `objL8` (필요한 만큼만), 항목은 `itmId` (`ALL` 또는 특정 ID).
101
105
 
102
106
  응답 셀 필드: `PRD_DE` (기간), `ITM_NM` (항목), `UNIT_NM` (단위), `DT` (값), `C1_NM`~`C8_NM` (분류명).
@@ -58,7 +58,7 @@ ERROR_CODE_HINTS: dict[str, str] = {
58
58
  "11": "인증키가 만료되었거나 해당 endpoint에서 무효입니다. https://kosis.kr/openapi/ 에서 갱신하거나, bigdata는 본인이 등록한 userStatsId 인지 확인하세요.",
59
59
  "20": "필수 요청 변수가 누락되었습니다. `meta --table-id <ID> --meta-type ITM --json` 으로 ITM 안에 들어 있는 OBJ_ID(분류 차원)와 코드를 확인하세요(많은 표가 OBJ 메타는 비어 있고 분류가 ITM 안에 들어 있음). 그 뒤 `--obj-l 1=<코드> --obj-l 2=<코드>` 형태로 필요한 차원을 모두 지정해 재호출하세요. 별도 OBJ 메타가 있는 표는 `--meta-type OBJ` 로도 확인 가능합니다.",
60
60
  "21": "잘못된 요청 변수입니다. orgId/tblId/기간 형식을 재확인하세요. tblId가 의심되면 `search --query <키워드>` 로 정확한 ID를 다시 찾으세요.",
61
- "30": "조회 결과가 없습니다. 키워드를 더 짧게(예: '1인 가구' → '가구') 또는 다른 표현으로 재검색하거나, 기간/분류 필터를 완화하세요. meta 호출에서 이 에러가 나면 해당 메타 타입을 표가 지원하지 않는 경우이므로 다른 `--meta-type` 을 시도하세요.",
61
+ "30": "조회 결과가 없습니다. data 호출이면 먼저 `--prd-se` 오지정을 의심하세요 — 표의 실제 수록주기와 다르면 기간/분류가 맞아도 항상 이 에러가 납니다. 연 단위로 보이는 총조사·센서스류는 다년주기 `F` 또는 부정기 `IR` 인 경우가 많으니 `explain --org-id <ORG> --table-id <TBL>` 로 조사주기를 확인하거나 좁은 슬라이스로 `Y` → `F` → `IR` → `M`/`Q`/`S` 순으로 프로브하세요(`search` 응답의 `PRD_SE` 는 코드 체계가 달라 그대로 쓸 수 없습니다). search 호출이면 키워드를 더 짧게(예: '1인 가구' → '가구') 또는 다른 표현으로 재검색하거나, 기간/분류 필터를 완화하세요. meta 호출에서 이 에러가 나면 해당 메타 타입을 표가 지원하지 않는 경우이므로 다른 `--meta-type` 을 시도하세요.",
62
62
  "31": "조회 결과가 한도(40,000셀)를 초과했습니다. 기간을 좁히거나(예: 5년→1년) 분류 필터의 ALL 을 특정 코드로 바꾸세요(예: `--obj-l 1=ALL` → `--obj-l 1=11` 서울만). 그래도 부족하면 `bigdata` 서브커맨드 + 사전 등록한 userStatsId 를 사용하세요.",
63
63
  "40": "분당 호출 한도(1,000건)를 초과했습니다. 잠시 대기 후 재시도하거나 호출 간 sleep 을 두세요.",
64
64
  "41": "1회 호출 ROW 한도를 초과했습니다. 기간이나 분류를 좁혀 쿼리를 분할하세요.",
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `ktx-booking`
2
+
3
+ 이 스킬에서 `KTX`, `코레일`, `Korail` 명칭은 열차 조회·예약·취소의 **대상 철도 서비스와 운영기관**을 식별하기 위해 사용한다. k-skill의 출처나 운영주체를 코레일로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 운송계약, API·서비스 약관, 개인정보 또는 예약·결제 흐름의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `lck-analytics`
2
+
3
+ 이 스킬에서 `LCK`, `Riot Games`, `LoL Esports` 명칭은 경기 결과·순위·밴픽·메타 분석의 **대상 리그, 게임, 데이터 출처**를 식별하기 위해 사용한다. k-skill의 출처를 Riot Games 또는 LCK 운영주체로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 경기·게임 데이터의 저작권·데이터베이스권, 중계권, 커뮤니티 정책, 약관·계약 또는 접근 방식의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `lotto-results`
2
+
3
+ 이 스킬에서 `로또 6/45` 및 `Lotto` 명칭은 회차별 당첨번호·당첨금·일치 여부 조회의 **대상 복권 상품**을 식별하기 위해 사용한다. k-skill의 출처나 복권 발행·수탁 주체를 해당 운영기관으로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 복권 판매·구매 권한, 게임 규칙, 데이터 권리, 약관·계약 또는 접근 방식의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `market-kurly-search`
2
+
3
+ 이 스킬에서 `마켓컬리` 및 `Market Kurly` 명칭은 상품 검색·가격·할인·품절 조회의 **대상 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 마켓컬리 운영사로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 저작권, 데이터베이스권, 부정경쟁방지법, 약관·계약, 개인정보 또는 접근 방식의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `myrealtrip-search`
2
+
3
+ 이 스킬에서 `마이리얼트립` 및 `MyRealTrip` 명칭은 항공권·숙소·투어·티켓 검색의 **대상 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 마이리얼트립 운영사로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 여행상품 계약, 저작권, 데이터베이스권, 부정경쟁방지법, 약관·계약, 개인정보 또는 예약·결제 흐름의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `naver-ad-performance`
2
+
3
+ 이 스킬에서 `네이버 검색광고` 및 `Naver` 명칭은 광고 성과·캠페인·키워드 조회의 **대상 광고 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 네이버로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 API 이용약관, 광고계약, 영업비밀, 개인정보, 데이터베이스권 또는 접근 방식의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `naver-blog-research`
2
+
3
+ 이 스킬에서 `네이버 블로그` 및 `Naver` 명칭은 블로그 검색·본문 열람·이미지 내려받기의 **대상 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 네이버로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 게시물·이미지의 저작권, 데이터베이스권, 약관·계약, 개인정보 또는 수집·재사용의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -33,9 +33,14 @@ BLOG_ANCHOR_PATTERN = re.compile(
33
33
  re.DOTALL,
34
34
  )
35
35
 
36
+ # 검색 결과 앵커마다 시각적으로 숨겨진 접근성 라벨
37
+ # <span class="fender-ui_해시">새 창 열림</span>이 들어 있다. 클래스명은
38
+ # CSS 모듈 해시라 안정적이지 않으므로 라벨 텍스트 기준으로 span째 제거한다.
39
+ NEW_WINDOW_LABEL_RE = re.compile(r"<span[^>]*>\s*새\s*창\s*열림\s*</span>")
40
+
36
41
 
37
42
  def strip_html(text: str) -> str:
38
- return unescape(TAG_RE.sub("", text)).strip()
43
+ return unescape(TAG_RE.sub("", NEW_WINDOW_LABEL_RE.sub("", text))).strip()
39
44
 
40
45
 
41
46
  def build_search_params(query: str, start: int = FIRST_PAGE_START, sort: str = "sim") -> dict[str, str]:
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `naver-news-search`
2
+
3
+ 이 스킬에서 `네이버 뉴스` 및 `Naver` 명칭은 뉴스 검색 결과와 기사 링크 조회의 **대상 검색 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 네이버로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 기사·요약의 저작권, 데이터베이스권, 언론사 권리, 약관·계약 또는 재사용의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `naver-shopping-search`
2
+
3
+ 이 스킬에서 `네이버 쇼핑` 및 `Naver` 명칭은 상품 후보·최저가·판매처 링크 조회의 **대상 쇼핑 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 네이버로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 상품정보의 저작권·데이터베이스권, 부정경쟁방지법, 약관·계약 또는 접근·재사용의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `ohou-today-deal`
2
+
3
+ 이 스킬에서 `오늘의집` 명칭은 오늘의딜 상품·할인·리뷰 조회의 **대상 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 오늘의집 운영사로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 상품정보의 저작권·데이터베이스권, 부정경쟁방지법, 약관·계약 또는 접근·재사용의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `olive-young-search`
2
+
3
+ 이 스킬에서 `올리브영` 및 `Olive Young` 명칭은 매장·상품·재고 조회의 **대상 서비스**를 식별하기 위해 사용한다. k-skill 또는 upstream CLI의 출처를 올리브영 운영사로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 상품정보의 저작권·데이터베이스권, 부정경쟁방지법, 약관·계약 또는 접근·재사용의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `popbill`
2
+
3
+ 이 스킬에서 `팝빌` 및 `Popbill` 명칭은 전자세금계산서·전자명세서·현금영수증·메시징 등 **대상 API 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 팝빌 운영사로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 API 계약, 세무·전자문서 규제, 메시지 발송 권한, 개인정보 또는 개별 거래의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `saramin-talent-search`
2
+
3
+ 이 스킬에서 `사람인` 및 `Saramin` 명칭은 기업회원 인재검색·비교의 **대상 채용 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 사람인 운영사로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 채용 적합성, 저작권, 데이터베이스권, 부정경쟁방지법, 약관·계약, 개인정보 또는 접근 방식의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `srt-booking`
2
+
3
+ 이 스킬에서 `SRT` 및 `SR` 명칭은 열차 조회·예약·취소의 **대상 철도 서비스와 운영기관**을 식별하기 위해 사용한다. k-skill의 출처나 운영주체를 SR로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 운송계약, API·서비스 약관, 개인정보 또는 예약·결제 흐름의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,91 @@
1
+ # 장수 점포 레이더 (상가업소 시계열)
2
+
3
+ ## What this skill does
4
+
5
+ 공공데이터포털 **「소상공인시장진흥공단_상가(상권)정보」** 공개 파일(비회원 다운로드 가능)을 이용해 두 가지를 한다.
6
+
7
+ 1. `current` — 최신 분기 스냅샷(전국 17개 시도 zip)에서 **업종코드/상호 키워드로 점포 전수**를 뽑는다. 스냅샷에 존재 = 해당 시점 영업 중으로 취급되는 데이터다.
8
+ 2. `match` — 사용자가 가진 **과거 스냅샷 CSV**(예: 2019년 국가중점데이터 배포본)와 상호·좌표를 매칭해 **"과거에도 존재했고 지금도 존재하는" 장수 점포**를 추출한다.
9
+
10
+ 기본 업종은 문구·완구(`G21302` 문구/회화용품 소매업, `G21306` 장난감 소매업)이며 옵션으로 어떤 업종이든 지정할 수 있다.
11
+
12
+ ## Honest limitations (반드시 사용자에게 고지)
13
+
14
+ - 이 데이터에는 **사업자등록번호·개업일이 없다.** 산출되는 것은 "최초 관측 시점 하한"(그 시점에 이미 존재)이지 개업일이 아니다.
15
+ - 상호 변경·이전한 점포는 매칭에서 빠진다(과소집계). 동명 상호는 좌표 거리(기본 150m)로 구분하지만 단정하지 않는다.
16
+ - 폐업 확정은 사업자등록번호 확보 후 `nts-business-registration`(국세청 상태조회)으로 하고, 인허가 업종이면 `localdata-business-status`로 인허가일자(업력)를 본다.
17
+
18
+ ## Design principles
19
+
20
+ - 점수·등급 같은 해석 라벨을 만들지 않는다. 스냅샷 존재 사실 + 매칭 방법만 담는다.
21
+ - 무인증 공개 파일 서버이므로 프록시를 거치지 않고 사용자 머신에서 직접 받는다.
22
+ - 최신 zip은 수백 MB이므로 1일 로컬 캐시(`~/.cache/k-skill/store-longevity-radar/`)한다. 반복 다운로드하지 않는다.
23
+
24
+ ## When to use
25
+
26
+ - "지금도 영업 중인 오래된 문방구/철물점/레코드점 리스트 뽑아줘"
27
+ - "이 업종 전국 점포 전수 데이터 줘 (주소·좌표 포함)"
28
+ - "10년 전에도 있었고 아직 있는 가게 찾아줘" (과거 스냅샷 CSV 필요)
29
+
30
+ ## Prerequisites
31
+
32
+ - 인터넷 연결, `python3` (stdlib만 사용)
33
+ - `scripts/store_longevity_radar.py` helper
34
+ - `match`를 쓰려면 과거 스냅샷 CSV 파일 (사용자가 보유하거나 별도 확보; 과거분은 공공데이터포털에서 최신 분기만 배포되므로 강의·연구용 미러 등에서 구한다)
35
+
36
+ ## Credential requirements
37
+
38
+ - 없음. 무인증 공개 파일 다운로드다.
39
+
40
+ ## Inputs
41
+
42
+ - `--code`: 상권업종소분류코드 (반복 지정, 기본 `G21302` `G21306`). 다른 업종을 `match`할 때 코드체계가 바뀌었다면 현재 코드와 과거 코드를 모두 반복 지정한다.
43
+ - `--keyword`: 상호 키워드 (반복 지정, 기본 문구/문방구/완구/장난감 — 업종코드 밖 점포 보완용)
44
+ - `--sido`: 시도명 필터 (예: `서울`, `부산`; 생략 시 전국)
45
+ - `--zip`: 이미 받아둔 최신 zip 경로 (생략 시 자동 다운로드+캐시)
46
+ - `--old-csv`: (`match` 전용) 과거 스냅샷 CSV, 반복 지정. `'|'`/`','` 구분자 자동 감지
47
+ - `--max-dist`: (`match` 전용) 동일 상호 허용 좌표 거리(m), 기본 150
48
+ - `--out`, `--format`: 출력 파일/형식 (csv 기본, json 가능)
49
+
50
+ ## CLI examples
51
+
52
+ ```bash
53
+ # 전국 문구·완구 현재 전수 → CSV
54
+ npx -y @nomadamas/k-skill@0 exec store-longevity-radar scripts/store_longevity_radar.py -- \
55
+ current --out 전국_문구완구.csv
56
+
57
+ # 서울·부산만, 과거 2019 스냅샷과 매칭해 장수 점포 추출
58
+ npx -y @nomadamas/k-skill@0 exec store-longevity-radar scripts/store_longevity_radar.py -- \
59
+ match --sido 서울 --sido 부산 --old-csv 상가업소정보_201912_01.csv --out 장수점포.csv
60
+
61
+ # 다른 업종 예: 철물점 상호 키워드로
62
+ npx -y @nomadamas/k-skill@0 exec store-longevity-radar scripts/store_longevity_radar.py -- \
63
+ current --code NONE --keyword 철물 --out 전국_철물점.csv
64
+ ```
65
+
66
+ ## Workflow
67
+
68
+ 1. `current`부터 실행해 대상 업종 전수를 확보한다. zip 자동 다운로드는 수 분 걸릴 수 있음을 사용자에게 알린다.
69
+ 2. 과거 스냅샷 CSV가 있으면 `match`로 장수 점포를 추출한다. 기본 문구·완구 코드는 helper가 2022년 이전 `D08A01`/`D04A01`/`D04A02`를 자동 포함한다. 다른 업종은 현재 코드와 과거 코드를 `--code`로 함께 지정한다.
70
+ 3. 결과 전달 시 위 Honest limitations를 함께 요약한다.
71
+ 4. 후속 확인이 필요하면 `nts-business-registration`(폐업 확정), `localdata-business-status`(인허가 업력), `kakao-map`(전화번호·현재 등재)을 안내한다.
72
+
73
+ ## Failure modes
74
+
75
+ - 데이터셋 페이지에서 파일 ID 발견 실패 → `unavailable` + 수동 확인 URL 출력 (분기 개편 시 페이지 구조 변경 가능).
76
+ - 공공데이터포털 접속/다운로드 timeout 또는 HTTP 실패 → `unavailable` + 원인 + 수동 확인 URL 출력.
77
+ - 다운로드 중단 → `.part` 파일만 남고 캐시로 승격되지 않음. 재실행하면 이어서 새로 받는다.
78
+ - `match`에 과거 CSV 미지정 → argparse 에러. 과거분 확보 방법을 사용자에게 안내한다.
79
+ - 0건 매칭: 업종코드가 스냅샷 코드체계와 다를 수 있다. `--keyword`만으로 재시도한다.
80
+
81
+ ## Official surfaces
82
+
83
+ - 데이터셋: <https://www.data.go.kr/data/15083033/fileData.do>
84
+ - 다운로드: `https://www.data.go.kr/cmm/cmm/fileDownload.do?atchFileId=<FILE_ID>&fileDetailSn=1` (무인증)
85
+ - 관련 스킬: `nts-business-registration`, `localdata-business-status`, `kakao-map`
86
+
87
+ ## Done when
88
+
89
+ - `current` 결과 건수와 출력 파일 경로가 보고되었다.
90
+ - `match` 사용 시 매칭 방법(상가업소번호/상호+좌표)별 건수가 보고되었다.
91
+ - 개업일이 아닌 "최초 관측 시점 하한"임이 사용자에게 고지되었다.
@@ -0,0 +1,230 @@
1
+ # -*- coding: utf-8 -*-
2
+ """store-longevity-radar — 상가(상권)정보 스냅샷 기반 업종 전수 추출 + 장수 점포 매칭.
3
+
4
+ python3 stdlib만 사용한다.
5
+
6
+ subcommands:
7
+ current 최신 공개 스냅샷(무인증 zip)에서 업종코드/상호 키워드로 점포 전수 추출
8
+ match current 결과에 과거 스냅샷 CSV를 매칭해 장수 점포 추출
9
+
10
+ 데이터 출처: 공공데이터포털 「소상공인시장진흥공단_상가(상권)정보」 파일데이터
11
+ (https://www.data.go.kr/data/15083033/fileData.do) — 비회원 다운로드 가능.
12
+ """
13
+ import argparse
14
+ import csv
15
+ import io
16
+ import json
17
+ import math
18
+ import os
19
+ import re
20
+ import sys
21
+ import time
22
+ import urllib.error
23
+ import urllib.request
24
+ import zipfile
25
+
26
+ DATASET_PAGE = "https://www.data.go.kr/data/15083033/fileData.do"
27
+ DOWNLOAD_URL = "https://www.data.go.kr/cmm/cmm/fileDownload.do?atchFileId={fid}&fileDetailSn=1"
28
+ UA = "Mozilla/5.0 (compatible; k-skill-store-longevity-radar)"
29
+ CACHE_DIR = os.path.join(os.path.expanduser("~"), ".cache", "k-skill", "store-longevity-radar")
30
+ CACHE_TTL = 24 * 3600
31
+
32
+ DEFAULT_CODES = ["G21302", "G21306"] # 문구/회화용품 소매업, 장난감 소매업 (2022~ 코드체계)
33
+ DEFAULT_KEYWORDS = ["문구", "문방구", "완구", "장난감"]
34
+ LEGACY_CODES_BY_CURRENT = {
35
+ "G21302": {"D08A01"},
36
+ "G21306": {"D04A01", "D04A02"},
37
+ }
38
+ COLS = ["상가업소번호", "상호명", "상권업종소분류코드", "상권업종소분류명",
39
+ "시도명", "시군구명", "행정동명", "도로명주소", "지번주소", "경도", "위도"]
40
+
41
+
42
+ def log(msg):
43
+ print(msg, file=sys.stderr)
44
+
45
+
46
+ def http_get(url, timeout=60):
47
+ req = urllib.request.Request(url, headers={"User-Agent": UA, "Accept": "*/*"})
48
+ return urllib.request.urlopen(req, timeout=timeout)
49
+
50
+
51
+ def discover_atch_file_id():
52
+ """데이터셋 페이지에서 현재 분기 파일 ID를 찾는다 (분기마다 갱신됨)."""
53
+ html = http_get(DATASET_PAGE).read().decode("utf-8", "replace")
54
+ ids = re.findall(r"FILE_[0-9]{6,}", html)
55
+ if not ids:
56
+ raise SystemExit(json.dumps({"status": "unavailable",
57
+ "note": "데이터셋 페이지에서 파일 ID를 찾지 못함. 수동 확인: " + DATASET_PAGE},
58
+ ensure_ascii=False))
59
+ return ids[0]
60
+
61
+
62
+ def download_latest_zip():
63
+ os.makedirs(CACHE_DIR, exist_ok=True)
64
+ path = os.path.join(CACHE_DIR, "sdc_latest.zip")
65
+ if os.path.exists(path) and time.time() - os.path.getmtime(path) < CACHE_TTL:
66
+ log(f"cache hit: {path}")
67
+ return path
68
+ try:
69
+ fid = discover_atch_file_id()
70
+ log(f"downloading {fid} (수백 MB, 수 분 소요) ...")
71
+ tmp = path + ".part"
72
+ with http_get(DOWNLOAD_URL.format(fid=fid), timeout=1800) as r, open(tmp, "wb") as f:
73
+ while True:
74
+ chunk = r.read(1 << 20)
75
+ if not chunk:
76
+ break
77
+ f.write(chunk)
78
+ os.replace(tmp, path)
79
+ except (TimeoutError, urllib.error.URLError) as exc:
80
+ raise SystemExit(json.dumps({
81
+ "status": "unavailable",
82
+ "note": f"공공데이터포털 접속 또는 다운로드 실패: {exc}. 수동 확인: {DATASET_PAGE}",
83
+ }, ensure_ascii=False)) from None
84
+ return path
85
+
86
+
87
+ def norm_name(s):
88
+ s = re.sub(r"[\s()\[\]{}\-_.·&']", "", s or "")
89
+ return re.sub(r"(점|본점|지점)$", "", s)
90
+
91
+
92
+ def row_matches(d, codes, keywords):
93
+ if d.get("상권업종소분류코드") in codes:
94
+ return True
95
+ name = d.get("상호명", "")
96
+ return any(k in name for k in keywords)
97
+
98
+
99
+ def historical_codes(codes):
100
+ expanded = set(codes)
101
+ for code in codes:
102
+ expanded.update(LEGACY_CODES_BY_CURRENT.get(code, ()))
103
+ return expanded
104
+
105
+
106
+ def iter_csv(fobj, delimiter):
107
+ reader = csv.reader(io.TextIOWrapper(fobj, encoding="utf-8", errors="replace"),
108
+ delimiter=delimiter)
109
+ header = next(reader)
110
+ idx = {h: i for i, h in enumerate(header)}
111
+ for row in reader:
112
+ yield {h: (row[i] if i < len(row) else "") for h, i in idx.items() if h in COLS}
113
+
114
+
115
+ def extract_current(args):
116
+ path = args.zip or download_latest_zip()
117
+ rows = []
118
+ with zipfile.ZipFile(path) as z:
119
+ for info in z.infolist():
120
+ if not info.filename.endswith(".csv"):
121
+ continue
122
+ if args.sido and not any(s in info.filename for s in args.sido):
123
+ continue
124
+ with z.open(info) as f:
125
+ for d in iter_csv(f, ","):
126
+ if row_matches(d, set(args.code), args.keyword):
127
+ rows.append(d)
128
+ return rows
129
+
130
+
131
+ def load_old(paths, codes, keywords):
132
+ rows = []
133
+ for p in paths:
134
+ with open(p, "rb") as f:
135
+ head = f.read(4096).decode("utf-8", "replace")
136
+ delim = "|" if head.count("|") > head.count(",") else ","
137
+ with open(p, "rb") as f:
138
+ for d in iter_csv(f, delim):
139
+ if row_matches(d, codes, keywords):
140
+ rows.append(d)
141
+ return rows
142
+
143
+
144
+ def dist_m(a, b):
145
+ try:
146
+ return math.hypot((float(a["경도"]) - float(b["경도"])) * 88800,
147
+ (float(a["위도"]) - float(b["위도"])) * 111000)
148
+ except (ValueError, KeyError):
149
+ return float("inf")
150
+
151
+
152
+ def match_longevity(current, old, max_dist):
153
+ old_by_id = {o["상가업소번호"]: o for o in old if o.get("상가업소번호")}
154
+ old_by_name = {}
155
+ for o in old:
156
+ old_by_name.setdefault(norm_name(o.get("상호명")), []).append(o)
157
+ out = []
158
+ for c in current:
159
+ o, how = old_by_id.get(c.get("상가업소번호")), "상가업소번호"
160
+ if not o:
161
+ best = None
162
+ for cand in old_by_name.get(norm_name(c.get("상호명")), []):
163
+ d = dist_m(cand, c)
164
+ if d <= max_dist and (best is None or d < best[1]):
165
+ best = (cand, d)
166
+ if best:
167
+ o, how = best[0], f"상호+좌표({best[1]:.0f}m)"
168
+ if o:
169
+ rec = dict(c)
170
+ rec["과거상호"] = o.get("상호명", "")
171
+ rec["과거업종"] = o.get("상권업종소분류명", "")
172
+ rec["매칭방법"] = how
173
+ out.append(rec)
174
+ return out
175
+
176
+
177
+ def write_out(rows, out, fmt):
178
+ if fmt == "json" or not out:
179
+ payload = json.dumps({"count": len(rows), "rows": rows}, ensure_ascii=False)
180
+ if out:
181
+ with open(out, "w", encoding="utf-8") as f:
182
+ f.write(payload)
183
+ else:
184
+ print(payload)
185
+ return
186
+ cols = list(rows[0].keys()) if rows else COLS
187
+ with open(out, "w", encoding="utf-8-sig", newline="") as f:
188
+ w = csv.DictWriter(f, fieldnames=cols, extrasaction="ignore")
189
+ w.writeheader()
190
+ w.writerows(rows)
191
+ print(json.dumps({"count": len(rows), "saved": out}, ensure_ascii=False))
192
+
193
+
194
+ def main():
195
+ p = argparse.ArgumentParser(description=__doc__)
196
+ sub = p.add_subparsers(dest="cmd", required=True)
197
+ common = argparse.ArgumentParser(add_help=False)
198
+ common.add_argument("--code", action="append", default=None,
199
+ help="상권업종소분류코드 (반복 지정, 기본 G21302/G21306)")
200
+ common.add_argument("--keyword", action="append", default=None,
201
+ help="상호 키워드 (반복 지정, 기본 문구/문방구/완구/장난감)")
202
+ common.add_argument("--sido", action="append", default=None,
203
+ help="시도명 부분 문자열 필터 (예: 서울, 부산). 생략 시 전국")
204
+ common.add_argument("--zip", help="이미 받아둔 최신 스냅샷 zip 경로 (생략 시 자동 다운로드+캐시)")
205
+ common.add_argument("--out", help="출력 파일 경로 (생략 시 stdout JSON)")
206
+ common.add_argument("--format", choices=["csv", "json"], default="csv")
207
+
208
+ sub.add_parser("current", parents=[common], help="최신 스냅샷 업종 전수 추출")
209
+ mp = sub.add_parser("match", parents=[common], help="과거 스냅샷과 매칭해 장수 점포 추출")
210
+ mp.add_argument("--old-csv", action="append", required=True,
211
+ help="과거 상가업소 CSV 경로 (반복 지정 가능, '|'/',' 자동 감지)")
212
+ mp.add_argument("--max-dist", type=float, default=150.0,
213
+ help="상호 동일 시 허용 좌표 거리(m), 기본 150")
214
+
215
+ args = p.parse_args()
216
+ args.code = args.code or DEFAULT_CODES
217
+ args.keyword = args.keyword or DEFAULT_KEYWORDS
218
+
219
+ current = extract_current(args)
220
+ log(f"current: {len(current)}건")
221
+ if args.cmd == "current":
222
+ write_out(current, args.out, args.format)
223
+ return
224
+ old = load_old(args.old_csv, historical_codes(set(args.code)), args.keyword)
225
+ log(f"old: {len(old)}건")
226
+ write_out(match_longevity(current, old, args.max_dist), args.out, args.format)
227
+
228
+
229
+ if __name__ == "__main__":
230
+ main()
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "store-longevity-radar",
3
+ "description": "소상공인시장진흥공단 상가(상권)정보 공개파일(무인증)로 업종·상호 키워드에 맞는 전국 점포 전수를 뽑고, 과거 스냅샷과 상호+좌표 매칭해 'N년 전에도 존재했고 지금도 영업 중'인 장수 점포 리스트를 추출한다. 사업자등록번호 없이 상호 기준이며 개업일이 아닌 최초 관측 시점 하한을 제공한다.",
4
+ "profiles": [
5
+ "lookup"
6
+ ],
7
+ "frontmatter": "name: store-longevity-radar\ndescription: 소상공인시장진흥공단 상가(상권)정보 공개파일(무인증)로 업종·상호 키워드에 맞는 전국 점포 전수를 뽑고, 과거 스냅샷과 상호+좌표 매칭해 'N년 전에도 존재했고 지금도 영업 중'인 장수 점포 리스트를 추출한다. 사업자등록번호 없이 상호 기준이며 개업일이 아닌 최초 관측 시점 하한을 제공한다.\nlicense: MIT\nmetadata:\n category: business\n locale: ko-KR\n phase: v1"
8
+ }
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `ticket-availability`
2
+
3
+ 이 스킬에서 `YES24`와 `인터파크` 명칭은 공연 일정·등급별 잔여석 조회의 **대상 티켓 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 각 서비스 운영사로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 공연·좌석 데이터의 저작권·데이터베이스권, 약관·계약, 부정경쟁방지법 또는 접근 방식의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `toss-securities`
2
+
3
+ 이 스킬에서 `토스증권` 및 `Toss Securities` 명칭은 계좌·보유주식·시세·주문 조회의 **대상 증권 서비스**를 식별하기 위해 사용한다. k-skill 또는 fallback CLI의 출처를 토스증권으로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 금융규제, 투자 적합성, API·서비스 약관, 개인정보, 계좌 접근 또는 개별 거래의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)
@@ -0,0 +1,9 @@
1
+ # 상표 사용 법적 고지 — `used-car-price-search`
2
+
3
+ 이 스킬에서 `SK렌터카` 명칭은 중고차 재고·가격·인수가 조회의 **대상 판매·렌터카 서비스**를 식별하기 위해 사용한다. k-skill의 출처를 SK렌터카 운영사로 표시하려는 사용이 아니다.
4
+
5
+ 대법원 2005. 6. 10. 선고 [2005도1637 판결](https://www.law.go.kr/LSW/precInfoP.do?precSeq=83920)은 타인의 표장을 출처표시가 아니라 상품 기능 또는 적용 기종을 밝히기 위해 사용하고 상표 사용으로 인식될 수 없는 경우 침해가 아니라고 판시했다. [상표법 제2조](https://www.law.go.kr/법령/상표법/제2조), [제89조](https://www.law.go.kr/법령/상표법/제89조), [제90조](https://www.law.go.kr/법령/상표법/제90조), [제108조](https://www.law.go.kr/법령/상표법/제108조)와 대법원 [2011다18802](https://www.law.go.kr/LSW/precInfoP.do?precSeq=167457), [2019후10418](https://law.go.kr/LSW/precInfoP.do?mode=0&precSeq=230725) 판결에 따라 실제 거래계에서 출처표시로 기능하는지는 표시 태양과 사용 경위 등을 종합해 판단해야 한다.
6
+
7
+ 따라서 이 명칭은 필요한 범위의 평문으로만 사용하고, 별도 근거 없이 로고, 공식·제휴·후원·인증·파트너 표현을 사용하지 않는다. 각 상표의 권리는 해당 권리자에게 있다. 이 문서는 차량정보의 저작권·데이터베이스권, 매매·렌탈 계약, 약관·계약, 소비자보호 또는 접근 방식의 적법성을 판단하지 않는다.
8
+
9
+ 전체 검토: [제3자 상표의 기능 설명·호환 대상 표시 검토](https://github.com/NomaDamas/k-skill/blob/dev/docs/legal/trademark-use-review.md)