delivery-tracking logo

delivery-tracking

delivery tracking

nomadamas/k-skill2.5Kinstalls5.3Kstars

SKILL.md

Full skill instructions

Delivery Tracking

What this skill does

CJ๋Œ€ํ•œํ†ต์šด๊ณผ ์šฐ์ฒด๊ตญ ๊ณต์‹ ์กฐํšŒ ํ‘œ๋ฉด์„ ์‚ฌ์šฉํ•ด ์†ก์žฅ ๋ฒˆํ˜ธ๋กœ ํ˜„์žฌ ๋ฐฐ์†ก ์ƒํƒœ๋ฅผ ์กฐํšŒํ•œ๋‹ค.

  • CJ๋Œ€ํ•œํ†ต์šด: ๊ณต์‹ ๋ฐฐ์†ก์กฐํšŒ ํŽ˜์ด์ง€๊ฐ€ ๋…ธ์ถœํ•˜๋Š” JSON endpoint ์‚ฌ์šฉ
  • ์šฐ์ฒด๊ตญ: ๊ณต์‹ ๋ฐฐ์†ก์กฐํšŒ ํŽ˜์ด์ง€๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” HTML endpoint ์‚ฌ์šฉ
  • ๊ฒฐ๊ณผ๋Š” ๊ณตํ†ต ํฌ๋งท(ํƒ๋ฐฐ์‚ฌ / ์†ก์žฅ๋ฒˆํ˜ธ / ํ˜„์žฌ ์ƒํƒœ / ์ตœ๊ทผ ์ด๋ฒคํŠธ๋“ค)์œผ๋กœ ์งง๊ฒŒ ์ •๋ฆฌ

When to use

  • "CJ๋Œ€ํ•œํ†ต์šด ์†ก์žฅ ์กฐํšŒํ•ด์ค˜"
  • "์šฐ์ฒด๊ตญ ํƒ๋ฐฐ ์ง€๊ธˆ ์–ด๋””์•ผ"
  • "์ด ์†ก์žฅ๋ฒˆํ˜ธ ๋ฐฐ์†ก์™„๋ฃŒ์ธ์ง€ ํ™•์ธํ•ด์ค˜"
  • "ํƒ๋ฐฐ์‚ฌ๋ณ„ ์กฐํšŒ ๋กœ์ง์„ ๋‚˜์ค‘์— ๋” ๋ถ™์ผ ์ˆ˜ ์žˆ๊ฒŒ ์ •๋ฆฌํ•ด์ค˜"

When not to use

  • ์ฃผ๋ฌธ๋ฒˆํ˜ธ๋งŒ ์žˆ๊ณ  ์†ก์žฅ๋ฒˆํ˜ธ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ
  • ํƒ๋ฐฐ ์˜ˆ์•ฝ/๋ฐ˜ํ’ˆ ์ ‘์ˆ˜๊นŒ์ง€ ๋ฐ”๋กœ ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ
  • ๋น„๊ณต์‹ ํ†ตํ•ฉ ๋ฐฐ์†ก์กฐํšŒ ์„œ๋น„์Šค๋กœ ์šฐํšŒํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

Prerequisites

  • ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ
  • python3
  • curl
  • ์„ ํƒ ์‚ฌํ•ญ: jq

Inputs

  • ํƒ๋ฐฐ์‚ฌ ์‹๋ณ„์ž: cj ๋˜๋Š” epost
  • ์†ก์žฅ๋ฒˆํ˜ธ
    • CJ๋Œ€ํ•œํ†ต์šด: ์ˆซ์ž 10์ž๋ฆฌ ๋˜๋Š” 12์ž๋ฆฌ
    • ์šฐ์ฒด๊ตญ: ์ˆซ์ž 13์ž๋ฆฌ

Carrier adapter rule

์ด ์Šคํ‚ฌ์€ ํƒ๋ฐฐ์‚ฌ๋ณ„ ๋กœ์ง์„ carrier adapter ๋‹จ์œ„๋กœ ๋‚˜๋ˆˆ๋‹ค.

