국가가 맺은 협정을, 개인의 체류조건에 맞춘 권리로 바꿉니다. 해외로 나갈 때도, 한국으로 들어올 때도.
체류 국가·목적·고용형태·기간을 입력하면 외교부 공공데이터 기반의 검수된 규칙으로 받을 수 있는 협정 권리와 지켜야 할 행정 기한을 판정하고, 실행 일정으로 관리합니다.
2026 외교 공공데이터·AI 활용 경진대회 · 제품 또는 서비스 개발 부문 출품작
배포 https://pact-app-lemon.vercel.app · 검증 방법 /verification · 기계 판독 상태 /api/health
같은 검증된 판정 엔진을 세 갈래로 씁니다. 코어(src/lib/rules/engine.ts)는 하나이고, 위 계층만 갈라집니다.
- 개인 ·
/app— 조건을 입력하면 내 권리·기한을 찾아, 내가 할 일 / 회사에 요청할 일 / 공식기관 확인으로 나눠 안내합니다. 파견 근로자에게는 회사에 보낼 요청서까지 만들어 줍니다. - 양방향 — 한·독 협정 제7조는 방향 중립입니다(일방체약당사국 ↔ 타방체약당사국). 한국인이 독일로 갈 때와 독일인이 한국으로 올 때가 같은 원문·같은 엔진으로 대칭 판정됩니다. 새 국가를 늘리지 않고 하나의 공공데이터가 두 시장에 작동합니다.
- 기관 ·
/org— 개인에게 권리를 안내하는 같은 엔진으로, HR·대학 국제처가 구성원의 적용 가능성과 준비 현황을 한 화면에서 봅니다.
무엇을 하는지보다 이쪽이 더 중요합니다.
| 하지 않는 것 | 이유 |
|---|---|
| LLM이 권리 적용 여부를 판정하지 않는다 | 판정은 결정적 규칙 엔진만 수행합니다. AI는 조약 원문에서 규칙 초안을 뽑는 단계에만 쓰이고, 그 결과는 사람이 검수해야 배포됩니다. |
| 근거 없는 카드를 렌더링하지 않는다 | 모든 조건에는 basis(원문 인용 또는 공식 출처)가 있어야 합니다. 없으면 런타임에 예외를 던집니다. |
| 검수 안 된 규칙을 배포하지 않는다 | reviewedBy 서명이 없으면 배포 게이트가 차단합니다. DB 제약으로도 막습니다. |
| 판정을 단정하지 않는다 | 단정 표현은 CI에서 검사해 차단합니다. |
| 체류조건을 서버로 보내지 않는다 | 판정은 브라우저에서 실행됩니다. 서버는 어떤 규칙을 쓸지만 배포합니다. |
정직하게 적습니다. 과장하면 이 프로젝트가 지켜 온 원칙이 무너집니다.
- 국가: 독일 1개국. 규칙 5개 — 아웃바운드 4개(사회보장협정 파견 · 입국·체류 · 운전면허 · 문서인증) + 인바운드 1개(독일→한국 국민연금 적용 제외). 인바운드는 같은 협정 원문·같은 스팬을 방향만 바꿔 재사용합니다.
- 검수 상태: 제안자 자체 원문 대조. 제3자 독립 검수는 아직 없으며, 그래서 모든 규칙이
prototype채널에 머물러 있습니다. 화면에도 그렇게 표시됩니다. - 운전면허: 한·독 간 상호인정 협정이 없습니다. 데이터에 없는 것을 있는 척하지 않고, 해당 카드를 강등해 공식기관 확인으로 안내합니다.
- 인바운드 외국인용 다국어·전체 항목은 준비 중. 지금은 "같은 엔진이 방향을 바꿔 작동한다"는 대칭 판정까지 보여줍니다.
발표와 화면에 쓰는 숫자는 전부 저장소 안의 데이터에서 재현됩니다.
| 항목 | 값 | 재현 방법 |
|---|---|---|
| 외교부 양자조약 | 2,829건 / 227개국·기구 | public/data/bilateral_treaties.csv |
| 독일 관련 조약 | 124건 | 같은 CSV, 체결대상국가 필터 |
| 한·독 사회보장협정 | 조약 1613호 · 발효 2003-01-01 | 같은 CSV |
| 협정 제7조 파견 기간 | 24개월 (방향 중립) | src/data/sources/kr-de-ssa-art7.txt 원문 |
| 사회보장협정 체결국 | 외교부 공식 43개국 중 41개국을 조약 원문 수준으로 대조 완료 | 조약 데이터 수록 기준일 차이 |
| 판정 전수 대조 | 입력 60,480조합 × 규칙 전체 · 불일치 0건 | npm test |
이 전수 대조가 보증하는 것은 구현 일관성(같은 규칙이 어디서 실행돼도 같은 판정)이지, 규칙의 법적 타당성이 아닙니다. 법적 타당성은 원문 대조와 사람 검수로 별도 확인합니다.
npm run verify순서대로 실행합니다.
typecheck— 타입 검사lint:forbidden— 사용자 화면 문구에 단정 표현이 있는가test— 규칙 엔진 전수 동치. 60,480개 입력 조합을 경진대회 제출본의 참조 구현과 대조해 판정이 하나라도 다르면 실패합니다. 샘플링이 아니라 전수입니다.lint— ESLintbuild— 프로덕션 빌드lint:typography— 한글이 고정폭 서체에 얹혀 있지 않은가
추가로 node scripts/verify-all.mjs 가 공공데이터 재현 · 접근성 대비 · 원문 변경 감지(음성 대조군 포함) · 회귀를 한 번에 돌립니다.
test/reference/engine.reference.mjs 는 제출본에서 가져온 동결 사본입니다.
프론트엔드와 백엔드를 아무리 바꿔도 이 테스트가 판정 로직이 제출본과 동일함을 계속 보증합니다.
판정 규칙이 어떻게 만들어지는지가 저장소 안에 있습니다. 본체는 tools/rights-compiler.mjs —
협정 원문(SHA-256 고정) → LLM 초안 → 스키마·스팬 검증(인용이 원문 [start,end) 구간에
실제로 존재하는지 기계 대조) → 검수 서명 게이트를 한 번에 수행하고, reviewedBy 서명이
없으면 exit 1로 종료합니다. "사람 검수 없이는 배포 불가"는 문서의 주장이 아니라 프로세스 종료 코드입니다.
node tools/rights-compiler.mjs --provider replay # 네트워크 0으로 전 과정 재현 (기권·스팬검증·차단까지)
node tools/consistency.mjs --provider replay # K회 자기일관성 하니스- 불확실하면 기권합니다 — K회 독립 호출의 합의율이 임계값에 못 미치는 항목은 판정하지 않고
공식 확인으로 강등합니다. 실측 결과:
out/consistency.json(provider: anthropic). - 평가 세트
eval/gold.json· 교란 대조군fixtures/· 원문 변경 감지tools/drift.mjs· 버전 간 판정 difftools/regression.mjs. - 오픈API 수집 증빙:
public/data/api/스냅샷 25종 +_fetch-log.json(수집 일시·엔드포인트 기록).
전체 데이터 흐름·프라이버시 설계는 docs/architecture 참조.
src/
lib/rules/
engine.ts 결정적 판정 엔진 — 이 경로에 LLM 호출이 존재하지 않는다
types.ts 규칙 데이터 모델 (direction·homeCountry·hostCountry 포함)
validate.ts 런타임 검증 — 근거 없는 규칙은 여기서 막힌다
load.ts 번들 규칙 + 서버 배포본 병합 (수신 규칙은 3단계 무결성 검증)
digest.ts 규칙 내용 다이제스트 — 정본 JSON SHA-256, 변조 감지
space.ts 전수 대조 입력공간 (60,480 조합)
lib/nl/ 자연어 → 체류조건 구조화 (기기 내 결정적 파서 · 필드별 근거 스팬)
lib/db/
schema.sql Postgres 스키마 — PII 컬럼이 하나도 없다
client.ts Supabase 클라이언트 (없어도 앱은 동작한다)
data/rules/ 규칙 JSON — 코드가 아니라 데이터 (아웃바운드 + 인바운드)
data/sources/ 조약 원문 + sha256
components/
app/ 개인 앱 화면 (홈·폼·스캔·결과·상세·지갑·일정)
org/ 기관 대시보드 (같은 엔진 재사용)
landing/ 랜딩
app/ Next.js App Router — (app)/ · admin/(검수 콘솔) · api/ · org/
public/data/ 공공데이터 스냅샷 (api/ 오픈API 25종 + 수집 로그)
scripts/ 검증 도구
tools/ 규칙 생산 파이프라인 (rights-compiler·자기일관성·회귀·변경감지·대조군)
eval/ 평가 세트 (gold.json) · fixtures/ 교란 대조군
docs/architecture/ 아키텍처 문서 — 데이터 흐름·규칙 OTA·AI 사용 지도·프라이버시 설계
규칙은 코드가 아니라 데이터입니다. 그래서 새 국가·새 방향 추가는 JSON 배포이지 코드 변경이 아니고, 버전 간 판정 차이를 기계적으로 diff 할 수 있습니다.
npm install
npm run dev환경변수는 전부 선택 사항입니다 (.env.example 참조).
아무것도 설정하지 않아도 앱은 번들된 규칙으로 완전히 동작합니다 — 이것은 폴백이 아니라 설계입니다.
| 변수 | 없으면 |
|---|---|
NEXT_PUBLIC_SUPABASE_* |
번들 규칙만 사용 |
ADMIN_TOKEN |
/admin 이 읽기전용으로 잠김 |
ANTHROPIC_API_KEY |
규칙 초안 생성만 불가 (판정에는 무관) |
이 서비스는 법률·세무 자문이 아닙니다. 판정 결과는 참고용이며, 최종 확인은 각 카드에 표시된 공식기관(국민연금공단·주한독일대사관 등)에서 받아야 합니다.
공공데이터 출처: 외교부(공공데이터포털), 국민연금공단, 국가법령정보센터.