포트로직스
경력근거: 운임 원장, 선사·파트너 API, EDI, 비표준 메일과 PDF, 크롤링 원천을 정합성까지 검증해 하나로 통합합니다.
※ 실제 산출물이 아닌 AI 예측 시안입니다.
포트로직스는 이메일에 기댄 수출입 업무를 자사 솔루션 TOMS 로 옮기는 디지털 포워더이고, 이 자리는 개발본부 네 셀 가운데 나머지 셀이 공통으로 딛는 기반을 만드는 플랫폼 셀입니다. 공고가 데이터 통합 항목에서 운임 원장과 선사·파트너 API, EDI, 비표준 메일과 PDF, 크롤링을 정합성까지 검증해 하나로 통합하고 그 검증 도구를 직접 만든다고 적었고, 같은 셀이 자동 견적 엔진도 들고 있어 원장에 잘못 얹힌 요율이 곧바로 견적 금액으로 나갑니다. 선사마다 요금 코드를 다르게 쓰고 같은 노선을 API 와 메일이 다른 금액으로 보내오는 모양은 포워딩 원천을 다섯 갈래로 받는 회사에서만 나오는 문제입니다. 이 포트폴리오는 여러 원천의 요율을 키로 짝지어 금액과 기간과 통화를 견주는 기술을 보여줍니다. 해상운임 시황이나 선사 계약 구조 전문성은 주장하지 않습니다. 여기서 더 들어가는 질문에는 아는 척하지 않고 모른다고 답하겠습니다.
공고가 운임 원장과 선사 API, EDI, 비표준 메일과 PDF, 크롤링을 정합성까지 검증해 하나로 합치는 일을 플랫폼 셀의 업무로 못박았습니다. 그 문장이 이 편의 판정 대상 그대로입니다.
플랫폼 셀의 사용자가 다른 셀 엔지니어와 사내 현업이라고 적혀 있습니다. 그래서 산출물을 터미널 도구가 아니라 프라이싱 담당이 매일 여는 화면으로 잡았습니다.
자동 견적 엔진이 플랫폼 셀 소유로 적혀 있어, 원장에 어긋난 요율이 얹히면 그대로 견적으로 나갑니다. 원장에 올리기 전에 거르는 자리가 여기입니다.
선사와 파트너가 API·EDI·메일·PDF·크롤링으로 제각각 보내온 요율 줄을 하루치로 모아, 사내 운임 원장에 이미 올라 있는 값과 노선표에 맞춰 한 줄씩 어디가 어긋났는지 정하는 관리자 페이지입니다. 메일과 PDF, 크롤링이 사람 읽으라고 적어 보낸 금액 표기는 원천별 규칙표대로 통화 기호와 규격 꼬리표를 떼고 천 단위와 소수 구분을 풀어 숫자로 돌려놓은 뒤에 씁니다. 그렇게 채운 금액을 선사 코드와 노선, 컨테이너 규격, 요금 코드 네 값으로 찾은 원장 줄과 빼 보고, 받은 날이 그 요율의 유효기간 안인지 보고, 통화 단위가 원장과 같은지 보고, 같은 항목을 두 원천이 서로 다른 금액으로 보내왔는지 봅니다. 어긋난 줄은 사유별로 묶여 원장 줄 번호와 벌어진 금액을 달고 서므로, 프라이싱 담당은 원장에 올릴 것과 선사에 되물을 것을 그 자리에서 갈라냅니다.
선사·파트너가 메일·PDF·EDI·API 로 제각각 보내오는 운임을 받아 통합 원장에 올리는 사내 프라이싱 담당자와, 그 원장 위에 자동 견적 엔진을 얹어 둔 플랫폼 팀 — 무엇이 최신이고 무엇이 어긋났는지 지금은 손으로 대조한다
요율 한 줄은 어느 원천으로 들어오든 선사 코드와 노선, 컨테이너 규격, 요금 코드 네 값으로 원장의 한 줄을 가리키고, 금액과 통화와 유효기간은 그 줄에 숫자와 날짜로 적혀 있습니다. 그래서 네 값으로 짝을 찾아 견주는 규칙을 붙이면, 어긋난 요율이 견적으로 나간 뒤가 아니라 원장에 올라가기 전에 걸린다는 가정입니다.
수집 원천 표와 운임 원장, 노선표를 올리면 요율 한 줄마다 여섯 판정 중 하나를 정하고 짝지은 원장 줄 번호와 벌어진 금액을 붙여 사유별로 묶어 보여주는 관리자 페이지입니다. 메일·PDF·크롤링이 문자열로 보낸 금액은 원천별 표기 규칙표대로 읽어 숫자로 돌려놓은 뒤에 견줍니다. 수집 원천 표는 공개된 선사 요율표 양식과 EDI 운임 메시지 규격을 보고 지원자가 직접 만들어 넣습니다.
하루치 수집분인 운임 1,286줄에 프라이싱 담당이 손으로 매긴 정답 판정을 붙여 자동 판정과 대조해 사유별 일치율과 어긋난 줄의 목록을 내고, 수집과 대조를 AWS 배치로 올려 아침마다 화면이 새로 차게 하는 단계입니다.
선사가 보내온 메일 본문과 첨부 PDF 에서 요율 표를 뽑아 수집 원천 표의 열에 맞춰 채우고, 뽑은 값마다 원문 어디에서 왔는지를 달아 담당자가 바로 열어 보게 하며, 대조 결과를 다른 셀 에이전트가 물어볼 MCP 서버로 여는 단계입니다.
프라이싱 담당이 하루치 수집 원천 표와 표기 규칙표, 운임 원장, 노선표를 올리면 메일과 PDF 로 온 금액이 숫자로 돌아오고 어긋난 요율이 사유별로 묶여 화면에 나오는 과정을 시연합니다.
운임 1,286줄에 손으로 매긴 정답 판정을 붙여 대조하고 사유별 일치율을 냅니다. 단, 정답과 요율을 모두 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건 동작입니다.
깨진 수집분 30종으로 먼저 돌려 봅니다. 금액 표기를 읽을 수 없는 줄과 노선표에 없는 노선, 원장에 짝이 없는 요금 코드가 섞여도 화면이 서고, 견주지 못한 값은 사유로 세우지 않고 hedge 에 남습니다.
요율 값이 어긋났다고 볼 폭을 0달러에서 5달러로 올렸을 때 어긋남으로 걸리는 줄이 몇 개 줄어드는지 회귀로 확인합니다.
여기까지가 이 포트폴리오가 말할 수 있는 범위입니다. 위 수치는 제가 만든 요율을 제가 채점한 값이고, 견적 오차가 실제로 줄었는지는 포트로직스가 TOMS 로 받는 실 수집분과 실 프라이싱 판단을 넣어야 나옵니다. 그 측정을 수집분이 붙는 날 돌릴 수 있게 대조 규칙과 평가 러너까지 만들어 둡니다.
사유별 건수와 일치율은 제가 만든 수집분을 제가 채점한 값이라 성능을 증명하지 못합니다. 면접에서는 화면이 도는 범위와, 포트로직스 실 수집분이 붙으면 그대로 재볼 수 있다는 준비 상태를 말합니다.
원장을 만든 사람이 정답 판정도 붙였으니 일치율이 높은 것은 당연합니다. 금액을 협의 중이라고만 적어 보낸 줄과 무료로 실려 온 줄, 닫힌 노선의 요율까지 남겨 두어 짝이 잘 서는 줄만 대조하는 화면이 되지 않게 했습니다.
이 포트폴리오는 여러 원천의 요율을 키로 짝지어 금액과 기간과 통화를 견주는 기술을 보여줍니다. 해상운임 시황이나 선사 계약 구조 전문성은 주장하지 않습니다. 판정은 짝짓기와 뺄셈과 날짜 비교가 하고 모델은 목록에 뜨는 문장만 맡습니다.
통화가 다른 항목은 환율을 붙여야 금액을 견줄 수 있는데 어느 날짜 환율을 쓸지는 회사가 정하는 값이라, 이 도구는 환산하지 않고 통화가 다르다는 사실만 사유로 냅니다.
실제 도입 때는 선사마다 요금 코드와 부대비 항목이 계속 늘어나므로, 코드 목록과 노선표를 프라이싱팀과 이어서 채우는 일을 운영 과제로 둡니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
선사와 파트너가 API·EDI·메일·PDF·크롤링으로 보내온 하루치 요율 줄입니다. 수집 번호와 원천 종류, 선사 코드, 노선, 컨테이너 규격, 요금 코드, 금액, 원문 금액 표기, 통화, 유효기간, 받은 시각을 한 줄에 둡니다. API 와 EDI 는 금액을 숫자 필드로 보내지만 메일·PDF·크롤링은 사람이 읽으라고 쓴 문자열로 보내므로, 그 줄은 금액 칸이 비어 오고 원문 표기만 들어옵니다. 지원자는 공개된 선사 요율표 양식과 EDI 운임 메시지 규격을 보고 이 표를 스스로 만듭니다. 금액을 협의 중이라고만 적어 보낸 줄과 무료로 실려 FREE 라고 적힌 줄, 유효기간이 이미 끝난 줄, 같은 항목을 두 원천이 다른 금액으로 보내온 짝, 그리고 선사·노선·요금 코드는 같은데 컨테이너 규격만 다른 짝을 일부러 섞어 판정이 갈리게 둡니다.
| rate_no | source_type | carrier_code | lane | container_type | charge_code | amount | currency | valid_from | valid_until | received_at | raw_amount_text |
|---|---|---|---|---|---|---|---|---|---|---|---|
| SR-2026-0401 | 메일 | MAEU | KRPUS-NLRTM | 40HC | OFR | — | USD | 2026-09-01 | 2026-10-31 | 2026-09-08T08:12:00 | USD 2,150.00 |
| SR-2026-0402 | EDI | ONEY | KRINC-USLAX | 20GP | BAF | 180 | USD | 2026-07-01 | 2026-08-31 | 2026-09-08T07:40:00 | — |
| SR-2026-0403 | HLCU | KRPUS-VNSGN | 40GP | THC | — | USD | 2026-09-01 | 2026-10-31 | 2026-09-08T09:05:00 | USD128.00 | |
| SR-2026-0404 | API | CMDU | KRPUS-SGSIN | 40HC | OFR | 1,980 | USD | 2026-09-01 | 2026-10-31 | 2026-09-08T06:30:00 | — |
| SR-2026-0405 | 메일 | CMDU | KRPUS-SGSIN | 40HC | OFR | — | USD | 2026-09-01 | 2026-10-31 | 2026-09-08T10:15:00 | USD 2,120.00 |
아래 JSON Schema 를 그대로 만족하는 수집 요율 행을 800개 더 만들어 주세요. 선사 코드는 MAEU·ONEY·HLCU·CMDU·MSCU 다섯 개를 쓰고 노선은 노선표에 있는 것에서 고르되 노선표에 없는 노선도 스무 줄쯤 넣습니다. source_type 은 다섯 종류를 고르게 흩고, charge_code 는 OFR 을 절반쯤 두고 나머지를 BAF·THC·DOC·CAF 로 나눕니다. API 와 EDI 로 들어오는 줄은 amount 에 숫자를 채우고 raw_amount_text 를 비웁니다. 반대로 메일·PDF·크롤링 줄은 amount 를 비우고 raw_amount_text 에만 금액을 적되, 표기 규칙표에 있는 원천별 방식대로 씁니다. 곧 통화 기호를 앞이나 뒤에 붙이고, 천 단위와 소수 구분을 원천마다 다르게 쓰고, 규격 꼬리표를 슬래시 뒤에 달고, 무료거나 금액이 안 적힌 줄은 FREE·요율 협의 같은 말로 적습니다. 숫자 자체는 해상운임이면 400 에서 3000 사이 달러, 부대비면 30 에서 400 사이 달러로 두되 원화로 적힌 줄은 100000 에서 300000 사이로 둡니다. valid_from 과 valid_until 은 한 달에서 석 달 사이 구간으로 두고 received_at 은 2026년 9월 8일 앞뒤로 흩습니다. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: 금액이 비어 있는 줄, 금액이 0 인 줄, 받은 날이 유효기간 밖인 줄, 같은 선사·노선·요금 코드를 두 원천이 다른 금액으로 보낸 짝, 원장에 짝이 없는 요금 코드. 형식을 깨뜨리는 시도 10건은 수집분에 섞지 않고 따로 둔 파일로 넣어, 그 줄만 이슈로 서고 나머지 사유 묶음은 살아 있는지 봅니다.
{"type": "object", "properties": {"rate_no": {"type": "string"}, "source_type": {"type": "string", "enum": ["API", "EDI", "메일", "PDF", "크롤링"]}, "carrier_code": {"type": "string"}, "lane": {"type": "string"}, "container_type": {"type": "string", "enum": ["20GP", "40GP", "40HC"]}, "charge_code": {"type": "string", "enum": ["OFR", "BAF", "THC", "DOC", "CAF"]}, "amount": {"type": ["number", "null"], "minimum": 0}, "raw_amount_text": {"type": ["string", "null"], "description": "메일·PDF·크롤링이 보낸 금액 표기 원문입니다. API 와 EDI 는 금액을 숫자 필드로 보내므로 비어 있습니다."}, "currency": {"type": "string", "enum": ["USD", "KRW", "EUR"]}, "valid_from": {"type": "string"}, "valid_until": {"type": "string"}, "received_at": {"type": "string"}}, "required": ["rate_no", "source_type", "carrier_code", "lane", "container_type", "charge_code", "amount", "raw_amount_text", "currency", "valid_from", "valid_until", "received_at"]}{"type": "object", "properties": {"rate_no": {"type": "string"}, "source_type": {"type": "string", "enum": ["API", "EDI", "메일", "PDF", "크롤링"]}, "carrier_code": {"type": "string"}, "lane": {"type": "string"}, "container_type": {"type": "string", "enum": ["20GP", "40GP", "40HC"]}, "charge_code": {"type": "string", "enum": ["OFR", "BAF", "THC", "DOC", "CAF"]}, "amount": {"type": ["number", "null"], "minimum": 0}, "raw_amount_text": {"type": ["string", "null"], "description": "메일·PDF·크롤링이 보낸 금액 표기 원문입니다. API 와 EDI 는 금액을 숫자 필드로 보내므로 비어 있습니다."}, "currency": {"type": "string", "enum": ["USD", "KRW", "EUR"]}, "valid_from": {"type": "string"}, "valid_until": {"type": "string"}, "received_at": {"type": "string"}}, "required": ["rate_no", "source_type", "carrier_code", "lane", "container_type", "charge_code", "amount", "raw_amount_text", "currency", "valid_from", "valid_until", "received_at"]}원천마다 금액을 어떻게 적어 보내는지 모아 둔 표기 규칙표입니다. 규칙 번호와 원천 종류, 선사 코드, 금액 앞뒤에 붙는 통화 표기, 천 단위 기호, 소수 구분 기호, 무료로 실렸다는 말, 금액이 안 정해졌다는 말을 한 줄에 둡니다. 선사 코드가 정확히 같은 줄을 먼저 찾고 없으면 별표 줄을 씁니다. 지원자는 선사가 공개한 요율표 PDF 와 EDI IFTMIN·IFCSUM 운임 메시지 예제, 포워딩 커뮤니티에 올라온 선사 통보 메일 견본을 열 곳쯤 모아 금액이 적힌 자리를 옮겨 적으며 이 표를 만듭니다. API 와 EDI 는 금액이 숫자 필드로 오므로 기호 칸을 비워 두어 파싱 자체를 건너뛰게 합니다.
| format_no | source_type | carrier_code | currency_marks | thousands_sep | decimal_sep | zero_tokens | null_tokens |
|---|---|---|---|---|---|---|---|
| FMT-01 | 메일 | * | USD|US$|$ | , | . | FREE|NIL|무료 | 요율 협의|별도 협의|TBA |
| FMT-02 | 메일 | MAEU | USD|US$ | , | . | FREE|NIL | 요율 협의|TBA |
| FMT-03 | 메일 | CMDU | USD|EUR|€ | , | . | FREE|GRATIS | TBA|별도 협의 |
| FMT-04 | * | USD|$ | , | . | FREE|NIL | 요율 협의|TBA|별도 협의 | |
| FMT-05 | HLCU | USD|EUR | , | . | FREE | 요율 협의|TBA |
아래 JSON Schema 를 그대로 만족하는 표기 규칙 행을 20개 더 만들어 주세요. 원천 종류는 메일·PDF·크롤링 세 갈래만 늘리고 API 와 EDI 는 기호 칸을 빈 문자열로 둡니다. carrier_code 는 대부분 별표로 두되 선사마다 다른 규칙을 쓰는 줄을 대여섯 개 넣습니다. thousands_sep 와 decimal_sep 는 쉼표와 마침표를 서로 바꿔 쓰는 유럽식 줄을 서너 개 섞습니다. currency_marks 와 zero_tokens, null_tokens 는 세로줄로 이어 적고, 같은 뜻을 다른 말로 적은 표기를 여럿 넣어 무료와 미정이 갈리는 경우가 늘어나게 합니다.
{"type": "object", "properties": {"format_no": {"type": "string"}, "source_type": {"type": "string", "enum": ["API", "EDI", "메일", "PDF", "크롤링"]}, "carrier_code": {"type": "string"}, "currency_marks": {"type": "string"}, "thousands_sep": {"type": "string"}, "decimal_sep": {"type": "string"}, "zero_tokens": {"type": "string"}, "null_tokens": {"type": "string"}}, "required": ["format_no", "source_type", "carrier_code", "currency_marks", "thousands_sep", "decimal_sep", "zero_tokens", "null_tokens"]}{"type": "object", "properties": {"format_no": {"type": "string"}, "source_type": {"type": "string", "enum": ["API", "EDI", "메일", "PDF", "크롤링"]}, "carrier_code": {"type": "string"}, "currency_marks": {"type": "string"}, "thousands_sep": {"type": "string"}, "decimal_sep": {"type": "string"}, "zero_tokens": {"type": "string"}, "null_tokens": {"type": "string"}}, "required": ["format_no", "source_type", "carrier_code", "currency_marks", "thousands_sep", "decimal_sep", "zero_tokens", "null_tokens"]}사내 통합 운임 원장입니다. 원장 번호와 선사 코드, 노선, 컨테이너 규격, 요금 코드, 금액, 통화, 유효기간, 갱신 시각을 한 줄로 둡니다. 자동 견적 엔진이 값을 읽어 가는 표라 여기에 무엇이 올라 있는지가 견적 금액을 정합니다. 지원자는 수집 원천 표와 같은 열 구성으로 이 표를 만들되 갱신이 늦어 옛 값이 남은 줄과 통화가 원화로 잡힌 줄을 섞어 둡니다.
| ledger_no | carrier_code | lane | container_type | charge_code | amount | currency | valid_from | valid_until | updated_at |
|---|---|---|---|---|---|---|---|---|---|
| L-2026-0101 | MAEU | KRPUS-NLRTM | 40HC | OFR | 2,480 | USD | 2026-08-01 | 2026-09-30 | 2026-08-01T09:00:00 |
| L-2026-0102 | ONEY | KRINC-USLAX | 20GP | BAF | 180 | USD | 2026-07-01 | 2026-08-31 | 2026-07-01T09:00:00 |
| L-2026-0103 | HLCU | KRPUS-VNSGN | 40GP | THC | 165,000 | KRW | 2026-08-15 | 2026-10-15 | 2026-08-15T10:20:00 |
| L-2026-0104 | CMDU | KRPUS-SGSIN | 40HC | OFR | 1,980 | USD | 2026-09-01 | 2026-10-31 | 2026-09-01T08:40:00 |
| L-2026-0105 | MAEU | KRPUS-JPTYO | 20GP | OFR | 620 | USD | 2026-08-20 | 2026-10-20 | 2026-08-20T11:10:00 |
아래 JSON Schema 를 그대로 만족하는 원장 행을 400개 더 만들어 주세요. 선사 코드와 노선, 컨테이너 규격, 요금 코드 네 값의 짝이 원장 안에서 한 번씩만 나오게 합니다. amount 는 수집 요율과 같은 자릿수로 두되 오분의 일쯤은 수집 값과 다르게 두어 어긋남이 나오게 합니다. currency 는 대부분 달러로 두고 부대비 몇 줄을 원화로 둡니다. valid_until 이 이미 지난 줄을 스무 줄쯤 두고, updated_at 은 valid_from 과 같거나 그 뒤로 둡니다. 수집 원천 표에는 있는데 원장에는 없는 조합도 서른 줄쯤 남겨 짝이 안 서는 경우가 나오게 합니다.
{"type": "object", "properties": {"ledger_no": {"type": "string"}, "carrier_code": {"type": "string"}, "lane": {"type": "string"}, "container_type": {"type": "string", "enum": ["20GP", "40GP", "40HC"]}, "charge_code": {"type": "string", "enum": ["OFR", "BAF", "THC", "DOC", "CAF"]}, "amount": {"type": ["number", "null"], "minimum": 0}, "currency": {"type": "string", "enum": ["USD", "KRW", "EUR"]}, "valid_from": {"type": "string"}, "valid_until": {"type": "string"}, "updated_at": {"type": "string"}}, "required": ["ledger_no", "carrier_code", "lane", "container_type", "charge_code", "amount", "currency", "valid_from", "valid_until", "updated_at"]}{"type": "object", "properties": {"ledger_no": {"type": "string"}, "carrier_code": {"type": "string"}, "lane": {"type": "string"}, "container_type": {"type": "string", "enum": ["20GP", "40GP", "40HC"]}, "charge_code": {"type": "string", "enum": ["OFR", "BAF", "THC", "DOC", "CAF"]}, "amount": {"type": ["number", "null"], "minimum": 0}, "currency": {"type": "string", "enum": ["USD", "KRW", "EUR"]}, "valid_from": {"type": "string"}, "valid_until": {"type": "string"}, "updated_at": {"type": "string"}}, "required": ["ledger_no", "carrier_code", "lane", "container_type", "charge_code", "amount", "currency", "valid_from", "valid_until", "updated_at"]}회사가 서비스하는 노선표입니다. 노선 코드와 출발항, 도착항, 직항인지 환적인지, 그 노선이 지금 열려 있는지를 한 줄로 둡니다. 항구 코드는 공개된 UN/LOCODE 를 그대로 쓰므로 지원자가 실물과 같은 모양으로 만들 수 있습니다. 노선이 열려 있는지 여부가 이 표에만 있어야 닫힌 노선의 요율이 판정으로 도출됩니다.
| lane | origin_port | destination_port | service_level | active |
|---|---|---|---|---|
| KRPUS-NLRTM | KRPUS | NLRTM | 직항 | true |
| KRINC-USLAX | KRINC | USLAX | 직항 | true |
| KRPUS-VNSGN | KRPUS | VNSGN | 환적 | true |
| KRPUS-SGSIN | KRPUS | SGSIN | 직항 | true |
| KRPUS-JPTYO | KRPUS | JPTYO | 직항 | true |
아래 JSON Schema 를 그대로 만족하는 노선 행을 60개 더 만들어 주세요. 출발항은 KRPUS 와 KRINC 두 곳으로 두고 도착항은 공개된 UN/LOCODE 에서 고릅니다. lane 은 출발항과 도착항을 하이픈으로 이어 적습니다. service_level 은 직항을 삼분의 이쯤 두고 나머지를 환적으로 둡니다. active 는 대부분 참으로 두되 닫힌 노선을 대여섯 줄 넣어 그 노선의 요율이 어떻게 걸리는지 보게 합니다.
{"type": "object", "properties": {"lane": {"type": "string"}, "origin_port": {"type": "string"}, "destination_port": {"type": "string"}, "service_level": {"type": "string", "enum": ["직항", "환적"]}, "active": {"type": "boolean"}}, "required": ["lane", "origin_port", "destination_port", "service_level", "active"]}{"type": "object", "properties": {"lane": {"type": "string"}, "origin_port": {"type": "string"}, "destination_port": {"type": "string"}, "service_level": {"type": "string", "enum": ["직항", "환적"]}, "active": {"type": "boolean"}}, "required": ["lane", "origin_port", "destination_port", "service_level", "active"]}| Python | 메일·PDF·크롤링이 보낸 금액 표기를 규칙표대로 숫자로 돌려놓고, 네 값으로 원장 줄을 찾아 금액과 기간과 통화를 견주며 사유를 정하는 대조 엔진을 맡습니다. |
| TypeScript | 사유별로 묶은 목록과 요율 한 줄을 펼쳐 원장 값과 나란히 보는 상세 화면을 맡습니다. |
| AWS | 2주차부터 수집분 적재와 아침 배치를 AWS 에 올려 담당자가 출근했을 때 화면이 이미 차 있게 합니다. |
| LangChain | 3주차에 선사 메일 본문과 첨부 PDF 에서 요율 표를 뽑아 수집 원천 표의 열에 맞춰 채우는 추출 체인으로 씁니다. |
| LLM | 뽑아낸 값마다 원문의 어느 줄에서 왔는지 근거를 달아, 담당자가 숫자를 믿기 전에 원문을 열어 보게 합니다. |
| Claude | 어긋난 사유와 벌어진 금액을 담당자가 목록에서 한 줄로 읽을 문장으로 줄이는 데 씁니다. |
| MCP | 3주차에 대조 결과를 사내 시스템에 붙일 MCP 서버로 열어, 다른 셀의 에이전트가 원장에 올려도 되는 요율인지 물어보게 합니다. |
✗ fail → 숫자로 못 돌려놓은 줄이나 짝이 안 서는 줄이 절반을 넘으면 표기 규칙표와 요금 코드 목록부터 프라이싱팀과 맞춰 채웁니다.
✓ pass → 2주차 정답 대조와 아침 배치로 넘어갑니다.
✗ fail → 어긋난 줄을 모아 사유 우선순위와 유효기간을 견주는 기준 시각을 다시 봅니다.
✓ pass → 3주차 메일·PDF 추출과 MCP 공개로 넘어갑니다.
위 예측 UI 는 3주차까지 완주했을 때의 화면입니다. 1주차에 실제로 만드는 것은 아래 표시된 화면 하나입니다.
reconcile_verdict사유 라벨 · rate_no + 한 줄 요약(근거 수치 포함)화면·코드·면접에서 이 단어를 그대로 씁니다. 키는 출력 스키마의 enum 과 같습니다.
원장과 일치일치요율 값 어긋남금액 어긋남유효기간 지난 요율기간 지남원장에 없는 항목원장 짝 없음통화 단위 다름통화 다름원천끼리 서로 다름원천 충돌수집된 요율 한 줄마다 사내 원장과 어디가 어긋났는지 정합니다. 어긋났으면 금액·유효기간·원장 짝·통화 단위·원천 사이 차이 중 어느 쪽인지 싣고, 짝지은 원장 줄 번호와 벌어진 금액을 함께 냅니다. 메일·PDF·크롤링이 보낸 금액은 문자열로 오므로 숫자로 돌려놓은 값을 함께 싣습니다. 목록은 이 사유별로 갈라 세웁니다.
{"type": "object", "properties": {"verdict_no": {"type": "string"}, "rate_no": {"type": "string"}, "carrier_code": {"type": "string"}, "lane": {"type": "string"}, "charge_code": {"type": "string"}, "reconcile_verdict": {"type": "string", "enum": ["원장과 일치", "요율 값 어긋남", "유효기간 지난 요율", "원장에 없는 항목", "통화 단위 다름", "원천끼리 서로 다름"]}, "ledger_no": {"type": ["string", "null"], "description": "carrier_code·lane·container_type·charge_code 네 값이 모두 같은 원장 줄의 번호입니다. 짝이 없으면 비웁니다."}, "parsed_amount": {"type": ["number", "null"], "description": "source_rate.amount 를 그대로 쓰거나, 비어 있으면 raw_amount_text 를 표기 규칙표대로 읽어 채운 숫자입니다. 무료 표기는 0 이 되고 금액이 안 정해졌다는 말은 비워 둡니다."}, "amount_difference": {"type": ["number", "null"], "description": "parsed_amount 에서 짝지은 rate_ledger.amount 를 뺀 값입니다. 통화가 다르거나 한쪽 금액이 비어 있으면 뺄 수 없으므로 비웁니다."}, "evidence": {"type": "array", "items": {"type": "object", "properties": {"field": {"type": "string"}, "agg": {"type": ["string", "null"]}, "value": {}}, "required": ["field", "value"]}}, "summary": {"type": "string"}, "hedge": {"type": ["string", "null"]}}, "required": ["verdict_no", "rate_no", "carrier_code", "lane", "charge_code", "reconcile_verdict", "evidence", "summary"]}[
{
"verdict_no": "RC-001",
"rate_no": "SR-2026-0407",
"carrier_code": "MAEU",
"lane": "KRPUS-JPTYO",
"charge_code": "OFR",
"reconcile_verdict": "원장과 일치",
"ledger_no": "L-2026-0105",
"amount_difference": 0,
"evidence": [
{
"field": "raw_amount_text",
"agg": null,
"value": "USD 620.00 / 20GP"
},
{
"field": "ledger_no",
"agg": null,
"value": "L-2026-0105"
},
{
"field": "valid_until",
"agg": null,
"value": "2026-10-20"
}
],
"summary": "선사 메일이 보내온 620달러가 원장에 올라 있는 값과 같고 유효기간도 아직 남아 프라이싱 담당이 손댈 것이 없습니다.",
"hedge": null,
"parsed_amount": 620
},
{
"verdict_no": "RC-002",
"rate_no": "SR-2026-0408",
"carrier_code": "ONEY",
"lane": "KRPUS-CNSHA",
"charge_code": "OFR",
"reconcile_verdict": "원장과 일치",
"ledger_no": "L-2026-0106",
"amount_difference": 0,
"evidence": [
{
"field": "amount",
"agg": null,
"value": 740
},
{
"field": "ledger_no",
"agg": null,
"value": "L-2026-0106"
},
{
"field": "updated_at",
"agg": null,
"value": "2026-08-10T09:30:00"
}
],
"summary": "EDI 로 들어온 740달러가 지난달에 갱신된 원장 값과 같아 자동 견적 엔진이 그대로 써도 됩니다.",
"hedge": null,
"parsed_amount": 740
},
{
"verdict_no": "RC-003",
"rate_no": "SR-2026-0401",
"carrier_code": "MAEU",
"lane": "KRPUS-NLRTM",
"charge_code": "OFR",
"reconcile_verdict": "요율 값 어긋남",
"ledger_no": "L-2026-0101",
"amount_difference": -330,
"evidence": [
{
"field": "raw_amount_text",
"agg": null,
"value": "USD 2,150.00"
},
{
"field": "amount",
"agg": null,
"value": 2480
},
{
"field": "ledger_no",
"agg": null,
"value": "L-2026-0101"
}
],
"summary": "선사 메일 본문에 USD 2,150.00 으로 적혀 온 부산발 로테르담 40HC 해상운임을 숫자로 돌려놓으니 2,150달러인데, 원장에는 2,480달러가 올라 있어 330달러가 벌어집니다.",
"hedge": "메일 본문에서 뽑은 값이라 첨부 요율표와 한 번 더 맞춰 볼 후보로 둡니다.",
"parsed_amount": 2150
},
{
"verdict_no": "RC-004",
"rate_no": "SR-2026-0402",
"carrier_code": "ONEY",
"lane": "KRINC-USLAX",
"charge_code": "BAF",
"reconcile_verdict": "유효기간 지난 요율",
"ledger_no": "L-2026-0102",
"amount_difference": 0,
"evidence": [
{
"field": "received_at",
"agg": null,
"value": "2026-09-08T07:40:00"
},
{
"field": "valid_until",
"agg": null,
"value": "2026-08-31"
}
],
"summary": "금액은 원장과 같지만 유효기간이 8월 말에 끝난 요율이 9월 8일에 들어와 지금 견적에 쓰면 지난달 값으로 팝니다.",
"hedge": null,
"parsed_amount": 180
},
{
"verdict_no": "RC-005",
"rate_no": "SR-2026-0406",
"carrier_code": "MAEU",
"lane": "KRPUS-AEJEA",
"charge_code": "OFR",
"reconcile_verdict": "원장에 없는 항목",
"ledger_no": null,
"amount_difference": null,
"evidence": [
{
"field": "lane",
"agg": null,
"value": "KRPUS-AEJEA"
},
{
"field": "active",
"agg": null,
"value": false
}
],
"summary": "크롤링이 주워 온 부산발 제벨알리 요율인데 이 노선은 노선표에서 닫혀 있고 원장에도 짝이 없어 값을 견줄 자리가 없습니다.",
"hedge": "노선이 다시 열린 것인지 크롤링이 옛 페이지를 읽은 것인지는 영업팀에 물어야 갈라집니다.",
"parsed_amount": 1740
},
{
"verdict_no": "RC-006",
"rate_no": "SR-2026-0403",
"carrier_code": "HLCU",
"lane": "KRPUS-VNSGN",
"charge_code": "THC",
"reconcile_verdict": "통화 단위 다름",
"ledger_no": "L-2026-0103",
"amount_difference": null,
"evidence": [
{
"field": "currency",
"agg": null,
"value": "USD"
},
{
"field": "currency",
"agg": null,
"value": "KRW"
},
{
"field": "ledger_no",
"agg": null,
"value": "L-2026-0103"
}
],
"summary": "PDF 요율표는 달러로 적혀 있는데 원장의 같은 항목은 원화로 잡혀 있어 두 값을 그대로 빼면 뜻이 없습니다.",
"hedge": "환율을 붙여 견주는 일은 어느 날짜 환율을 쓸지 프라이싱팀이 정해야 해서 판정에 넣지 않았습니다.",
"parsed_amount": 128
},
{
"verdict_no": "RC-007",
"rate_no": "SR-2026-0405",
"carrier_code": "CMDU",
"lane": "KRPUS-SGSIN",
"charge_code": "OFR",
"reconcile_verdict": "원천끼리 서로 다름",
"ledger_no": "L-2026-0104",
"amount_difference": 140,
"evidence": [
{
"field": "raw_amount_text",
"agg": null,
"value": "USD 2,120.00"
},
{
"field": "amount",
"agg": null,
"value": 1980
},
{
"field": "source_type",
"agg": null,
"value": "API"
},
{
"field": "received_at",
"agg": null,
"value": "2026-09-08T10:15:00"
}
],
"summary": "같은 부산발 싱가포르 40HC 해상운임을 선사 API 는 1,980달러로, 같은 날 온 메일은 2,120달러로 보내와 어느 쪽을 원장에 올릴지 정해야 합니다.",
"hedge": "늦게 받은 메일을 위에 올렸지만 API 가 계약 요율이고 메일이 스팟일 수 있어 사람이 한 번 봅니다.",
"parsed_amount": 2120
},
{
"verdict_no": "RC-008",
"rate_no": "SR-2026-0409",
"carrier_code": "HLCU",
"lane": "KRINC-DEHAM",
"charge_code": "OFR",
"reconcile_verdict": "유효기간 지난 요율",
"ledger_no": "L-2026-0107",
"amount_difference": null,
"evidence": [
{
"field": "received_at",
"agg": null,
"value": "2026-09-08T09:40:00"
},
{
"field": "valid_until",
"agg": null,
"value": "2026-08-20"
},
{
"field": "raw_amount_text",
"agg": null,
"value": "요율 협의"
}
],
"summary": "인천발 함부르크 요율표가 8월 20일에 끝난 기간으로 들어와 지금 원장에 얹을 수 없는 줄입니다.",
"hedge": "금액 칸에 요율 협의라고만 적혀 와 숫자로 돌려놓지 못했습니다. 값 비교는 건너뛰고 기간만으로 사유를 세웠습니다.",
"parsed_amount": null
},
{
"verdict_no": "RC-009",
"rate_no": "SR-2026-0415",
"carrier_code": "MAEU",
"lane": "KRPUS-NLRTM",
"charge_code": "OFR",
"reconcile_verdict": "원장과 일치",
"ledger_no": "L-2026-0113",
"parsed_amount": 1180,
"amount_difference": 0,
"evidence": [
{
"field": "container_type",
"agg": null,
"value": "20GP"
},
{
"field": "amount",
"agg": null,
"value": 1180
},
{
"field": "ledger_no",
"agg": null,
"value": "L-2026-0113"
}
],
"summary": "같은 선사와 노선, 같은 해상운임 코드라도 20GP 는 40HC 와 다른 항목이라 원장에서도 따로 서고, 그 줄의 1,180달러와 값이 같습니다.",
"hedge": "규격을 빼고 짝을 찾으면 이 줄이 40HC 요율과 한 묶음이 되어 원천 충돌로 잘못 걸리므로 네 값을 모두 씁니다."
}
][자동 검증 · 코드가 판정합니다] 1. reconcile_verdict 가 enum 여섯 값 중 하나인지 확인합니다. 2. verdict_no·rate_no·carrier_code·lane·charge_code·reconcile_verdict·evidence·summary 가 모두 채워졌는지 확인합니다. 3. rate_no 가 수집 원천 표에 실재하는 번호인지, ledger_no 가 원장에 실재하는 번호인지 대조합니다. 3-1. amount 가 비어 있고 raw_amount_text 가 차 있는 줄은 먼저 금액을 숫자로 돌려놓습니다. 표기 규칙표에서 source_type 이 같고 carrier_code 가 정확히 같은 줄을 찾고 없으면 carrier_code 가 별표인 줄을 씁니다. 원문에서 앞뒤 공백을 지우고 대문자로 접은 뒤, null_tokens 중 하나와 같으면 금액을 비운 채로 두고, zero_tokens 중 하나와 같으면 0 으로 둡니다. 그 밖에는 슬래시 뒤에 붙은 규격 꼬리표를 떼고 currency_marks 에 적힌 통화 표기를 긴 것부터 차례로 지운 다음, thousands_sep 를 지우고 decimal_sep 를 마침표로 바꿔 숫자로 읽습니다. 숫자가 한 자리도 남지 않으면 금액을 비웁니다. 아래 계산은 모두 이렇게 채운 금액으로 합니다. 4. lane 이 노선표에 없거나 active 가 거짓이고 carrier_code·lane·container_type·charge_code 네 값이 모두 같은 원장 줄도 없으면 reconcile_verdict 가 원장에 없는 항목인지 확인합니다. 5. source_rate.currency 가 짝지은 rate_ledger.currency 와 다르면 reconcile_verdict 가 통화 단위 다름인지 확인하고, 그때 amount_difference 는 비어 있는지 확인합니다. 6. received_at 이 그 줄의 valid_from 과 valid_until 사이를 벗어나거나 짝지은 원장 줄의 valid_until 보다 뒤이면 reconcile_verdict 가 유효기간 지난 요율인지 확인합니다. 7. carrier_code·lane·container_type·charge_code 네 값이 모두 같은데 source_type 이 다른 두 줄의 amount 가 서로 다르면 두 줄 모두 reconcile_verdict 가 원천끼리 서로 다름인지 확인하고, received_at 이 늦은 줄을 목록 위에 올립니다. 규격을 빼고 세 값으로만 묶으면 같은 선사·노선·요금 코드의 20GP 와 40HC 가 한 묶음이 되어 값이 다른 것이 당연한데도 충돌로 잡히므로, 4번·8번과 똑같이 네 값을 씁니다. 8. amount_difference 를 source_rate.amount 에서 짝지은 rate_ledger.amount 를 빼 다시 계산하고, 0 이 아니면 reconcile_verdict 가 요율 값 어긋남인지 확인합니다. 다만 통화가 다르거나 한쪽 금액이 비어 있으면 이 칸은 비우고 값 비교를 건너뜁니다. 9. reconcile_verdict 가 원장과 일치이면 위 다섯 조건 어디에도 안 걸리는지 다시 확인하고, 사유가 둘 이상 걸리면 원장에 없는 항목·통화 단위 다름·유효기간 지난 요율·원천끼리 서로 다름·요율 값 어긋남 순으로 앞선 것을 세웁니다. 10. evidence 의 field 이름이 수집 원천 표·운임 원장·노선표에 실재하는 컬럼인지 대조합니다. 11. agg 가 없는 evidence 의 value 가 그 컬럼에 수록된 행 값과 같은지 확인합니다. 12. 원문 표기를 숫자로 돌려놓지 못했거나 원장에 짝이 없으면 그 사실이 hedge 에 적혔는지 확인합니다. 13. summary 가 존댓말로 끝나는지 확인합니다. [평가 러너 · 2주차] 하루치 수집분인 운임 1,286줄에 프라이싱 담당이 손으로 매긴 정답 판정을 붙여 자동 판정과 대조하고, 사유별 일치율과 어긋난 줄의 목록을 냅니다. [수동 검증 · 사람이 봅니다] 1. 원천끼리 값이 갈릴 때 어느 쪽을 원장에 올릴지는 프라이싱 담당이 목록을 보고 정합니다. 2. 통화가 다른 항목에 어느 날짜 환율을 붙일지는 프라이싱팀과 정한 뒤 규칙에 넣습니다.