์ƒˆ ํƒ๋ฐฐ์‚ฌ๋ฅผ ๋ถ™์ผ ๋•Œ๋Š” ์•„๋ž˜ ํ•„๋“œ๋ฅผ ๋จผ์ € ์ •ํ•œ๋‹ค.

  • carrier id: ์˜ˆ) cj, epost
  • validator: ์†ก์žฅ๋ฒˆํ˜ธ ์ž๋ฆฌ์ˆ˜/ํŒจํ„ด
  • entrypoint: ๊ณต์‹ ์กฐํšŒ ์ง„์ž… URL
  • transport: JSON API / HTML form / CLI ์ค‘ ๋ฌด์—‡์„ ์“ฐ๋Š”์ง€
  • parser: ์–ด๋–ค ํ•„๋“œ๋‚˜ ํ…Œ์ด๋ธ”์—์„œ ์ƒํƒœ๋ฅผ ๋ฝ‘๋Š”์ง€
  • status map: ๊ฐ ํƒ๋ฐฐ์‚ฌ์˜ ์›๋ณธ ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๊ณตํ†ต ์ƒํƒœ๋กœ ์–ด๋–ป๊ฒŒ ์ค„์ผ์ง€
  • retry policy: timeout/retry ๊ทœ์น™

ํ˜„์žฌ ์–ด๋Œ‘ํ„ฐ๋Š” ์•„๋ž˜ ๋‘˜์ด๋‹ค.

carrier adapterofficial entrytransportvalidatorparser focus
cjhttps://www.cjlogistics.com/ko/tool/parcel/trackingpage GET + tracking-detail POST JSON10์ž๋ฆฌ ๋˜๋Š” 12์ž๋ฆฌ ์ˆซ์žparcelDetailResultMap.resultList
eposthttps://service.epost.go.kr/trace.RetrieveRegiPrclDeliv.postal?sid1=form POST HTML13์ž๋ฆฌ ์ˆซ์ž๊ธฐ๋ณธ์ •๋ณด table_col + ์ƒ์„ธ processTable

Workflow

0. Normalize the input first

  • ํƒ๋ฐฐ์‚ฌ ์ด๋ฆ„์„ cj / epost ๋‘˜ ์ค‘ ํ•˜๋‚˜๋กœ ์ •๊ทœํ™”ํ•œ๋‹ค.
  • ์†ก์žฅ๋ฒˆํ˜ธ์—์„œ ๊ณต๋ฐฑ๊ณผ - ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค.
  • ์ž๋ฆฌ์ˆ˜ ๊ฒ€์ฆ์ด ๋จผ์ € ์‹คํŒจํ•˜๋ฉด ์กฐํšŒ๋ฅผ ๋ณด๋‚ด์ง€ ์•Š๋Š”๋‹ค.

1. CJ๋Œ€ํ•œํ†ต์šด: official JSON flow

๊ณต์‹ ์ง„์ž… ํŽ˜์ด์ง€์—์„œ _csrf ๋ฅผ ์ฝ๊ณ , ๊ทธ ๊ฐ’์„ tracking-detail POST์— ๊ฐ™์ด ๋ณด๋‚ธ๋‹ค.

  • ์ง„์ž… ํŽ˜์ด์ง€: https://www.cjlogistics.com/ko/tool/parcel/tracking
  • ์ƒ์„ธ endpoint: https://www.cjlogistics.com/ko/tool/parcel/tracking-detail
  • ํ•„์ˆ˜ ํ•„๋“œ: _csrf, paramInvcNo

๊ธฐ๋ณธ ์˜ˆ์‹œ๋Š” curl ๋กœ _csrf ์™€ cookie๋ฅผ ์œ ์ง€ํ•˜๊ณ , Python์€ JSON ์ •๋ฆฌ์—๋งŒ ์“ด๋‹ค.

tmp_body="$(mktemp)"
tmp_cookie="$(mktemp)"
tmp_json="$(mktemp)"
invoice="1234567890"  # ๊ณต์‹ ํŽ˜์ด์ง€ placeholder ์„ฑ๊ฒฉ์˜ smoke-test ๊ฐ’

curl -sS -L -c "$tmp_cookie" \
  "https://www.cjlogistics.com/ko/tool/parcel/tracking" \
  -o "$tmp_body"

csrf="$(python3 - <<'PY' "$tmp_body"
import re
import sys

text = open(sys.argv[1], encoding="utf-8", errors="ignore").read()
print(re.search(r'name="_csrf" value="([^"]+)"', text).group(1))
PY
)"

curl -sS -L -b "$tmp_cookie" \
  -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
  --data-urlencode "_csrf=$csrf" \
  --data-urlencode "paramInvcNo=$invoice" \
  "https://www.cjlogistics.com/ko/tool/parcel/tracking-detail" \
  -o "$tmp_json"

