尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证브라우저 전용 인쇄 전 검수 웹
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗인쇄소에 PDF를 넘기기 전에 스스로 검수해 보는 웹앱입니다. 폰트가 빠졌는지, 도련이 모자라지 않는지, 이미지 해상도가 버티는지, 고른 종이에 찍으면 색이 얼마나 달라지는지를 미리 보여 줍니다.
| 바로 검사 | 에이전트 검사(A2A) | |
|---|---|---|
| 계산하는 곳 | 이 브라우저 안 | 에이전트 9개(기본 127.0.0.1:8700~8708) |
| 어디로도 보내지 않음 | 에이전트에 올라감 | |
| 가이드 검색 | 브라우저가 모델을 받아 직접 | guide 에이전트가 대신 |
| 볼 수 있는 것 | 검수 결과 | 결과 + 누가 언제 무엇을 했는지(의뢰 추적·소통 기록·안전 관문 결정) |
| 필요한 것 | 없음 | 에이전트를 켜 둬야 함 |
에이전트를 켜지 않아도 앱은 바로 검사 모드로 전부 동작합니다. 주소 없이 열면(/) 에이전트 검사가 기본이고, /?mode=direct가 바로 검사입니다.
로그인은 선택입니다. 하지 않아도 검수는 전부 되고, 그때 기록은 그 브라우저에만 남습니다. 헤더 오른쪽에서 구글로 로그인하면 그때까지 한 검수가 계정으로 옮겨 가고, 다른 기기에서도 이어서 보입니다.
| 에이전트 | 포트 | 하는 일 | 런타임 |
|---|---|---|---|
| 총괄 orchestrator | 8700 | 의뢰를 받아 나눠 보내고 결과를 모읍니다. 바깥에 열리는 창구는 여기 하나뿐입니다 | Python |
| 안전 관문 safety | 8701 | 행동 등급(읽기/A/B/C)을 보고 허가합니다. 막히면 막힌 채로 둡니다(fail-closed) | Python |
| 사전 검사 preflight | 8702 | PDF 구조 검사 | Node |
| 색 color | 8703 | 인쇄 색 차이 예측 | Node |
| 인쇄 가이드 guide | 8704 | 가이드 원문 검색 | Python |
| 종이·위험도 paper | 8705 | 종이 추천, 불량 위험 점검 | Node |
| 교정 proofread | 8706 | 오탈자 수정 제안 | Python |
| 보고서 report | 8708 | 검수 보고서 작성 | Python |
| 원본 수정 designcraft | 8709 | 편집 파일(IDML)을 열어 교정을 반영하고 PDF로 내보냅니다 | Python + DesignCraft MCP |
frontend/ Next.js 16 앱 (app/ 화면, lib/ 계산, agents/ Node 에이전트, scripts/ 검증, public/ 데이터)
agents/ 에이전트 9종(A2A)과 MCP 서버 — 에이전트 검사 모드의 뒷단
eval/ 평가·데이터 생성(Python): 검색 모델 비교, 색 엔진 대조, 종이·인쇄소 수집
deploy/ 배포용(에이전트 컨테이너, ICC 내려받기 스크립트)
samples/ 시험용 PDF
# 파이썬과 Node를 한 환경에 둡니다(Node 에이전트도 이 node로 돕니다)
conda create -y -n dev python=3.12 nodejs=22
conda activate dev
pip install -r agents/requirements.txt
cd frontend && npm install # tsx 포함(Node 에이전트 실행용)
그다음 저장소에 없는 파일(모델·wasm·ICC 프로파일)을 채웁니다. 아래 같은 이름의 절을 보세요.
설치는 끝났고 꺼진 것을 되살리기만 하면 되는 상황이라면 RUN.md로 가세요 — 켜는 명령과 증상별(502·530) 판별표만 모아 둔 짧은 문서입니다.
먼저 conda activate dev를 합니다. run_agents.py는 자기를 실행한 파이썬으로 자식 에이전트를 띄우기 때문에, 환경을 켜지 않고 python을 치면 패키지가 없는 시스템 파이썬이 잡혀 파이썬 에이전트 6개가 전부 코드 1로 죽습니다(로그에는 ModuleNotFoundError: No module named 'uvicorn'). Node 에이전트 3개는 그대로 떠 있어서 절반만 죽은 것처럼 보입니다.
conda activate dev # 빼먹으면 에이전트가 안 뜹니다
# 1) 바로 검사만 — 에이전트 없이 브라우저 안에서 전부 계산합니다
cd frontend && npm run dev -- -H 127.0.0.1 -p 8752
# 2) 에이전트 검사까지 — 에이전트 9개를 켜고 앱에서 '에이전트 검사'를 고릅니다
python agents/run_agents.py # 로그는 agents/.data/logs/<이름>.log
cd frontend && npm run dev -- -H 127.0.0.1 -p 8752
conda activate가 안 먹는 터미널에서는 경로를 직접 줘도 됩니다.
"$HOME/miniforge3/envs/dev/python.exe" agents/run_agents.py # Windows
python agents/run_agents.py guide color처럼 이름을 적으면 일부만 켭니다. 끄는 것은 Ctrl+C 한 번이면 전부 내려갑니다.
공개 배포 구성으로 쓰는 경우, 에이전트와 터널은 한 쌍입니다. 둘 중 하나만 켜면 공개 사이트에서 에이전트가 안 보입니다. 둘은 각자 창을 붙잡고 있어서 한 창에서 같이 켤 수 없으므로 터미널 두 개에 각각 띄웁니다.
켜는 폴더가 둘이 다릅니다.
| 폴더 | 왜 | |
|---|---|---|
| 에이전트 | 저장소 루트 — 이 README가 있는 폴더 | agents/run_agents.py는 상대 경로다. 다른 데서 치면 can't open file이 난다 |
| 터널 | 아무 폴더에서나 | cloudflared는 현재 폴더를 보지 않는다. 터널 설정을 %USERPROFILE%\.cloudflared\config.yml에서 읽으므로 어디서 쳐도 같다 |
# 터미널 1 — 저장소 루트로 가서
cd <저장소를 클론한 폴더> # 예: cd ~/Documents/PrintGuard-AI
conda activate dev
python agents/run_agents.py
# 터미널 2 — 폴더는 상관없습니다
cloudflared tunnel run printguard
cloudflared: command not found가 나면 PATH에 없는 것입니다. 설치 폴더로 옮겨 가서 치거나(Windows 기본값 C:\Program Files (x86)\cloudflared) 실행 파일을 전체 경로로 부릅니다.
cd "/c/Program Files (x86)/cloudflared" # Git Bash
./cloudflared tunnel run printguard
증상으로 어느 쪽이 꺼졌는지 가릅니다.
| 증상 | 꺼진 것 |
|---|---|
curl http://127.0.0.1:8700/health가 응답 없음 | 에이전트 |
로컬은 되는데 https://pg.2taeyoon.com이 530 | 터널 — 아직 아무 터널도 붙지 않았다는 뜻 |
로컬도 응답이 없고 https://pg.2taeyoon.com이 502 | 에이전트 — 터널은 PC까지 닿았는데 8700이 대답을 안 한다 |
| 로컬도 터널도 되는데 화면만 안 붙음 | CORS(agents/.env의 PG_CORS_ORIGIN_REGEX) 확인 |
터널은 에이전트와 달리 수명을 길게 둘 수 있습니다. Windows 서비스로 등록하면 PC를 켤 때 알아서 뜨고, 창을 닫아도 안 죽습니다. 그 뒤로 손으로 켤 것은 에이전트 하나로 줄어듭니다 — 대개 꺼져 있는 쪽이 에이전트인 이유입니다.
관리자 권한 터미널에서 한 번만 합니다. 폴더는 상관없습니다.
cloudflared service install
터널 이름을 따로 줄 필요는 없습니다. 서비스가 %USERPROFILE%\.cloudflared\config.yml을 그대로 읽어 돕니다. 그래서 그 파일을 고쳤으면 서비스를 다시 시작해야 반영됩니다.
확인과 멈춤·되살리기는 서비스로 다룹니다(멈춤·되살리기·해제는 관리자 권한).
sc query cloudflared # RUNNING인지. 이름을 못 찾으면 sc query state= all | findstr -i cloudflared
net stop cloudflared # 멈춤
net start cloudflared # 되살리기
cloudflared service uninstall # 등록 해제
서비스가 돌고 있으면 cloudflared tunnel run을 따로 치지 마세요. 같은 터널에 두 프로세스가 붙어 요청이 둘로 갈립니다. 긴가민가하면 tasklist | findstr cloudflared로 먼저 셉니다.
테스트: python -m pytest agents -q (122개)
타입·린트·빌드: cd frontend && npx tsc --noEmit && npx eslint app lib && npm run build
밖의 LLM 클라이언트가 검수를 쓰게 합니다. 에이전트를 먼저 켭니다.
claude mcp add printguard -- "$(conda run -n dev python -c 'import sys;print(sys.executable)')" -m pg_agents.mcp_server
cwd는 agents/여야 합니다. 읽기 도구 7개와 쓰기 도구 1개(보고서 작성)를 내보냅니다. 쓰기 도구는 safety 관문을 거치고, 사람 승인(C 등급)은 MCP가 대신할 수 없습니다 — 웹 화면에서 사람이 승인합니다.
같은 PC라면 토큰이 필요 없습니다. MCP 클라이언트가 이 프로세스를 직접 띄우고(stdio), 서명 비밀 파일을 읽을 수 있다는 것이 곧 이 PC의 주인이라는 뜻이라, 오케스트레이터에 낼 토큰을 스스로 만듭니다.
MCP에는 구글 로그인이 필요 없습니다. 로그인 창을 띄울 브라우저가 없어서, 대신 같은 PC라는 사실이나 미리 발급한 토큰으로 주인을 가립니다.
다른 PC에서 터널을 넘어 붙일 때는 에이전트를 돌리는 PC에서 토큰을 발급해 옮깁니다.
cd agents
python -m pg_agents.mktoken --label claude-desktop --days 90 # 조회만
python -m pg_agents.mktoken --label cursor --days 30 --write # 보고서 작성까지
발급한 값은 다시 볼 수 없습니다(서버가 저장하지 않고 서명만 확인합니다). 한꺼번에 무효로 만들려면
agents/.data/auth_secret을 지우고 다시 켭니다. 토큰은 클라이언트의 PG_TOKEN에, 주소는
PG_ORCHESTRATOR_URL에 넣습니다.
MCP 서버 자체를 주소로 열 수도 있습니다(PG_MCP_TRANSPORT=streamable-http, PG_MCP_PUBLIC_URL 필수).
그때는 공개 주소에 놓이므로 인증 없이는 뜨지 않고, 받은 Bearer 토큰을 오케스트레이터에 그대로
넘깁니다 — 조회 전용 토큰이 중간에서 쓰기 권한을 얻는 일이 없게 합니다. 또 check_pdf(path=…)가
막히고 content_base64로 올려야 합니다: path는 '서버 PC의 파일'을 뜻해서, 멀리서 부르는 쪽이 남의
PC 파일을 고르는 길이 되기 때문입니다.
검수는 PDF로 하지만 고칠 수 있는 것은 원본뿐입니다. DesignCraft에서 PDF는 배치만 되고 글자를 집을 수 없습니다(editable vectors 미지원). 그래서 화면이 둘로 나뉩니다 — 인쇄 검수에서 교정 목록을 복사하고, 원본 수정에서 IDML에 얹습니다.
| 포맷 | 열기 | 돌려주기 |
|---|---|---|
.idml · .designcraft | O | O (같은 형식 + PDF) |
.indd · .indt | 받지 않습니다 | — INDD로 돌려줄 수 없어서입니다. IDML로 내보내 올립니다 |
.pdf | — | 받지 않습니다(고칠 수 없어서) |
IDML은 사진을 링크로만 들고 있습니다. 파일 하나만 올리면 인쇄용 사진이 따라오지 않아
끊긴 이미지 링크가 뜨고, 내보낸 PDF에서도 사진이 빠집니다. 화면에 보이는 그림은 IDML이
품고 있는 저해상 미리보기라 인쇄에는 못 씁니다.
InDesign에서 파일 → 패키지로 만든 폴더를 통째로 올리면 그대로 열립니다.
내 잡지 폴더/
magazine.idml
Links/ ← 사진. DesignCraft가 IDML 옆이나 이 폴더에서 찾는다
cover.jpg
Document fonts/ ← 글꼴. 있으면 대체 글꼴 문제도 사라진다
글자 교정만 하고 고친 IDML만 받으실 거면 파일 하나로도 충분합니다.
DesignCraft의 designcraft-cli가 에이전트를 돌리는 PC에
있어야 합니다. MCP는 stdin/stdout으로만 말해서 브라우저가 직접 부를 수 없고, 이 PC에서 프로세스를
띄워 파이프로 말하는 수밖에 없습니다(Claude 데스크톱이 하는 것과 같습니다).
릴리스의 Windows portable zip이나 MSI에 CLI가 같이 들어 있습니다. 푼 다음 designcraft-cli.exe를
기본 위치에 두면 설정 없이 찾습니다.
%LOCALAPPDATA%\Programs\ArtCraft\DesignCraft\designcraft-cli.exe # Windows 기본
/Applications/DesignCraft.app/Contents/MacOS/designcraft-cli # macOS
/usr/bin/designcraft-cli # Linux
다른 데 두었으면 agents/.env에 경로를 적습니다. PATH에 있으면 그것도 씁니다.
PG_DESIGNCRAFT_CLI=D:\tools\designcraft\designcraft-cli.exe
화면 위쪽 DesignCraft MCP 연결에 버전·프로토콜·도구 수가 뜨면 된 것입니다. 안 되면 왜 안 되는지 같이 나옵니다.
| 검사 방식 | 교정 짝(원래 내용 → 수정할 내용) |
|---|---|
| 바로 검사 | 오용·외래어 표기 사전으로 브라우저에서 찾습니다 |
| 에이전트 검사 | 위 사전 + Kiwi 오타 모델 + (키를 넣으면) LLM 문맥 교정 |
사전은 frontend/public/data/korean-misuse.json 하나입니다. 파이썬 교정 에이전트와 브라우저가
같은 파일을 읽습니다 — 한쪽에만 낱말을 더하면 두 검사 방식의 결과가 갈립니다.
여백 부족·수치 불일치처럼 사람이 판단할 항목에는 짝이 없습니다. 복사한 글에 주석으로 따로 적습니다.
교정 한 건마다 find.find로 다시 찾고 story.replaceRange로 바꿉니다. 미리 위치를 모아 두지
않는 이유는 한글이 글자당 3바이트여서 앞을 고치면 뒤가 전부 밀리기 때문입니다. 다시 찾으면 밀린
위치가 저절로 따라옵니다.
같은 문구가 여러 군데면 고치지 않고 실패로 남깁니다. 어느 것인지 가릴 수 없는데 찍어서 고치면 조용히 틀립니다. 교정 줄에 쪽 번호를 적어 주면 그 쪽에서만 찾습니다.
고친 뒤 한 번 더 preflight.run을 돌립니다. 교정이 새 문제를 만들 수 있어서입니다 — 한글을 라틴
글꼴 자리에 넣으면 글리프가 없고, 글이 길어지면 넘칩니다.
preflight.run은 PDF만 봐서는 알 수 없는 것들을 잡습니다. 넘친 글자는 PDF에 아예 안 찍히고,
끊긴 이미지는 빈 칸으로 보일 뿐이며, 폰트는 이미 대체가 끝난 상태입니다.
overset(넘침) · missingFont · missingGlyphs · missingLink · lowResolution · emptyText · rgbColor
반대로 CMYK 색 차이(ΔE)·총 잉크량은 PDF를 래스터화해야 나오므로 기존 검수가 맡습니다. 원본만 올리면 DesignCraft가 PDF를 직접 뽑아 주므로 판본이 어긋날 일이 없습니다.
--automation-read-root/--write-root로 의뢰 폴더에 가둡니다. 읽기는 올린 원본이 있는
폴더와 작업 폴더만, 쓰기는 작업 폴더만입니다.화면의 1번(DesignCraft MCP 연결)은 DesignCraft 자체 기능이고, 2·3·4는 그 위에 PrintGuard가 올린
화면입니다. 그래서 같은 MCP를 AI 코딩 도구에 바로 붙여 대화로 고치게 할 수도 있습니다 — 도구 26개가
그대로 붙어서 file.openIdml → find.change → file.exportPdf를 스스로 합니다.
claude mcp add designcraft -- designcraft-cli mcp \
--automation-read-root C:\work\idml \
--automation-write-root C:\work\out
두 폴더를 빼면 디스크 전체가 열립니다. 문서의 "Without either flag nothing changes"는 가두지 않는다는 뜻입니다. 실제로 확인해 보니, 플래그 없이 띄운 MCP가 임의의 폴더에 있는 IDML을 읽고
%LOCALAPPDATA%\Temp에 PNG를 썼습니다. 그래서mcp_client.py는 두 폴더가 없으면 프로세스를 아예 띄우지 않습니다.
직접 붙이면 이 저장소가 하던 것들은 빠집니다 — 같은 글자가 여러 쪽에 있을 때 쪽으로 가리기, 한 건 고칠 때마다 다시 찾기(한글은 한 자가 3바이트라 한 번 바꾸면 뒤쪽 바이트 위치가 모두 밀립니다), 항목별 실패 이유, safety 관문, 고친 뒤 preflight 재검사. 한두 건이면 직접 붙이는 편이 빠르고, 검수 결과 전부를 그대로 반영할 때는 화면 쪽이 안전합니다.
프론트는 Vercel에 올리고, 에이전트는 개발자 PC에서 돌리면서 Cloudflare 터널로 고정 주소를 붙이는 구성입니다. 에이전트 9개는 서로 http로 부르며 계속 떠 있어야 해서, 요청 때만 깨는 서버리스로는 돌릴 수 없습니다.
브라우저 ─▶ Vercel(프론트) ─▶ https://pg.2taeyoon.com ─▶ Cloudflare 터널 ─▶ PC 127.0.0.1:8700 ─▶ 에이전트 9개
프론트(Vercel) — Root Directory frontend, 프리셋 Next.js, main에 머지하면 자동 배포됩니다. 환경변수는 하나입니다.
NEXT_PUBLIC_PG_ORCHESTRATOR=https://pg.2taeyoon.com
NEXT_PUBLIC_ 값은 빌드할 때 번들에 박히므로, 바꾸면 재배포해야 합니다. 이 값이 로컬 주소가 아니면 앱은 공개 배포로 보고 에이전트 검사를 기본 모드로 엽니다.
에이전트(내 PC + 터널) — 터널은 한 번만 만들어 두면 주소가 고정됩니다.
cloudflared tunnel login # 최초 1회
cloudflared tunnel create printguard # 최초 1회
cloudflared tunnel route dns printguard pg.2taeyoon.com # 최초 1회
~/.cloudflared/config.yml에 들어갈 내용은 이렇습니다. 바깥에 여는 것은 오케스트레이터 하나뿐이고 나머지 경로는 막습니다.
tunnel: <터널 ID>
credentials-file: <경로>/<터널 ID>.json
ingress:
- hostname: pg.2taeyoon.com
service: http://127.0.0.1:8700
- service: http_status:404
그 뒤로는 켤 때마다 두 줄입니다.
python agents/run_agents.py
cloudflared tunnel run printguard
브라우저가 다른 출처에서 오케스트레이터를 부르므로 agents/.env에 그 출처를 허용해 둡니다.
PG_CORS_ORIGIN_REGEX=https://.*\.vercel\.app|http://(127\.0\.0\.1|localhost):\d+
공개 사이트에서 달라지는 점
.icc 파일을 화면에서 직접 올려야 합니다.NEXT_PUBLIC_PG_ORCHESTRATOR 하나만 씁니다 — 주소를 입력하는 칸은 들어오는 사람 아무에게나 그 주소를 적어 보여 주는 자리였습니다. 다만 주소 자체가 숨겨지는 것은 아닙니다(브라우저가 거기로 요청을 보내니 개발자도구에는 보입니다). 막는 일은 오케스트레이터의 토큰 검사와 CORS가 합니다.컨테이너로 올리고 싶으면 deploy/hf-space/Dockerfile이 에이전트 9개를 한 컨테이너에 담습니다(PG_HOST=0.0.0.0, PORT로 오케스트레이터 포트를 받습니다).
로그인은 선택입니다 — 클라이언트 ID가 없어도 검수는 전부 됩니다. 다만 로그인 단추가 열리지 않아 기록이 그 브라우저를 벗어나지 못합니다.
https://<배포 주소>, http://localhost:8752, http://127.0.0.1:8752.
리디렉션 URI는 넣지 않습니다. ID 토큰만 받는 방식이라 되돌아올 주소가 없습니다./privacy)·이용약관(/terms) 주소를 넣고, 대상(Audience) 화면에서 앱 게시를 눌러 프로덕션으로 올립니다. 테스트 중으로 두면 거기 적힌 테스트 사용자만 로그인됩니다(기본 범위 openid·email·profile만 쓰므로 검토 절차는 없습니다).agents/.env의 PG_GOOGLE_CLIENT_ID에 넣고 에이전트를 다시 켭니다.# agents/.env
PG_GOOGLE_CLIENT_ID=<클라이언트 ID>.apps.googleusercontent.com
.env는 커밋되지 않습니다. 에이전트를 켜는 PC마다 이 줄을 넣어야 합니다.
클라이언트 ID는 비밀이 아닙니다 — 브라우저가 화면에 들고 다니는 값입니다. 클라이언트 비밀번호는 쓰지 않습니다.
브라우저는 이 값을 에이전트에게 물어서(GET /auth/config) 가져옵니다. 앱은 한 번 배포해 두고 에이전트는 사람마다
자기 PC에서 켜기 때문에, 앱에 박아 두면 다른 사람이 자기 에이전트를 쓸 때 ID를 바꿀 길이 없어서입니다.
앱에 박아 둔 NEXT_PUBLIC_GOOGLE_CLIENT_ID는 에이전트가 답하지 못할 때의 대비책입니다.
전부 무효로 만들려면 agents/.data/auth_secret을 지우고 다시 켭니다.
agents/.env.example을 agents/.env로 복사해 값을 채웁니다(.env는 커밋되지 않습니다). 터미널에 이미 설정된 환경변수가 있으면 그 값이 이깁니다.
cp agents/.env.example agents/.env # Windows: copy agents\.env.example agents\.env
# agents/.env
GEMINI_API_KEY=발급받은_키
PG_LLM_MODEL=gemini-3.5-flash-lite # 무료 등급이 있는 모델(기본값)
PG_PROOF_METHODS=rules,kiwi_typo,llm
LANGSMITH_API_KEY=발급받은_키
LANGSMITH_PROJECT=printguard
| 기능 | 환경변수 | 받는 곳 | 쓰는 법 |
|---|---|---|---|
| LLM 교정 제안(규칙·Kiwi에 더해) | GEMINI_API_KEY, 모델은 PG_LLM_MODEL(기본 gemini-3.5-flash-lite — 무료 등급. gemini-2.5-*는 신규 키에 제공되지 않음), PG_PROOF_METHODS | Google AI Studio | .env에 넣고 python agents/run_agents.py |
| LLM 교정기 정량평가 | 위와 같음 | 위와 같음 | python eval/proofread/eval_proofread.py (키가 있으면 LLM 조합이 표에 더해집니다. API 호출 121회 — 무료 등급 하루 한도 안, 분당 한도에 걸리면 기다렸다 다시 부릅니다) |
| 추적을 LangSmith로 보내기 | LANGSMITH_API_KEY, LANGSMITH_PROJECT(기본 printguard) | LangSmith → Settings → API Keys | cd agents && python -m pg_agents.langsmith_export <context_id> |
.env를 읽는 곳은 run_agents.py(자식 에이전트까지 물려 줍니다), pg_agents.mcp_server, pg_agents.langsmith_export, 교정 평가 스크립트입니다. 앱(브라우저) 쪽 설정은 Next.js 규칙대로 frontend/.env.local에 둡니다 — 오케스트레이터 주소(NEXT_PUBLIC_PG_ORCHESTRATOR=http://127.0.0.1:8700)와 구글 클라이언트 ID의 대비책(NEXT_PUBLIC_GOOGLE_CLIENT_ID) 둘입니다.
LangSmith로 나가는 것은 공통 로그로 만든 추적(에이전트·skill·시간·상태·관문 결정)뿐입니다. PDF 본문과 입력값은 공통 로그에 애초에 남기지 않으므로 나가지 않습니다.
라이선스나 용량 때문에 올리지 않았습니다. 셋 다 없어도 앱은 뜨지만, 모델과 wasm은 CDN에서 받아 오느라 느려지고 ICC가 없으면 색 차이를 재지 못합니다.
frontend/public/models/Xenova/multilingual-e5-small/
Hugging Face Xenova/multilingual-e5-small에서 config.json, tokenizer.json, tokenizer_config.json, special_tokens_map.json, sentencepiece.bpe.model, quant_config.json, onnx/model_quantized.onnx를 받습니다. 없으면 브라우저는 Hugging Face CDN에서, 에이전트는 huggingface_hub로 받아 씁니다.frontend/public/ort/
npm install 후 node_modules/onnxruntime-web/dist/의 ort-wasm-simd-threaded*.{mjs,wasm}를 복사합니다. 없으면 transformers.js 기본 CDN을 씁니다.frontend/public/icc/ (재배포 금지라 직접 받아야 합니다)
python deploy/fetch_icc.py # 12개를 ECI·ICC 레지스트리에서 받아 넣습니다
손으로 받으려면 — ECI(https://eci.org/lib/exe/<이름>.zip의 pso-coated_v3, pso-uncoated_v3_fogra52, eci_offset_2009, eci_offset_profiles_inp, pso_sc-b_paper_v3) 안의 PSOcoated_v3.icc, PSOuncoated_v3_FOGRA52.icc, ISOcoated_v2_eci.icc, ISOuncoatedyellowish.icc, PSO_LWC_Improved_eci.icc, PSO_LWC_Standard_eci.icc, PSO_MFC_Paper_eci.icc, PSO_SNP_Paper_eci.icc, PSO_INP_Paper_eci.icc와, ICC 프로파일 레지스트리(https://registry.color.org/profile-registry/profiles/<이름>.icc)의 PSOsc-b_paper_v3_FOGRA54.icc, APTEC_PC10_CardBoard_2023_v1.icc, JapanColor2011Coated.icc입니다.frontend/scripts/test-substrate.mts, 적용 확인: test-substrate-engine.mts).human:<이름>)뿐입니다.gemini-3.5-flash-lite, 2026-10-27). 규칙 기반 쪽은 오류를 넣는 규칙과 찾는 규칙이 겹쳐 재현율이 부풀어 있어 실제 원고로 다시 재야 합니다.PG_PROOF_METHODS로 직접 켜야 합니다. LLM 교정기와 LangSmith 추적은 사용자가 GEMINI_API_KEY·LANGSMITH_API_KEY를 직접 넣을 때만 씁니다 — 키를 찾거나 읽지 않습니다.POST /auth/session) 브라우저가 localStorage에 둡니다. 누구인지는 담기지 않고, 기한이 있습니다(기본 12시간).POST /auth/google). ID 토큰의 서명·발급자·청중(클라이언트 ID)·기한을 확인하고 계정에 묶인 토큰으로 바꿉니다. 비밀번호는 지나가지 않습니다. 받아 두는 것은 계정 번호와 이름·이메일·사진뿐이고, 계정 번호는 서버 비밀로 해시해서 씁니다 — 의뢰 기록과 로그에 남는 값이라, 그대로 쓰면 계정 번호가 같이 남습니다. 이름·이메일·사진은 화면 표시용이라 서버에 저장하지 않습니다. 검사에는 쓰지 않습니다.POST /auth/claim). 들고 있던 익명 토큰을 그대로 내밀어 권리를 증명하고(번호만 알면 남의 것을 가져갈 수 있어서는 안 됩니다), 옮긴 뒤 로컬의 익명 토큰은 지웁니다. 로그인한 토큰은 저장하지 않습니다 — 새로 고치면 구글에 조용히 다시 묻습니다.crypto.randomUUID()로 스스로 만든 값을 localStorage에 영구히 두고 주인 표시로 썼습니다. 서버가 발급하지 않으니 기한도 회수도 없었습니다. 지금 거기 있는 값은 서버가 발급해 서명한 토큰이고, 기한이 있으며, 로그인하면 지워집니다.한국제지연합회 「종이의 분류」, 두성종이·삼원페이퍼 제품 페이지와 국내 제지사 공식 제품 페이지, 행정안전부 LOCALDATA 기타_인쇄사(공공누리 출처표시), 파주출판도시 입주기업협의회, Kodak 공개 테스트 사진. 화면의 출처 탭에 논문·데이터·모델·라이브러리를 전부 적어 두었습니다.