python3 - <<'PY' "$tmp_json"
import json
import sys

payload = json.load(open(sys.argv[1], encoding="utf-8"))
events = payload["parcelDetailResultMap"]["resultList"]
if not events:
    raise SystemExit("์กฐํšŒ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")

status_map = {
    "11": "์ƒํ’ˆ์ธ์ˆ˜",
    "21": "์ƒํ’ˆ์ด๋™์ค‘",
    "41": "์ƒํ’ˆ์ด๋™์ค‘",
    "42": "๋ฐฐ์†ก์ง€๋„์ฐฉ",
    "44": "์ƒํ’ˆ์ด๋™์ค‘",
    "82": "๋ฐฐ์†ก์ถœ๋ฐœ",
    "91": "๋ฐฐ๋‹ฌ์™„๋ฃŒ",
}

latest = events[-1]
normalized_events = [
    {
        "timestamp": event.get("dTime"),
        "location": event.get("regBranNm"),
        "status_code": event.get("crgSt"),
        "status": status_map.get(event.get("crgSt"), event.get("scanNm") or "์•Œ์ˆ˜์—†์Œ"),
    }
    for event in events
]
print(json.dumps({
    "carrier": "cj",
    "invoice": payload["parcelDetailResultMap"]["paramInvcNo"],
    "status_code": latest.get("crgSt"),
    "status": status_map.get(latest.get("crgSt"), latest.get("scanNm") or "์•Œ์ˆ˜์—†์Œ"),
    "timestamp": latest.get("dTime"),
    "location": latest.get("regBranNm"),
    "event_count": len(events),
    "recent_events": normalized_events[-min(3, len(normalized_events)):],
}, ensure_ascii=False, indent=2))
PY

rm -f "$tmp_body" "$tmp_cookie" "$tmp_json"
CJ ๊ณต๊ฐœ ์ถœ๋ ฅ ์˜ˆ์‹œ

์•„๋ž˜ ๊ฐ’์€ 2026-03-27 ๊ธฐ์ค€ live smoke test(1234567890)์—์„œ ํ™•์ธํ•œ ์ •๊ทœํ™” ๊ฒฐ๊ณผ๋‹ค.

{
  "carrier": "cj",
  "invoice": "1234567890",
  "status_code": "91",
  "status": "๋ฐฐ๋‹ฌ์™„๋ฃŒ",
  "timestamp": "2026-03-21 12:22:13",
  "location": "๊ฒฝ๊ธฐ๊ด‘์ฃผ์˜คํฌ",
  "event_count": 3,
  "recent_events": [
    {
      "timestamp": "2026-03-10 03:01:45",
      "location": "์ฒญ์›HUB",
      "status_code": "44",
      "status": "์ƒํ’ˆ์ด๋™์ค‘"
    },
    {
      "timestamp": "2026-03-21 10:53:19",
      "location": "๊ฒฝ๊ธฐ๊ด‘์ฃผ์˜คํฌ",
      "status_code": "82",
      "status": "๋ฐฐ์†ก์ถœ๋ฐœ"
    },
    {
      "timestamp": "2026-03-21 12:22:13",
      "location": "๊ฒฝ๊ธฐ๊ด‘์ฃผ์˜คํฌ",
      "status_code": "91",
      "status": "๋ฐฐ๋‹ฌ์™„๋ฃŒ"
    }
  ]
}

์ถ”๊ฐ€ smoke test ๋กœ๋Š” 000000000000 ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

CJ ์‘๋‹ต์€ parcelResultMap.resultList ๊ฐ€ ๋น„์–ด ์žˆ์–ด๋„ parcelDetailResultMap.resultList ์ชฝ์— ์ด๋ฒคํŠธ๊ฐ€ ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ƒ์„ธ ์ด๋ฒคํŠธ ๋ฐฐ์—ด์„ ์šฐ์„  ๋ณธ๋‹ค. published ์˜ˆ์‹œ๋Š” ๊ณตํ†ต ๊ฒฐ๊ณผ ์Šคํ‚ค๋งˆ(carrier, invoice, status, timestamp, location, event_count, recent_events, ์„ ํƒ์  status_code)์— ๋งž์ถฐ ๋น„์‹๋ณ„ ํ•„๋“œ๋งŒ ๋‚จ๊ธฐ๊ณ , ๋‹ด๋‹น์ž ์ด๋ฆ„ยท์—ฐ๋ฝ์ฒ˜๊ฐ€ ์„ž์ผ ์ˆ˜ ์žˆ๋Š” crgNm ์›๋ฌธ์€ ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

2. ์šฐ์ฒด๊ตญ: official HTML flow

์šฐ์ฒด๊ตญ์€ ๊ณต์‹ entry page๊ฐ€ ๋‹ค์‹œ trace.RetrieveDomRigiTraceList.comm ์œผ๋กœ sid1 ์„ POSTํ•˜๋Š” ๊ตฌ์กฐ๋‹ค.

  • ์ง„์ž… ํŽ˜์ด์ง€: https://service.epost.go.kr/trace.RetrieveRegiPrclDeliv.postal?sid1=
  • ์‹ค์ œ ์กฐํšŒ endpoint: https://service.epost.go.kr/trace.RetrieveDomRigiTraceList.comm
  • ํ•„์ˆ˜ ํ•„๋“œ: sid1

์šฐ์ฒด๊ตญ์€ ๋กœ์ปฌ Python HTTP client๋ณด๋‹ค curl --http1.1 --tls-max 1.2 ๊ฒฝ๋กœ๊ฐ€ ๋” ์•ˆ์ •์ ์ด๋ฏ€๋กœ ๊ทธ ์กฐํ•ฉ์„ ๊ธฐ๋ณธ ์˜ˆ์‹œ๋กœ ์“ด๋‹ค.

tmp_html="$(mktemp)"
python3 - <<'PY' "$tmp_html"
import html
import json
import re
import subprocess
import sys

invoice = "1234567890123"  # ๊ณต์‹ ํŽ˜์ด์ง€ placeholder ์„ฑ๊ฒฉ์˜ smoke-test ๊ฐ’
output_path = sys.argv[1]

cmd = [
    "curl",
    "--http1.1",
    "--tls-max",
    "1.2",
    "--silent",
    "--show-error",
    "--location",
    "--retry",
    "3",
    "--retry-all-errors",
    "--retry-delay",
    "1",
    "--max-time",
    "30",
    "-o",
    output_path,
    "-d",
    f"sid1={invoice}",
    "https://service.epost.go.kr/trace.RetrieveDomRigiTraceList.comm",
]
subprocess.run(cmd, check=True)

page = open(output_path, encoding="utf-8", errors="ignore").read()

summary = re.search(
    r"<th scope=\"row\">(?P<tracking>[^<]+)</th>.*?"
    r"<td>(?P<sender>.*?)</td>.*?"
    r"<td>(?P<receiver>.*?)</td>.*?"
    r"<td>(?P<delivered_to>.*?)</td>.*?"
    r"<td>(?P<kind>.*?)</td>.*?"
    r"<td>(?P<result>.*?)</td>",
    page,
    re.S,
)
if not summary:
    raise SystemExit("๊ธฐ๋ณธ์ •๋ณด ํ…Œ์ด๋ธ”์„ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.")

def clean(raw: str) -> str:
    text = re.sub(r"<[^>]+>", " ", raw)
    return " ".join(html.unescape(text).split())

def clean_location(raw: str) -> str:
    text = clean(raw)
    return re.sub(r"\s*(TEL\s*:?\s*)?\d{2,4}[.\-]\d{3,4}[.\-]\d{4}", "", text).strip()

events = re.findall(
    r"<tr>\s*<td>(\d{4}\.\d{2}\.\d{2})</td>\s*"
    r"<td>(\d{2}:\d{2})</td>\s*"
    r"<td>(.*?)</td>\s*"
    r"<td>\s*<span class=\"evtnm\">(.*?)</span>(.*?)</td>\s*</tr>",
    page,
    re.S,
)

normalized_events = [
    {
        "timestamp": f"{day} {time_}",
        "location": clean_location(location),
        "status": clean(status),
    }
    for day, time_, location, status, _detail in events
]

latest_event = normalized_events[-1] if normalized_events else None

print(json.dumps({
    "carrier": "epost",
    "invoice": clean(summary.group("tracking")),
    "status": clean(summary.group("result")),
    "timestamp": latest_event["timestamp"] if latest_event else None,
    "location": latest_event["location"] if latest_event else None,
    "event_count": len(normalized_events),
    "recent_events": normalized_events[-min(3, len(normalized_events)):],
}, ensure_ascii=False, indent=2))
PY
rm -f "$tmp_html"
์šฐ์ฒด๊ตญ ๊ณต๊ฐœ ์ถœ๋ ฅ ์˜ˆ์‹œ

์•„๋ž˜ ๊ฐ’์€ 2026-03-27 ๊ธฐ์ค€ live smoke test(1234567890123)์—์„œ ํ™•์ธํ•œ ์ •๊ทœํ™” ๊ฒฐ๊ณผ๋‹ค.

{
  "carrier": "epost",
  "invoice": "1234567890123",
  "status": "๋ฐฐ๋‹ฌ์™„๋ฃŒ",
  "timestamp": "2025.12.04 15:13",
  "location": "์ œ์ฃผ์šฐํŽธ์ง‘์ค‘๊ตญ",
  "event_count": 2,
  "recent_events": [
    {
      "timestamp": "2025.12.04 15:13",
      "location": "์ œ์ฃผ์šฐํŽธ์ง‘์ค‘๊ตญ",
      "status": "๋ฐฐ๋‹ฌ์ค€๋น„"
    },
    {
      "timestamp": "2025.12.04 15:13",
      "location": "์ œ์ฃผ์šฐํŽธ์ง‘์ค‘๊ตญ",
      "status": "๋ฐฐ๋‹ฌ์™„๋ฃŒ"
    }
  ]
}

์šฐ์ฒด๊ตญ ๊ธฐ๋ณธ์ •๋ณด ํ…Œ์ด๋ธ”์€ ๋“ฑ๊ธฐ๋ฒˆํ˜ธ, ๋ณด๋‚ด๋Š” ๋ถ„/์ ‘์ˆ˜์ผ์ž, ๋ฐ›๋Š” ๋ถ„, ์ˆ˜๋ น์ธ/๋ฐฐ๋‹ฌ์ผ์ž, ์ทจ๊ธ‰๊ตฌ๋ถ„, ๋ฐฐ๋‹ฌ๊ฒฐ๊ณผ ์ˆœ์„œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ƒ์„ธ ์ด๋ฒคํŠธ๋Š” processTable ์•„๋ž˜ ๋‚ ์งœ / ์‹œ๊ฐ„ / ๋ฐœ์ƒ๊ตญ / ์ฒ˜๋ฆฌํ˜„ํ™ฉ ํ–‰์„ ์ฝ์œผ๋ฉด ๋œ๋‹ค. published ์˜ˆ์‹œ๋Š” CJ์™€ ๊ฐ™์€ ๊ณตํ†ต ๊ฒฐ๊ณผ ์Šคํ‚ค๋งˆ(carrier, invoice, status, timestamp, location, event_count, recent_events)์— ๋งž์ถฐ ๋ฐฐ์†ก ์ƒํƒœ์— ํ•„์š”ํ•œ ๊ฐ’๋งŒ ๋‚จ๊ธฐ๊ณ , ์ด๋ฒคํŠธ location์— ์„ž์ผ ์ˆ˜ ์žˆ๋Š” TEL ๋ฒˆํ˜ธ ์กฐ๊ฐ๋„ ์ œ๊ฑฐํ•œ ๋’ค ์ˆ˜๋ น์ธ/์ƒ์„ธ ๋ฉ”๋ชจ ์›๋ฌธ์€ ๊ทธ๋Œ€๋กœ ๋…ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค.

3. Normalize for humans

์‘๋‹ต ์›๋ฌธ์„ ๊ทธ๋Œ€๋กœ ๋ถ™์ด์ง€ ๋ง๊ณ  ์•„๋ž˜ ๊ณตํ†ต ๊ฒฐ๊ณผ ์Šคํ‚ค๋งˆ๋กœ ์š”์•ฝํ•œ๋‹ค.

๊ณตํ†ต ๊ฒฐ๊ณผ ์Šคํ‚ค๋งˆ
  • carrier: ํƒ๋ฐฐ์‚ฌ ์‹๋ณ„์ž (cj ๋˜๋Š” epost)
  • invoice: ์ •๊ทœํ™”๋œ ์†ก์žฅ๋ฒˆํ˜ธ
  • status: ํ˜„์žฌ ๋ฐฐ์†ก ์ƒํƒœ
  • timestamp: ๋งˆ์ง€๋ง‰ ์ด๋ฒคํŠธ ์‹œ๊ฐ
  • location: ๋งˆ์ง€๋ง‰ ์ด๋ฒคํŠธ ์œ„์น˜
  • event_count: ์ „์ฒด ์ด๋ฒคํŠธ ์ˆ˜
  • recent_events: ์ตœ๊ทผ ์ตœ๋Œ€ 3๊ฐœ ์ด๋ฒคํŠธ ๋ชฉ๋ก
  • status_code: ํ•„์š”ํ•  ๋•Œ๋งŒ ๋‚จ๊ธฐ๋Š” ์›๋ณธ ์ƒํƒœ ์ฝ”๋“œ (ํ˜„์žฌ๋Š” CJ ์˜ˆ์‹œ์—์„œ๋งŒ ์‚ฌ์šฉ)

4. Retry and fallback policy

  • ์ž๋ฆฌ์ˆ˜ ์˜ค๋ฅ˜๋ฉด ๋ฐ”๋กœ ๋ฉˆ์ถ”๊ณ  ์˜ฌ๋ฐ”๋ฅธ ํ˜•์‹์„ ๋‹ค์‹œ ๋ฐ›๋Š”๋‹ค.
  • CJ๋Š” _csrf ์žฌ์ทจ๋“ ํ›„ ํ•œ ๋ฒˆ ๋” ์‹œ๋„ํ•œ๋‹ค.
  • ์šฐ์ฒด๊ตญ์€ curl --retry 3 --retry-all-errors --retry-delay 1 ์„ ์œ ์ง€ํ•œ๋‹ค.
  • ๋‹ค๋ฅธ ํƒ๋ฐฐ์‚ฌ๋กœ ์šฐํšŒํ•˜์ง€ ์•Š๋Š”๋‹ค.

Done when

  • ํƒ๋ฐฐ์‚ฌ์™€ ์†ก์žฅ๋ฒˆํ˜ธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‹๋ณ„๋˜์–ด ์žˆ๋‹ค
  • ํ˜„์žฌ ์ƒํƒœ์™€ ์ตœ๊ทผ ์ด๋ฒคํŠธ๊ฐ€ ์ •๋ฆฌ๋˜์–ด ์žˆ๋‹ค
  • ์–ด๋А official surface๋ฅผ ์ผ๋Š”์ง€ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๋‹ค๋ฅธ ํƒ๋ฐฐ์‚ฌ ํ™•์žฅ ์‹œ ์–ด๋–ค carrier adapter ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š”์ง€ ๋‚จ์•„ ์žˆ๋‹ค

Failure modes

  • CJ: _csrf ์ถ”์ถœ ์‹คํŒจ ๋˜๋Š” tracking-detail ์‘๋‹ต ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ
  • CJ: ์†ก์žฅ๋ฒˆํ˜ธ ๊ธธ์ด๊ฐ€ 10์ž๋ฆฌ ๋˜๋Š” 12์ž๋ฆฌ๊ฐ€ ์•„๋‹˜
  • ์šฐ์ฒด๊ตญ: sid1 ์ด 13์ž๋ฆฌ๊ฐ€ ์•„๋‹˜
  • ์šฐ์ฒด๊ตญ: HTML ๋งˆํฌ์—… ๋ณ€๊ฒฝ์œผ๋กœ ํ…Œ์ด๋ธ” ์ถ”์ถœ ๊ทœ์น™์ด ๊นจ์ง
  • ์šฐ์ฒด๊ตญ: curl ์—†์ด ๋‹ค๋ฅธ client๋กœ ๋ถ™๋‹ค๊ฐ€ timeout/reset ๋ฐœ์ƒ

Notes

  • ์กฐํšŒํ˜• ์Šคํ‚ฌ์ด๋‹ค.
  • ๊ธฐ๋ณธ ํ‘œ๋ฉด์€ ๊ณต์‹ carrier endpoint๋งŒ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋‹ค๋ฅธ ํƒ๋ฐฐ์‚ฌ ์ถ”๊ฐ€๋Š” ์ƒˆ carrier adapter 1๊ฐœ๋ฅผ ๊ฐ™์€ ํฌ๋งท์œผ๋กœ ๋ถ™์ด๋Š” ๋ฐฉ์‹์œผ๋กœ ํ™•์žฅํ•œ๋‹ค.