Imported from sangmokang/Valuehire_v5 (
.codex/skills/login/SKILL.md). Install upstream withnpx skills add sangmokang/Valuehire_v5 --skill login. Copyright stays with the author.
Login โ 3์ฌ ๋ธ๋ผ์ฐ์ ๋ก๊ทธ์ธยท์ธ์ ๋ณด์กด ํ์ค
์ด ์คํฌ์ macOS์ ๋ช
์์ ์ผ๋ก ์์๋ WinPC์์ ์ฌ๋์ธ, ์ก์ฝ๋ฆฌ์, LinkedIn Recruiter/RPS๋ฅผ ์ฌ๋ ๋ชจ๋ ์์
์ ์ ํ ์ ์ฐจ๋ค.
Claude, Codex, Hermes๋ ๊ฒ์ยทํ๋กํ ์ด๋ยทํฌ์ง์
๋ฑ๋ก๋ณด๋ค ๋จผ์ ์ด ์คํฌ์ ์ ์ฉํ๋ค. WinPC๋ ํ์ฌ ํด์ ์ฌ์ฅ๋์ด ์คํ ๊ธฐ๊ธฐ๋ฅผ ๋ช
์ํ ๊ฒฝ์ฐ์๋ง ๊ธฐ์กด ๋ก๊ทธ์ธ ์ธ์
์ ์ฌ์ฉํ๋ฉฐ idle ๊ธฐ๋ฐ ์๋ ์ฌ๊ฐ๋ฅผ ํ์ง ์๋๋ค. ๊ทธ ๋ฐ์ ์ด์์ฒด์ ๋ ์์ ์๋ WinPC ์คํ์ HUMAN_ACTIVE๋ก ์ค๋จํ๊ณ macOS์ ๊ฐ์ ์์ ์ฑ์ ์ฃผ์ฅํ์ง ์๋๋ค.
์ ๋ณธ ์ฐ์ ์์(์์ ๋ฌธ์๊ฐ ๋ค์ ๋ฌธ์๋ณด๋ค ์ฐ์ ํ๋ค):
- ๊ธฐ๊ณ ํ๋
์์ ๊ณ์ฝ:
skills/login/browser-control-contract.json - ์ฌ๋์ฉ ์คํ ํ๋กฌํํธ: ์ด
SKILL.md - ๋ก๊ทธ์ธ ํ์ ๊ณผ ์ฐจ๋จ ์ ํธ:
docs/sot/26-portal-login-spec.json - ์ฐธ๊ณ ๋ง ํ๋ ๊ณผ๊ฑฐ ๊ธฐ๋ก:
docs/ai-search/portal-login-live-search-runbook-2026-06-17.md - ๊ด๋ฆฌ ๋ธ๋ผ์ฐ์ ํ๋ก์ธ์คยทendpoint ์กฐํ:
scripts/portal_browsers.sh status|cdp - ๊ธฐ์กด ํญ ๋จ์ผ ์ฐ๊ฒฐยทํ์:
tools/multi_position_sourcing/raw_cdp.py - ์ฌ๋ ํ๋ ๊ฐ์ง:
tools/multi_position_sourcing/owner_activity.py - ๊ฒ์ ์ ์คํ ํ๋กฌํํธ:
docs/prompts/login-search-execution-contract.md - ๊ธ์ง ๊ฒฝ๋ก ๊ฐ์ Hook:
.claude/hooks/guards/login.py
๊ณผ๊ฑฐ ๊ธฐ๋ก์ด๋ ๊ธฐ์กด ์ฝ๋๊ฐ ์ด ์คํฌ/์์ ๊ณ์ฝ๊ณผ ์ถฉ๋ํ๋ฉด ๊ณผ๊ฑฐ ๊ธฐ๋ก์ ๋ฐ๋ฅด์ง ์๋๋ค.
0. ์ ๋ ๊ท์น
์๋ ๊ท์น์ ๊ถ๊ณ ๊ฐ ์๋๋ผ ์ค๋จ ์กฐ๊ฑด์ด๋ค.
- ๋จผ์ ์ฐพ๊ณ , ๋ก๊ทธ์ธ ํ๋ฆ์์๋ ์๋ก ์ด์ง ์๋๋ค. ์คํ ์ค์ธ ๋ธ๋ผ์ฐ์ , CDP endpoint, ์์ ํ๋กํ, ๋์ ์ฌ์ดํธ ํญ์ ์กฐ์ฌํด ์ ํํ ๊ธฐ์กด target๋ง ์ฌ์ฉํ๋ค.
- ๊ธฐ์กด ๋ธ๋ผ์ฐ์ ์ ๋ก๊ทธ์ธ๋ ํญ์ ์ต์ฐ์ ์ผ๋ก ์ฌ์ฌ์ฉํ๋ค. ์ ํํ ๋์ ํญ ํ๋์ raw CDP๋ก ์ฐ๊ฒฐํ๋ค.
- ์ฌ๋์ด ํค ์ ๋ ฅ, ๋ง์ฐ์ค ์กฐ์, ๋ก๊ทธ์ธ, captcha/2FA/checkpoint ํด๊ฒฐ์ ํ๋ ๋์ AI์ click/type/navigate/close๋ 0ํ๋ค. ์ฝ๊ธฐ ์ ์ฉ ์ํ ํ์ธ๋ง ํ์ฉํ๋ค.
- ์ฌ๋์ด ๋ง๋ ๋ก๊ทธ์ธ ์ธ์ ์ ์์ ๊ถ๊ณผ ๋ฌด๊ดํ๊ฒ ๋ณด์กดํ๋ค. ๋ก๊ทธ์ธ ์ฑ๊ณต ํ ์ฐฝ์ ๋ซ์ง ์๋๋ค. ํญ์ ๋ซ์ง ์๋๋ค. ํ๋กํ์ ์ญ์ ํ์ง ์๋๋ค.
- CDP ์ฐ๊ฒฐ ํด์ ์ ๋ธ๋ผ์ฐ์ ์ข
๋ฃ๋ฅผ ๊ตฌ๋ถํ๋ค. ์์
์ข
๋ฃ ์ WebSocket๋ง ๋๋๋ค.
context.close(),browser.close(),page.close(), Chrome kill,scripts/portal_browsers.sh stop|restart๋ฅผ ํธ์ถํ์ง ์๋๋ค. - ๋ก๊ทธ์ธ ํ๋ฆ์ ์ฐฝ๊ณผ ํญ์ ์์ฑํ์ง ์๋๋ค. ๊ธฐ์กด ๋ธ๋ผ์ฐ์ ์ ์ ํํ CDP target๋ง ์ฌ์ฌ์ฉํ๋ฉฐ ์ ์ฐฝ 0๊ฐ, ์ ํญ 0๊ฐ๋ค. ๋์ ํญ์ด ์์ผ๋ฉด ์์ ํ์ด์ง๋ฅผ ๋ง๋ค์ง ๋ง๊ณ ์ ํํ ๋ธ๋ผ์ฐ์ ยทํ๋กํยทendpoint ์ ๋ณด์ ํจ๊ป ์ค๋จํ๋ค.
- ๋ณด์ ์ฑ๋ฆฐ์ง๋ ์๋ ์ฐํํ์ง ์๋๋ค. captcha, 2FA, checkpoint, ์ด์ ์ ๊ทผ์ ์ฆ์ ์ฌ๋์๊ฒ ๋๊ธฐ๊ณ ๊ฐ์ ์ ์ถ์ ๋ฐ๋ณตํ์ง ์๋๋ค. LinkedIn ์ธ์
์ถฉ๋ยทmultiple-sign-in์ ์ฌ๋ ์ธ์ฆ ์ธ๊ณ๊ฐ ์๋ terminal
AUTH_CONFLICT๋ก ์ฆ์ ์ค๋จํ๋ค. - ๋น๋ฐ๋ฒํธ, ์ฟ ํค, ํ ํฐ, ์ธ์ ์ ์ฅ๊ฐ์ ์ถ๋ ฅยท๋ณต์ฌยท๋ฌธ์ํํ์ง ์๋๋ค. ์ ์ฅ ์๊ฒฉ์ฆ๋ช ์ ๋ ฅ์ ๊ฒ์ฆ๋ ๋ก๊ทธ์ธ ์คํ๊ธฐ๊ฐ ๋งก๋๋ค.
- AI๊ฐ ๋ถ์ ํญ์๋
vh-automation-badge๋ฅผ ํ์ํ๋ค. ํ์ ์คํจ ์ ๋ชฐ๋ ์กฐ์ํ์ง ๋ง๊ณ AI_ATTACHED ์ง์ ์ ๋ณด๋ฅํ๋ค. - ๋ก๊ทธ์ธ ์ฑ๊ณต์ URL ์ถ์ธก์ด ์๋๋ผ ์ฌ์ดํธ๋ณ ๋ก๊ทธ์ธ ๋ง์ปค๋ก ์ฆ๋ช ํ๋ค. ์ฆ๋ช ์ ์๋ ๊ฒ์์ ์์ํ์ง ์๋๋ค.
LinkedIn RPS ๋จ์ผ ์ธ์
๋ณด์กด (SESSION_CONTEXT_PRESERVATION, #156)
- LinkedIn Recruiter๋ ํ ์ข์์ ์ธ์
์ด ์ฌ๋ฌ Chrome ํ๋กํ์์ ์๋ก๋ฅผ ๋ก๊ทธ์์์ํฌ ์ ์๋ค. ๊ด๋ฆฌ์ฉ
Chrome๋ง ๋ณด์ง ๋ง๊ณ , ์๋ ค์ง Chrome ํ๋กํยทendpoint์์ ์ด๋ฏธ ์ธ์ฆ๋ RPS target์ด ์๋์ง ๋จผ์ ์ฝ๋๋ค.
๋ค๋ฅธ ํ๋กํ์ RPS ์ธ์
์ ํธ๊ฐ ์์ผ๋ฉด
AUTH_CONFLICT๋ก ์ค๋จํ๋ฉฐ ๋ ๋ฒ์งธ ํ๋กํ์์ ๋ก๊ทธ์ธํ์ง ์๋๋ค. - ์ ํํ ๊ธฐ์กด target์์ ๋ก๊ทธ์ธ ๋ง์ปค๊ฐ ์ด๋ฏธ ์ฐธ์ด๋ฉด ๋ก๊ทธ์ธ ๊ด๋ จ mutation์ 0ํ๋ค. ๋ก๊ทธ์ธ URL ์ด๋, ์๊ฒฉ์ฆ๋ช ์ ์ถ, ์ ๋ธ๋ผ์ฐ์ ยท์ ์ฐฝยท์ ํญ ์์ฑ, ๋ค๋ฅธ ํ๋กํ ์ ํ์ ํ์ง ์๊ณ ๊ฐ์ target์์ ์๋ ์์ ๋ง ์ฌ๊ฐํ๋ค.
enterprise-authentication/sessions,multiple sign-ins,Only one session์AUTH_LOST๊ฐ ์๋๋ผ terminalAUTH_CONFLICT๋ค. ์๋ ๋ก๊ทธ์ธยทContinue/Confirm ํด๋ฆญยท์ธ์ ์ข ๋ฃ ์ ํยทreload/navigation retry๋ฅผ ํ์ง ์๋๋ค. ์ฌ๋์ด ํ ๋ฒ ํด๊ฒฐํ ๊ฐ์ ์คํ์์ ์ฌ๋ฐํด๋ ๋ ๋ฒ์งธ ๋ก๊ทธ์ธ ์ธ๊ณ๋ฅผ ๋ง๋ค์ง ์๊ณ ์๊ตฌ ์ค๋จํ๋ค.- Recruiter ๊ฒฐ๊ณผ์ bare
profile_url์ ์ ์ฅยท์ค๋ณต์ ๊ฑฐ ์๋ณ์์ผ ๋ฟ์ด๋ค. ํ๋กํ ์ด๋์ ๊ฒ์ ๊ฒฐ๊ณผ DOM์์ ์ํํ query ํฌํจ ์๋ณธnavigation_url์ ๊ทธ๋๋ก ์ฐ๋ฉฐ, ์ด๋ ์งํ ์ฐจ๋จ ๊ฒ์ฌ๋ฅผ ์ถ์ถยท์คํฌ๋ฆฐ์ทยท์ ์ฅ๋ณด๋ค ๋จผ์ ํ๋ค.
1. ์ํ๊ธฐ๊ณ
ํ ๋ฒ์ ์ ํํ ํ ์ํ๋ง ์ ์งํ๋ค. ์ํ๋ฅผ ๊ฑด๋๋ฐ์ง ์๋๋ค.
| ์ํ | ๋ป | ํ์ฉ ํ๋ | ์ ์ด ์กฐ๊ฑด |
|---|---|---|---|
DISCOVER |
๋ธ๋ผ์ฐ์ ยทCDPยทํญยทํ๋กํ ์กฐ์ฌ ์ค | ํ๋ก์ธ์ค/endpoint//json/list ์ฝ๊ธฐ |
๋์ ํญ๊ณผ ์ฌ๋ ํ๋ ํ์ ์๋ฃ |
HUMAN_ACTIVE |
์ฌ์ฅ๋์ด 3์ฌ ํฌํธ ํ๋ฉด์ ๋ง์ง๋ ์ค(ํฌ๋กฌ ํ์ฑ ํญ์ด 3์ฌ ๋๋ฉ์ธ + ์ต๊ทผ ์ ๋ ฅ) | ๋ฌด์กฐ์, ์ํ ์ฝ๊ธฐ, ๋๊ธฐ | OS idle 60์ด ์ด์ ๋๋ ๋ช
์์ ์๋ณด. ๋จ ๋ก๊ทธ์ธ ๊ฐ์
์ค์ด๋ฉด HUMAN_AUTH ์ฐ์ |
AI_ATTACHED |
AI๊ฐ ๊ธฐ์กด ํญ ํ๋์ ์ฐ๊ฒฐํ๊ณ ๋ฐฐ์ง ํ์ | ํด๋น ํญ๋ง ์กฐ์, ์ฌ๋ ์ธ์ฆ ์ธ๊ณ ์ ์ ํํ ์ฐฝ 1ํ ํ๋ฉดํ | ๋ก๊ทธ์ธ ํ์โ์๋ ๋ก๊ทธ์ธ, ์ฑ๋ฆฐ์งโHUMAN_AUTH, ์ธ์
์ถฉ๋โAUTH_CONFLICT, ์ฑ๊ณตโAUTHENTICATED |
HUMAN_AUTH |
์ฌ๋์ด ๋ก๊ทธ์ธ/๋ณด์ ์ฑ๋ฆฐ์ง ์ฒ๋ฆฌ ์ค | ๋ฌด์กฐ์, 5์ด ์ด์ ๊ฐ๊ฒฉ์ ์ฝ๊ธฐ ์ ์ฉ ๋ก๊ทธ์ธ ๋ง์ปค ํ์ธ | ๋ก๊ทธ์ธ ๋ง์ปค ํ์ธ + ๋ง์ง๋ง ํค ์ ๋ ฅ/๋ง์ฐ์ค ํ๋ ํ 15์ด ์กฐ์ฉํจ |
AUTHENTICATED |
์ฌ์ดํธ๋ณ ๋ก๊ทธ์ธ ์ฆ๋ช ์๋ฃ | ์ฆ๊ฑฐ ๊ธฐ๋ก, ์๋ ์์ ์์ | ์ฌ๋์ธยท์ก์ฝ๋ฆฌ์ 15๋ถ/๋งํฌ๋์ธ 30๋ถ ๊ฒฝ๊ณผโKEEPALIVE, ๋ก๊ทธ์์ ์ ํธโAUTH_LOST |
KEEPALIVE |
์ธ์ ์๋ช ์ฐ์ฅ์ ์ํ ์์ ํ์ธ | ๊ฒ์ฆ๋ ์ฝ๊ธฐ ์ ์ฉ ๋งํฌ 1ํ ํด๋ฆญ ํ ๋์ผ ํญ์ ์ด์ history entry๋ก Browser Back | ์๋ URLยท๋ก๊ทธ์ธ ๋ง์ปค ์ฌํ์ธโAUTHENTICATED, ์คํจโAUTH_LOST |
AUTH_LOST |
๋ก๊ทธ์ธ ๋ง์ปค ์์ค/๋ก๊ทธ์ธ ํ๋ฉด ์ ํ | ์๋ ๋ก๊ทธ์ธ 1ํ ๋๋ ์ฌ๋ ์ธ๊ณ | ์ฑ๊ณตโAUTHENTICATED, ์ฑ๋ฆฐ์งโHUMAN_AUTH |
AUTH_CONFLICT |
LinkedIn ๋จ์ผ์ข์ ์ธ์ ์ถฉ๋ | ์ฝ๊ธฐ ์ ์ฉ ์ฆ๊ฑฐ ๊ธฐ๋ก ํ ์๊ตฌ ์ค๋จ | terminal; ์๋ ๋ก๊ทธ์ธยทํ์ธ ํด๋ฆญยท์ฌํ๋ฉดํยท์ฌ์๋ 0ํ |
HANDOFF |
์ฌ๋์๊ฒ ์์ ํ๊ฒ ๋๊น | guard ํ์ฉ ์ title/๋ฐฐ์ง ๋ณต์, ์๋๋ฉด cleanup pending; CDP ์ฐ๊ฒฐ๋ง ํด์ | ์ข ๋ฃ. ๋ธ๋ผ์ฐ์ ยท์ฐฝยทํญยทํ๋กํ์ ์ ์ง |
์ฌ๋ ์ ์ ํ์
- ์๋ ์์
์
tools.multi_position_sourcing.owner_activity.detect_owner_activity_snapshot()์ OS idle ์ ํธ๋ฅผ ํ์ธํ๋ค. - (2026-07-20 ์ฌ์ฅ๋ ์ง์) ์ฌ์ฅ๋ ๊ฐ์
์ ํฌ๋กฌ ํ์ฑ ํญ์ด 3์ฌ(์ฌ๋์ธยท์ก์ฝ๋ฆฌ์ยท๋งํฌ๋์ธ) ๋๋ฉ์ธ์ผ ๋๋ง ์ธ์ ํ๋ค โ ์ ํ๋ธ ๋ฑ ๋ค๋ฅธ ํ๋ฉด ์ฌ์ฉ์ ๊ฐ์
์ด ์๋๋ฏ๋ก ์๋ณดํ์ง ์๋๋ค. 3์ฌ ํ๋ฉด์์ ์ต๊ทผ ์
๋ ฅ์ผ๋ก idle์ด 60์ด ๋ฏธ๋ง์ด๋ฉด
HUMAN_ACTIVE๋ค. ํ์ ์๋ ์์ฐฝ ์ฑ ์ด๋ฆยทOS idleยทํ์ฑ ํญ ํธ์คํธ(๋๋ฉ์ธ) ๋ง ์ฝ๋๋ค โ ํ์ด์ง ๋ด์ฉยท์ ์ฒด URLยทํค์ ๋ ฅ์ ๋ณด์ง๋ ๊ธฐ๋กํ์ง๋ ์๋๋ค. - ๊ฐ์ง ์คํจยท๊ถํ ๋ถ์กฑยท๊ฐ ์์์ fail-closed ํ๋ค(๋จ ํญ ํธ์คํธ ํ๋ ์คํจ๋ idle 60์ด ์ ๊ณ ๋๊ธฐ โ ๋ฌด๊ธฐํ ์๋).
- ์ผ๋ฐ ์์
์ 60์ด idle ํ ์๋ ์ฌ๊ฐํ ์ ์๋ค. ๊ทธ๋ฌ๋ AI๊ฐ ๋ณด์ ์ฑ๋ฆฐ์ง๋ฅผ ์ฌ๋์๊ฒ ๋๊ธด
HUMAN_AUTH์ํ๋ ์์ ์๊ฐ์ด๊ณผ๋ก ๋ซ๊ฑฐ๋ ์ฌ๊ฐํ์ง ์๋๋ค. - ๋ก๊ทธ์ธ ์ต์ฐ์ (SOT26 INV9, 2026-07-31 ์ค๋ ์ง์ ๊ฐ์ ): ๋ก๊ทธ์ธ(
session_guard auto-login)๋ง์ ์ 60์ด ๋๊ธฐ ๊ท์น์ ๋ฐ๋ฅด์ง ์๋๋ค. ์ฌ์ฅ๋์ด ๊ทธ ์ฌ์ดํธ์ ๋ก๊ทธ์ธ ํ๋ฉด ์์ฒด๋ฅผ ์กฐ์ ์ค์ผ ๋๋ง ์๋ณดํ๊ณ , 3์ฌ ๋๋ฉ์ธ์ ๋ค๋ฅธ ํ๋ฉด(๊ฒ์ยท์ฑ์ฉ๊ณต๊ณ ๋ฑ)์ ๋ณด๊ณ ์๋ ๊ฒ์ idle๊ณผ ๋ฌด๊ดํ๊ฒ ๋ก๊ทธ์ธ ์๋ํ๋ฅผ ์ฆ์ ์งํํ๋ค. ๋ก๊ทธ์ธ ํ๋ฉด ์ฌ๋ถ๋tools.multi_position_sourcing.owner_activity.detect_login_screen_snapshot()๋ก ํ์ ํ๋ฉฐ, ํ๋ ๋ถ๊ฐ ์ fail-closed๋ก ๋ก๊ทธ์ธ ํ๋ฉด์ผ๋ก ๊ฐ์ฃผํด ์๋ณดํ๋ค. ๋ค๋ฅธ ํ์คํฌ(๊ฒ์ยท์ ์ฅ ๋ฑ)์ ์๋ณด ๊ฒ์ดํธ๋ ์ด ์์ธ์ ๋ฌด๊ดํ๊ฒ ๊ทธ๋๋ก๋ค. HUMAN_AUTH์์ ๋ก๊ทธ์ธ ๋ง์ปค๊ฐ ๋ํ๋๋ ์ฆ์ ํด๋ฆญํ์ง ์๋๋ค. ๋ง์ง๋ง ์ฌ๋ ํ๋ ๋ค ์ต์ 15์ด ์กฐ์ฉํจ์ ํ์ธํ ํAUTHENTICATED๋ก ์ ์ดํ๋ค.- ๋๊ธฐ ์ค์๋ ๊ฐ์ ์ฐฝ์ ์์ผ๋ก ๊ฐ์ ธ์ค์ง ์๋๋ค. ์ฑ๋ฆฐ์ง๋ฅผ ์ฒ์ ์ฌ๋์๊ฒ ๋๊ธฐ๊ธฐ ์ง์
AI_ATTACHED์์๋ง ์ ํํ ํด์๋ ์ฐฝ์ ํ ๋ฒ ๋ณด์ฌ์ฃผ๊ณ ,HUMAN_AUTH์ง์ ํ focus/focus_again์ 0ํ๋ค.
๋ก๊ทธ์ธํ ์ฐฝยทํ์ด์ง๋ฅผ ์ ํํ ํ์
์ฌ๋์๊ฒ ์ธ์ฆ์ ๋๊ธฐ๊ธฐ ์ ์ ์ ํํ CDP target๊ณผ macOS ์ฐฝ์ ๋ค์ ์์๋ก 1:1 ๊ฒฐํฉํ๋ค.
- ๊ด๋ฆฌ๋ site endpoint๋ฅผ ๊ฐ์ง ์ ํํ ๊ธฐ์กด Chrome ํ๋ก์ธ์ค์ ๋ช
๋ นํ์์
--remote-debugging-port,--user-data-dir, browser PID๋ฅผ ๊ฒฐํฉํ๋ค. macOSps -o command=๊ฐ argv ๋ฐ์ดํ๋ฅผ ๋ณด์กดํ์ง ์์ผ๋ฏ๋ก ๋ค์--flag๊ฒฝ๊ณ๊น์ง๋ฅผ ๊ฐ์ผ๋ก ์ฝ์ด ๊ณต๋ฐฑ ํฌํจ profile path๋ฅผ ์๋ฅด์ง ์๋๋ค. page target WebSocket์SystemInfo.getProcessInfo์ PID๋ฅผ ๋ฌป๊ฑฐ๋ ํฌํธ๋ฅผ ์ถ์ธกํ์ง ์๋๋ค. ๊ฐ์ endpoint/profile์ ์ฃผ์ฅํ๋ ๋ฃจํธ ํ๋ก์ธ์ค๊ฐ 0๊ฐ ๋๋ ์ฌ๋ฌ ๊ฐ๋ฉด ์ค๋จํ๋ค. - ๊ทธ endpoint์ ์ ํํ ๊ธฐ์กด target id์
Browser.getWindowForTargetbounds๋ฅผ ์ฝ๊ณ , ์คํฌ ํด๋ ๊ธฐ์ค ์๋ ๊ฒฝ๋กscripts/macos_window_locator.swift๋ฅผ ์คํํ๋ค. ๋จผ์ title marker ์์ด ๊ฐ์ PID + CDP bounds๋ก ํ์ฌ Space ๋ฐ ์ฐฝ๊น์ง ํฌํจํด ์ ์ผํ CGWindowID๋ฅผ preflightํ๋ค. 0๊ฐ์ด๊ฑฐ๋ ์ฌ๋ฌ ๊ฐ๋ฉด ์ด๋ค titleยท๋ฐฐ์งยทfocus๋ ๋ณด๋ด์ง ์๊ณ fail-closed ํ๋ค. - ์ธ๊ณ ์ง์ ํด๋น target์๋ง
[LOGIN HERE][<agent>][<site>][<target-id-suffix>]title prefix์vh-automation-badge๋ฅผ ๋ถ์ธ๋ค. ๋นํ์ฑ ํญ์document.title์ OS ์ฐฝ ์ ๋ชฉ์ ์์ง ๋ฐ์๋์ง ์์ผ๋ฏ๋ก fresh guard ๋คPage.bringToFront๋ฅผ ๋จผ์ 1ํ ์คํํ๊ณ , ๊ทธ ๋ค์ ๊ฐ์ PID + ๊ฐ์ bounds + prefix marker๋ก ๋ค์ ํด์ํ CGWindowID๊ฐ preflight์ ๊ฐ์์ง ํ์ธํ๋ค. ์ด์ด PID-boundNSRunningApplication.activate๋ฅผ fresh guard ๋ค 1ํ ์คํํ๊ณ , ํ์ฑํ ํ ๊ฐ์ CGWindowID๊ฐ on-screen์ด๋ฉด์ ์ ์ญ ์ต์๋จ layer-0 ์ฐฝ์ธ์ง ์ฆ๋ช ํ๋ค. titlecontains๋ ์ฒซ ์ฐฝ fallback์ ๊ธ์ง๋ค. - ์ฌ์ฉ์์๊ฒ agent, site, ๋ธ๋ผ์ฐ์ PID, profile path, CDP endpoint, target id ๋์๋ฆฌ, ์ ์ ํ title, query/fragment๋ฅผ ์ ๊ฑฐํ URL, CGWindowID, ์ฑ ํ์ฑํ ์ฆ๊ฑฐ๋ฅผ ๋ฐ๋์ ํ์ํ๋ค.
- ์คํฌ๋ฆฐ์ท์ด ํ์ํ๋ฉด ์ ์ฒด ํ๋ฉด์ด ์๋๋ผ
screencapture -x -l <CGWindowID>๋ก ๊ทธ ์ฐฝ๋ง ์บก์ฒํ๋ค. ๋ค๋ฅธ PID์ ์ฐฝ ์ ๋ชฉ์ ์ถ๋ ฅํ๊ฑฐ๋ ์บก์ฒํ์ง ์๋๋ค. 0700 ์์ ๋๋ ํฐ๋ฆฌ์ 0600 PNG ์ญ์ ๊ฐ ์คํจํ๋ฉด ์ฑ๊ณต์ผ๋ก ์จ๊ธฐ์ง ์๊ณ fail-closed ํ๋ค. HUMAN_AUTH์ง์ ํ์๋ 5์ด ์ด์ ๊ฐ๊ฒฉ์ผ๋ก fresh ๋ก๊ทธ์ธ ๋ง์ปค์ OS idle๋ง ์ฝ๋๋ค. ์๊ฐ์ ํ์ ์์ผ๋ฉฐ, ์ฑ๊ณต ๋ง์ปค,owner_activity_detected=false, ๋ง์ง๋ง ์ฌ๋ ์ ๋ ฅ ํ 15์ด ์กฐ์ฉํจ์ด ๋ชจ๋ ์ฑ๋ฆฝํด์ผ ์ฌ๊ฐํ๋ค.
์ธ ์์ด์ ํธ ๊ณต์ฉ ์ ์ ๊ถ
Claude, Codex, Hermes๊ฐ ๋์์ ๊ฐ์ ์ฌ์ดํธ๋ฅผ ๋ค๋ฃจ์ง ๋ชปํ๊ฒ DISCOVER๋ณด๋ค ๋จผ์ ์ฌ์ดํธ๋ณ ์ ์ ๊ถ์ ์ก๋๋ค.
- ๊ฒฝ๋ก:
~/.valuehire/browser_locks/login-<site>.lock - ํ๋: ์์์ ๋๋ ํฐ๋ฆฌ ์์ฑ(
mkdir)์ด ์ฑ๊ณตํ ํ ์คํ๋ง ์์ ์๋ค. ์์ ์ ํ ํฐ๊ณผ PID๋ฅผ ๋ด๋ถ ํ์ผ์ ๊ธฐ๋กํ๋ค. - ์ ์ ๊ถ์ ์ป์ง ๋ชปํ๋ฉด ๋ธ๋ผ์ฐ์ ยทํญ ์์ฑ๊ณผ CDP ์กฐ์์ 0ํ๋ก ์ ์งํ๊ณ ๊ธฐ๋ค๋ฆฐ๋ค. ๊ธฐ์กด lock์ ์๋ ์ญ์ ํ๊ฑฐ๋ ๋นผ์์ง ์๋๋ค.
- lock์ด ๋ก์ ๋ณด์ฌ๋ ์๋ ์ ๊ฑฐํ์ง ์๋๋ค. ๊ธฐ๋ก๋ ํ๋ก์ธ์ค์ ์ค์ ๋ธ๋ผ์ฐ์ ์์ ์ด ๋ชจ๋ ๋๋ฌ์์ ์ฌ๋์ด ํ์ธํ ๊ฒฝ์ฐ์๋ง ์ ๋ฆฌํ๋ค.
- ์์ ์๋
HANDOFF๊น์ง lock์ ์ ์งํ๊ณ , ์ข ๋ฃ ์ ์๊ธฐ ํ ํฐ์ด ์ผ์นํ ๋๋ง ์ ๊ฑฐํ๋ค. - target attach ์ง์ ์๋ ์๊ธฐ ํ ํฐ์ ๋ค์ ํ์ธํ๋ค. ํญ์ด ์์ผ๋ฉด ์์ฑํ์ง ์๊ณ
HANDOFFํ๋ค.
๋ชจ๋ ๋ณ๊ฒฝ ์กฐ์ ์ง์ ์ฅ๋ฒฝ
์ต์ด ์ ๊ฒ๋ง์ผ๋ก๋ ๋ถ์กฑํ๋ค. AI๊ฐ ๋ถ์ ๋ค ์ฌ๋์ด ํ์ดํ์ ์์ํ ์ ์์ผ๋ฏ๋ก navigate/click/type/submit ๋ฑ ๋ชจ๋ ๋ณ๊ฒฝ ์กฐ์ ์ง์ ์ ์๋๋ฅผ ๋งค๋ฒ ๋ฐ๋ณตํ๋ค.
- ์ฌ์ดํธ ์ ์ ๊ถ ํ ํฐ์ด ์์ง ์๊ธฐ ๊ฒ์ธ์ง ํ์ธํ๋ค.
- ์ฌ์ฅ๋ ๊ฐ์ ์ ํธ๋ฅผ ์ฝ๋๋ค โ ํฌ๋กฌ ํ์ฑ ํญ์ด 3์ฌ ๋๋ฉ์ธ์ด๋ฉด OS idle 60์ด ์ด์์ธ์ง ํ์ธํ๋ค(3์ฌ ์๋์ด ํ์ ์ด๋ฉด idle ๋ฌด๊ด ํต๊ณผ).
- 1์ด ๋์ ์๋ฌด ์กฐ์ ์์ด ๊ธฐ๋ค๋ฆฐ๋ค.
- ๊ฐ์ ์ ํธ๋ฅผ ๋ ๋ฒ์งธ ์ฝ์ด ํ์ ์ด ์ ์ง๋๋์ง(idle ์ฆ๊ฐ ์ค) ํ์ธํ๋ค.
- ๋ ๊ฒ์ฌ์ ํ ํฐ์ด ๋ชจ๋ ์ ํจํ ๋ ๋ณ๊ฒฝ ์กฐ์ ๋ฑ 1ํ๋ง ์คํํ๋ค. ๋ค์ ์กฐ์ ์ ์๋ 1๋ฒ๋ถํฐ ๋ค์ ํ๋ค.
์ด๋ ๊ฒ์ฌ๋ ์คํจํ๋ฉด ์์ ๋ CDP ๋ช
๋ น์ ๋ณด๋ด์ง ์๊ณ HUMAN_ACTIVE๋ก ์ ์ดํ๋ค. ๊ฐ์ง ์คํจ๋ ๋์ผํ๋ค. ์ฝ๊ธฐ ์ ์ฉ ์ํ ํ์ธ์ ํ์ฉํ์ง๋ง navigate, focus, popup-close๋ ๋ณ๊ฒฝ ์กฐ์์ผ๋ก ์ทจ๊ธํ๋ค.
2. ๋ธ๋ผ์ฐ์ ์ ํ ์์
์๋ ์์๋ฅผ ๊ณ ์ ํ๋ค. ์๋ ๋จ๊ณ๊ฐ ์ฑ๊ณตํ๋ฉด ๋ค์ ๋จ๊ณ๋ก ๊ฐ์ง ์๋๋ค.
- ์คํ ์ค์ธ ๋ชจ๋ Chrome/Chromium ํ๋ก์ธ์ค์์
--remote-debugging-port์--user-data-dir๋ฅผ ์กฐ์ฌํ๋ค. - ๊ฐ ์ด์์๋ endpoint์
/json/list๋ฅผ ์ฝ๊ณ , ์ ํํ ์ฌ์ดํธ URL๊ณผ ๋ก๊ทธ์ธ ๋ง์ปค๊ฐ ์๋ ํญ์ ์ฐพ๋๋ค. - ๋ก๊ทธ์ธ๋ ์ ํํ ํญ์ด ์์ผ๋ฉด ๊ทธ ํญ ํ๋์ raw CDP attachํ๋ค. ์ ์ฒด ๋ธ๋ผ์ฐ์ ๋ฅผ enumerateํ๋
connectOverCDP๋ ์ฌ์ฉํ์ง ์๋๋ค. - ๊ฐ์ ์์ ํ๋กํ์ Chrome ํ๋ก์ธ์ค๊ฐ ์ด์ ์๋๋ฐ CDP๋ง ์ ๊น ๋ฌด์๋ต์ด๋ฉด ์ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ด์ง ์๋๋ค. ๊ธฐ๋ค๋ฆฐ ๋ค ์ฌํ์ธํ๋ฉฐ ์ฌ์คํํ์ง ์๋๋ค.
- ๋์ ํญ์ด ์์ผ๋ฉด ์ ํญ์ด๋ ์ ์ฐฝ์ ๋ง๋ค์ง ์๋๋ค. ์ ํํ ์ฌ์ดํธยทprofileยทendpoint๊ฐ ์ด๋ค ๊ฒ์ด์๋์ง ๋ณด๊ณ ํ๊ณ
HANDOFFํ๋ค. - ํธํ๋๋ ๊ด๋ฆฌ ๋ธ๋ผ์ฐ์ ํ๋ก์ธ์ค๊ฐ ์๋๋ผ๋ ๋ก๊ทธ์ธ ํ๋ฆ์ด
start, ์ ๋ธ๋ผ์ฐ์ , ์ ์ฐฝ, ์ ํญ์ ์๋ ์คํํ์ง ์๋๋ค. ๊ธฐ๋ํ site/profile/endpoint์managed_browser_missing์ ๋ณด๊ณ ํ๊ณHANDOFFํ๋ค. ๋ธ๋ผ์ฐ์ ์์์ ์ฌ์ ์ค๋๊ฐ ๋ณ๋๋ก ๋ช ์ํ ์คํ ์์ฒญ์์๋ง ๋ณ๋ ์ ์ ๋ฌ๋๊ฐ ์ํํ๋ค.
ํฌํธ๋ 9222/9223/9224/9225๋ก ์ถ์ธกํ์ง ์๋๋ค. ๋ค์ ๋ช ๋ น์ผ๋ก ์ค์ ์ด์์๋ endpoint๋ฅผ ๊ตฌํ๋ค.
./scripts/portal_browsers.sh status
./scripts/portal_browsers.sh cdp saramin
./scripts/portal_browsers.sh cdp jobkorea
./scripts/portal_browsers.sh cdp linkedin
๊ธ์ง:
- ๋งค ์๋๋ง๋ค Chrome ์คํ
- ๋ก๊ทธ์ธ ํ๋ฆ์์
scripts/portal_browsers.sh start์๋ ์คํ - ๋งค ์ฌ์๋๋ง๋ค ์ ํญ ์์ฑ
- ๋์ ํญ์ด ์๋ค๊ณ
new_page/์ ํญ์ผ๋ก ๋ก๊ทธ์ธ ํ์ด์ง ์์ฑ - ๊ฐ์ ํ๋กํ๋ก ๋ Chrome ์คํ
- ์ค์ ํฌํธ๊ฐ ์ฃฝ์๋ค๋ ์ด์ ๋ง์ผ๋ก ๋ก๊ทธ์ธ ์ธ์ ์์ ํ์
- ํ ์ฌ์ดํธ ๋ก๊ทธ์ธ ์คํจ ๋๋ฌธ์ ๋ค๋ฅธ ์ฌ์ดํธ ์ฐฝ๊น์ง restart
3. AI ์ฌ์ฉ ํ์
AI๊ฐ ์กฐ์๊ถ์ ์ป์ ๋์ ํญ ํ๋์๋ง ๋ฐฐ์ง๋ฅผ ๋ถ์ธ๋ค.
export VH_BUSY_AGENT="Claude" # Codex ๋๋ Hermes๋ก ์ค์ ์คํ ์ฃผ์ฒด๋ฅผ ๊ธฐ๋ก
export VH_BUSY_TASK="login:<saramin|jobkorea|linkedin>"
raw_cdp.attach()๊ฐ ํ๋ฉด ์๋จ์ DOM id vh-automation-badge๋ฅผ ์ฃผ์
ํด์ผ ํ๋ค. attach์ ๋ฐฐ์ง ์ฃผ์
์ ๊ธฐ์กด ์ฝ๋์์ best-effort์ด๋ฏ๋ก, ์ฒซ click/type/navigate ์ ์ DOM์์ ๋ฐฐ์ง ์กด์ฌ๋ฅผ ์ง์ ์ฌํ์ธํ๋ค. ๋ฐฐ์ง๊ฐ ์์ผ๋ฉด ์ด๋ค ๋ณ๊ฒฝ ์กฐ์๋ ํ์ง ์๊ณ HANDOFFํ๋ค. ๋ฐฐ์ง ๋ฌธ๊ตฌ์๋ ์คํ ์ฃผ์ฒด์ ์์
์ ํ์ํ๋ค. ๋ฐฐ์ง๋ ํด๋ฆญ์ ๊ฐ๋ฆฌ์ง ์์์ผ ํ๋ฉฐ ํ์ด์ง ์ด๋ ํ ๋ค์ ๋ํ๋์ผ ํ๋ค.
- ๋ฐฐ์ง๊ฐ ์ด๋ฏธ ์์ผ๋ฉด ์ ๋ฐฐ์ง๋ฅผ ์์ง ๋ง๊ณ ๋ด์ฉ๋ง ๊ฐฑ์ ํ๋ค.
- ์ฌ๋์ด ์กฐ์์ ์์ํ๋ฉด AI๋ ์ฆ์ ๋ฌด์กฐ์์ผ๋ก ์ ํํ๋ค. ๋ฐฐ์ง๋
์ฌ๋ ๋ก๊ทธ์ธ ๋๊ธฐ ยท AI ๋ฌด์กฐ์์ฒ๋ผ ์ํ๋ฅผ ๋ฐ๊พผ๋ค. HANDOFF์์๋ fresh lease/idle mutation guard๊ฐ ํ์ฉํ ๋๋ง ์๋ title๊ณผ ๋ฐฐ์ง๋ฅผ ๋ณต์ํ๊ณ CDP WebSocket๋ง ๋ซ๋๋ค. ์ฌ๋์ด ๋ค์ ํ๋ํด cleanup guard๊ฐ ๋งํ๋ฉด UI๋ฅผ ๊ฑด๋๋ฆฌ์ง ์๊ณcleanup_pending=true๋ฅผ ๋ณด๊ณ ํ ๋ค WebSocket๋ง ๋ซ๋๋ค.- ๋ก๊ทธ์ธ๋ ํญ, ์ฐฝ, ๋ธ๋ผ์ฐ์ ํ๋ก์ธ์ค๋ ์ ๊ฑฐํ์ง ์๋๋ค.
4. ๋ก๊ทธ์ธ ์คํ ์์
๋์ ์ฑ๋์ ์ ๋ถ ์ ํ ๋ค ํ ๋ฒ์ ์ ๊ฒํ๋ค. ํ๋ฆ ์ค๊ฐ์ ์ฌ์ดํธ๋ง๋ค ๋ค๋ฆ๊ฒ ๋ก๊ทธ์ธํ์ง ์๋๋ค.
- ์ธ ์ฌ์ดํธ์ ๊ธฐ์กด ํญ๊ณผ ๋ก๊ทธ์ธ ๋ง์ปค๋ฅผ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ํ์ธํ๋ค.
- ๋ก๊ทธ์ธ๋ ์ฑ๋์ ๊ทธ๋๋ก ๋ณด์กดํ๊ณ ๋ค์ ๋ก๊ทธ์ธํ์ง ์๋๋ค.
- ๋ก๊ทธ์์ ์ฑ๋์ ํ์ฌ target์ ๊ฒ์ฆ๋ ๋ก๊ทธ์ธ ํผ์ด ์์ผ๋ฉด ๊ทธ๋๋ก ์ฌ์ฉํ๋ค. ํนํ LinkedIn
/uas/login-cap์ username/password ํ๋๊ฐ ๋ชจ๋ ์์ผ๋ฉด ๊นจ์ง/uas/login์ผ๋ก ๊ฐ์ ์ด๋ํ์ง ์๋๋ค. ํ์ฌ ํผ์ด ์์ ๋๋ง ๋์ผ target์์ ๊ณต์ ๋ก๊ทธ์ธ ํ๋ฉด์ผ๋ก 1ํ ์ด๋ํ๋ฉฐ ์ page/context/browser๋ฅผ ๋ง๋ค์ง ์๋๋ค. - ์ ์ฅ ์๊ฒฉ์ฆ๋ช
์ ๊ณต์ฉ macOS Keychain ์๋น์ค
valuehire.portal_credentials์์ ์คํ ํ๋ก์ธ์ค ์์ผ๋ก๋ง ์ฝ๊ณ ๋์ผ target์ ํผ์ 1ํ ์ ์ถํ๋ค..env.local์ Keychain ์ด๊ธฐ ์ ์ฌ์ฉ์ด๋ฉฐ, ์คํ ๋ shell ์ธ์๋ก ์๊ฒฉ์ฆ๋ช ์ ๋ค์ ์ฃผ์ ํ์ง ์๋๋ค. ๋น๋ฐ๊ฐ์ stdout, shell ์ธ์, ์ฐ์ถ๋ฌผ, ๋ชจ๋ธ ๋ํ์ ๋ฃ์ง ์๋๋ค. - ์ ์ถ ์งํ fresh DOM๊ณผ URL์ ์ฝ์ด ๋ณด์ ์ฑ๋ฆฐ์ง๋ฅผ ๋จผ์ ํ์ ํ๋ค. captcha/2FA/checkpoint/์ด์ ์ ๊ทผ์ด๋ฉด ์ฆ์
HUMAN_AUTH๋ก ๋ฐ๊พธ๊ณ ์ ์ถยทํด๋ฆญ์ ๋ฉ์ถ๋ค. LinkedIn ์ธ์ ์ถฉ๋์ด๋ฉด ์ฐฝ์ ํ๋ฉดํํ์ง ์๊ณ terminalAUTH_CONFLICT๋ก ์ค๋จํ๋ค. - ์ฑ๋ฆฐ์ง๋ฅผ ํ ๋ฒ ํ๋ฉดํํ ๋ค
HUMAN_AUTH๋ก ์ง์ ํ๋ค.HUMAN_AUTH์ค navigate/reload/back/click/type/submit/popup-close/close/focus/new-page๋ ๊ธ์ง๋ค. ํ์ฌ URLยทfresh ๋ก๊ทธ์ธ ๋ง์ปคยทOS idle์ ์ฝ๋ ๊ฒ ์ธ์๋ ํ์ง ์๋๋ค. - ์ฌ๋์ด ํด๊ฒฐํ ๋๊น์ง ์๊ฐ์ ํ ์์ด 5์ด ์ด์ ๊ฐ๊ฒฉ์ผ๋ก ์ฝ๊ธฐ ํด๋ง๋ง ํ๋ค. ์ฑ๊ณต ๋ง์ปค์ OS idle 15์ด๋ฅผ ๋ชจ๋ ํ์ธํ ๋ค ์ฌ๊ฐํ๋ค.
ํ์ฌ ์ ์ฅ์์์ ๊ธ์ง๋ ๊ณผ๊ฑฐ ์คํ๊ธฐ
tools.multi_position_sourcing.portal_login์ ๋ณด์กด ๋ชจ๋๊ฐ ์๋๋ฏ๋ก ์ฌ์ฉ ๊ธ์ง๋ค. ์ด ์คํ๊ธฐ๋ ์ page/context๋ฅผ ๋ง๋ค๊ณ ์ข
๋ฃ ์ page/context๋ฅผ ๋ซ์ ์ ์์ผ๋ฉฐ LinkedIn์์ ์ ์ฒด connectOverCDP๋ฅผ ์ฌ์ฉํ๋ค. ๋ฐ๋ผ์ ์ด ์คํฌ์ ํ์ค ์คํ๊ธฐ๋ก ํธ์ถํ๋ฉด ์ ๋๋ค.
์์ ํ ๋ก๊ทธ์ธ ๊ฒฝ๋ก๋ ๋ค์ ์กฐ๊ฑด์ ๋ชจ๋ ์ถฉ์กฑํด์ผ ํ๋ค.
tools.multi_position_sourcing.raw_cdp๋ก ๊ธฐ์กด target ํ๋์๋ง attach- ๋ธ๋ผ์ฐ์ contextยทpageยท์ ํญ ์์ฑ 0ํ
page.close(),context.close(),browser.close()ํธ์ถ 0ํ- ์ฌ๋ ๊ฐ์ ๋๊ธฐ์๊ฐ ๋ฌด์ ํ; ์ธ๋ถ ์ค๋จ ์์๋ WebSocket๋ง ํด์
- ๋ชจ๋ ์ฌ๋ ์๋ด๋ฅผ ์ฌ์ด ํ๊ตญ์ด๋ก ํ์
์ด ์กฐ๊ฑด์ ์ถฉ์กฑํ๋ ์๋ ๋ก๊ทธ์ธ ์ด๋ํฐ๊ฐ ํ์ฌ ์คํํ๊ฒฝ์์ ํ์ธ๋์ง ์์ผ๋ฉด ์ํํ ๊ณผ๊ฑฐ ์คํ๊ธฐ๋ก ๋์ฒดํ์ง ์๋๋ค. ๊ธฐ์กด ์ธ์
์ ๋ณด์กดํ๊ณ ๋์ผ ํญ์ ์ ์ login session guard์ HUMAN_AUTH๋ก ๋๊ธด๋ค. ๋ ๊ฑฐ์ ์ฌ๋ ๋๊ธฐ ํจ์๊ฐ human_auth_runner_required๋ฅผ ๋ฐํํ๋ฉด ์ด๋ ์ค๋จ ์ ํธ๊ฐ ์๋๋ผ ์ ํํ target/window ์๋ณ์ ๊ฐ์ถ ์ ์ ๋ฌ๋๋ก ์ ํํ๋ผ๋ fail-closed ์ ํธ๋ค. โ์๋ ๋ก๊ทธ์ธ์ ํ๋คโ๊ณ ๊ฑฐ์ง ๋ณด๊ณ ํ์ง ์๋๋ค.
์ ์ session guard ์คํ๊ธฐ
์๋ ๋ก๊ทธ์ธ๊ณผ ์ฌ๋ ์ธ์ฆ ์ธ๊ณ๋ legacy login ํจ์๋ ์ฆ์ CDP ์คํฌ๋ฆฝํธ๊ฐ ์๋๋ผ ๋ค์ ์ ์ ์ง์
์ ์ผ๋ก ์คํํ๋ค. ๋ ๋ช
๋ น ๋ชจ๋ --agent๋ง ์ค์ ์คํ ์ฃผ์ฒด๋ก ๋ฐ๊พธ๋ฉฐ ClaudeยทCodexยทHermes๊ฐ ๊ฐ์ ์ฝ๋์ Keychain์ ์ด๋ค. ์คํ๊ธฐ๋ site lease๋ฅผ ๋จผ์ ํ๋ํ๊ณ , ์ ์ ์ฐจ๋ก ์ฐพ์ ๊ธฐ์กด target ํ๋์๋ง attachํ๋ค. ์ ํํ target์ด ์ฌ๋ฌ ๊ฐ๋ฉด --target-id๋ก ํ๋๋ฅผ ๋ช
์ํ๊ณ , ์์ผ๋ฉด ๋ง๋ค์ง ์๋๋ค.
PYTHONPATH=. python3 -m tools.multi_position_sourcing.session_guard auto-login \
--site linkedin_rps \
--agent Codex \
--target-id '<existing-target-id>'
auto-login์ ๋ก๊ทธ์ธ๋ target์ด๋ฉด ์กฐ์ 0ํ, ๊ธฐ์กด login-cap ํผ์ด๋ฉด ๊ทธ ํผ์์๋ง ์๊ฒฉ์ฆ๋ช
1ํ ์ ์ถ, captcha/2FA/checkpoint๋ฉด ์ ์ถ 0ํ HUMAN_AUTH, ๋ฉํฐ์ธ์
์ด๋ฉด ๊ธฐ๋ณธ HUMAN_AUTH(์ธ์
์ถฉ๋, ์ ์ถ 0ํ), ์ฐ๊ฒฐ ์ค๋ฅยทํ๋ ์ค์ข
์ด๋ฉด SELECTOR_DRIFT๋ก ์ข
๋ฃํ๋ค. ๊ฐ์ ์คํจ๋ฅผ ์์ธ ๋ณ๊ฒฝ ์์ด ๋ฐ๋ณตํ์ง ์๋๋ค. ๊ฐ์ ํฌํธ๋ฅผ ์ ์ธํ Chrome์ด ์ฌ๋ฌ ๊ฐ๋ฉด ์ ํํ 127.0.0.1:<port> LISTEN PID๋ก LinkedIn ํ๋ก์ธ์ค๋ฅผ ๊ณ ๋ฅด๊ณ 0๊ฐ/์ฌ๋ฌ ๊ฐ๋ฉด ์ค๋จํ๋ค.
์ค๋ ๋ช
์ ๊ธฐ๊ธฐ ์ ํ(--owner-takeover, SOT26 INV8, 2026-07-31)
์ฌ์ฅ๋์ด ์ด ๊ธฐ๊ธฐ์์ ๋ก๊ทธ์ธํ๋ผ๊ณ ๋ช
์์ ์ผ๋ก ์ง์ํ ๊ฒฝ์ฐ์๋ง --owner-takeover๋ฅผ ๋ถ์ธ๋ค.
PYTHONPATH=. python3 -m tools.multi_position_sourcing.session_guard auto-login \
--site linkedin_rps \
--agent Codex \
--owner-takeover
- ์ด ํ๋๊ทธ๊ฐ ์์ผ๋ฉด ๋ฉํฐ์ธ์ (์ธ์ ์ถฉ๋) ์ ํธ๋ฅผ ์ด์ ๋ก ๋ฉ์ถ์ง ์๊ณ ์๊ฒฉ์ฆ๋ช ์ ์ถ๊น์ง ์งํํ๋ค. ๋ค๋ฅธ ๊ธฐ๊ธฐ์ ์ธ์ ์ LinkedIn ์์ฒด ๋จ์ผ์ข์ ์ ์ฑ ์ผ๋ก ์๋ ๋ฌดํจํ๋๋ฉฐ, ๋ณ๋ ๋ก๊ทธ์์ API๋ฅผ ํธ์ถํ์ง ์๋๋ค(์ ์ถ์ ๋ง์ง ์๋ ๊ฒ๋ง์ผ๋ก ์ถฉ๋ถ).
- ์ง์ง ์บก์ฐจยท2FAยทcheckpoint๋ ์ด ํ๋๊ทธ์ ๋ฌด๊ดํ๊ฒ ํญ์ ๋ฉ์ถ๋ค โ ์ค๋ ์ง์์ ๋์์ด ์๋๋ค.
- ํ๋๊ทธ ์์ด ์คํํ๋ฉด ์ง๊ธ๊น์ง์ฒ๋ผ ์ธ์ ์ถฉ๋ ์ ๊ทธ๋๋ก ๋ฉ์ถ๋ค(ํ๊ท ์์, ๊ธฐ๋ณธ๊ฐ ์์ ).
PYTHONPATH=. python3 -m tools.multi_position_sourcing.session_guard human-auth \
--site linkedin_rps \
--agent Codex \
--target-id '<existing-target-id>'
์ด ๋ช
๋ น์ lease ์ถฉ๋์ด๋ HUMAN_ACTIVE๋ฅผ ์ข
๋ฃ ์ค๋ฅ๋ก ์ทจ๊ธํ์ง ์๊ณ ๋ธ๋ผ์ฐ์ ๋ฌด์กฐ์ ์ํ๋ก ๊ธฐ๋ค๋ฆฐ๋ค. ํ์ฉ ์ํ๊ฐ ๋๊ณ ์ผ๋ฐ ๋ก๊ทธ์ธยท๋ณด์ ์ฑ๋ฆฐ์ง์ผ ๋๋ง ์ ํํ ์ฐฝ์ 1ํ ํ์ํ ๋ค locator JSON์ ์ถ๋ ฅํ๊ณ , HUMAN_AUTH ๋์ timeout ์์ด ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๊ธฐ๋ค๋ฆฐ๋ค. ์ธ์
์ถฉ๋์ด๋ฉด ์ฐฝ์ ํ์ํ์ง ์๊ณ AUTH_CONFLICT๋ก ์ข
๋ฃํ๋ค. visible marker๋ exact window ์ฆ๋ช
์ด ์คํจํ๋ฉด tracebackยทfirst-window fallbackยท์์ focus ์์ด handoff_failed์ exact_window_presentation_failed๋ฅผ ๋ฐํํ๋ค. ์ ์ ์๋ฃยท๋ช
์์ stopยทCtrl-Cยทํ์/์ถ๋ ฅ/๋๊ธฐ ์์ธ ๋ชจ๋์์ fresh guard๋ก title/๋ฐฐ์ง cleanup์ ์๋ํ๊ณ , ๋งํ๋ฉด cleanup_pending์ผ๋ก ๋ ์ฑ ์ฐฝยทํญยทํ๋กํ์ ์ ์งํ๊ณ CDP ์ฐ๊ฒฐ๋ง ํด์ ํ๋ค.
์ธ์
์ ์ง๋ ์๋ ์ ์ ์ง์
์ ๋ง ์ด๋ค. --safe-target-json์ ์ฌ๋์ด ์ฌ์ ๊ฐ์ฌํ ์ ํํ ๊ธฐ์กด target์ ๋์ผ originยทGETยท_selfยท๋ฌด๋ฃ ์ฝ๊ธฐ ์ ์ฉ ๋งํฌ ๋ ์ฝ๋์ฌ์ผ ํ๋ค. ์ต์ํ target_id, source_url, selector, destination_url, method, target_attr, download, dedicated_tab, clean_form, previously_opened_free, risk_labels๋ฅผ ๋ด๋๋ค. ๋ ์ฝ๋๊ฐ ์์ด๋ ์คํ๊ธฐ๊ฐ ์ํ URL/selector denylist, ๋์ผ origin, fresh DOM link ์์ฑ, target id, navigation history ์ถ๊ฐยท๋ณต์์ ๋ค์ ์ฆ๋ช
ํ๋ค. ํ์ผ์ด ์๊ฑฐ๋ ๊ฐ/์ฆ๋ช
์ด ํ๋๋ผ๋ ํ๋ฆฌ๋ฉด fail-closed SKIPํ๋ค.
PYTHONPATH=. python3 -m tools.multi_position_sourcing.session_guard keepalive \
--site linkedin_rps \
--agent Codex \
--safe-target-json '<pre-audited-safe-target.json>'
keepalive๋ ๋์ผ target์ allowlist ๋งํฌ 1ํ click๊ณผ Page.navigateToHistoryEntry(previous_entry) Browser Back ์๋ณต๋ง ํ์ฉํ๋ค. URLยทselector๋ ์ต๋ 4ํ percent-decodeํ ํ๋ฉด๊น์ง ์ํ ํ ํฐ์ ๊ฒ์ฌํ๊ณ , ๋จ์ percent triplet์ ๊ฑฐ๋ถํ๋ค. click๊ณผ Back์ ๋น๋๊ธฐ ์ด๋์ exact targetยทURLยท๋ก๊ทธ์ธยทhistory๋ฅผ ์ฐ์ 2ํ ์์ ํ์ธํ๋ฉฐ auth probe ์งํ target์ ๋ค์ ์ฝ๋๋ค. ์ ํญยท์ ์ฐฝยทgoto(source_url) fallbackยท์ฌ์๋๋ ์๋ค.
5. ์ฌ์ดํธ๋ณ ๊ฒฐ์ ์ ์ฆ๋ช
URL ํ๋๋ง์ผ๋ก ๋ก๊ทธ์ธ ์ฑ๊ณต์ ์ ์ธํ์ง ์๋๋ค. fresh DOM์์ ์๋ ์ฆ๊ฑฐ๋ฅผ ํ์ธํ๋ค.
์ฌ๋์ธ
- ๊ธฐ์
ํ์ talent pool:
https://www.saramin.co.kr/zf_user/memcom/talent-pool/main/search - ์ฑ๊ณต: ๊ณ์ ๋ช
๋๋
๋ก๊ทธ์์์ด ๋ณด์ด๊ณ , ๊ฒ์ ํ๋ฉด์input.search_input,#career_min,#career_max๊ฐ ์กด์ฌํ๋ค. - ์คํจ: ๊ณ์ ๋ช
์์ด
๋ก๊ทธ์ธ | ํ์๊ฐ์, ๊ธฐ์ ํ์ auth ํ๋ฉด, ์ง์๋๋ tutorial redirect. - ๋ก๊ทธ์ธ์ ๋ฐ๋์
ut=c๊ธฐ์ ํ์ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๋ค.
์ก์ฝ๋ฆฌ์
- ์ธ์ฌ๊ฒ์:
https://www.jobkorea.co.kr/Corp/Person/Find - ์ฑ๊ณต: ํค๋์
๋ก๊ทธ์์๊ณผ ๊ธฐ์ ๋ช /๊ณ์ ์ ํธ๊ฐ ์๊ณ ์ธ์ฌ๊ฒ์ ํ๋ฉด์ด ๋ก๋๋๋ค. - ์คํจ:
๋ก๊ทธ์ธ๋งํฌ๋ง ์๊ณ๋ก๊ทธ์์์ด ์๊ฑฐ๋ ๋ก๊ทธ์ธ ํผ์ผ๋ก ์ด๋ํ๋ค. - ์๋ ๋ก๊ทธ์ธ์ ๊ธฐ์ ํ์ ํญ์ ์ ํํ ๋ค ๊ฒ์ฆ๋ ์คํ๊ธฐ๊ฐ ์๊ฒฉ์ฆ๋ช ์ ์ ์ถํ๋ค.
- Recruiter/RPS:
https://www.linkedin.com/talent/ - ์ฑ๊ณต:
/talent/home/search/profile์ด login-cap์ด๋ enterprise-authentication์ผ๋ก ์ด๋ํ์ง ์๊ณ ๋ก๋๋๋ฉฐ, Recruiter ๊ณ์ /๋ฉ๋ด ๋ง์ปค๊ฐ ํจ๊ป ๋ณด์ธ๋ค. URL๋ง์ผ๋ก ์ฑ๊ณต ํ์ ํ์ง ์๋๋ค. - ์คํจ: ์ผ๋ฐ ๋ก๊ทธ์ธ,
/uas/login-cap, authwall, checkpoint. enterprise-authentication/sessions,multiple sign-ins,Only one session์ ์ธ์ ์ถฉ๋์ด๋ค. ์ฝ๊ธฐ ์ ์ฉ ์ฆ๊ฑฐ๋ง ๊ธฐ๋กํ๊ณAUTH_CONFLICT๋ก ์ค๋จํ๋ค. Continue/Confirm ํด๋ฆญยท์๋ ๋ก๊ทธ์ธยท์ฌ๋ ์ธ์ฆ ์ธ๊ณยท์ฌ์๋๋ ๋ชจ๋ ๊ธ์งํ๋ค.
์ฐจ๋จ ๋จ์ด๊ฐ ์ผ๋ฐ ์๋ด๋ฌธ์ ์ฐ์ฐํ ํฌํจ๋ ์ ์๋ค. ์ฐจ๋จ ํ์ ์ ์ค์ ํ๋ฉด๊ณผ URL์ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ํ ๋ฒ ๊ต์ฐจ ํ์ธํ๋ค. ์ค์ ์ฑ๋ฆฐ์ง๊ฐ ๋ง์ผ๋ฉด ์๋ ์ฐํํ์ง ์๋๋ค.
6. ๋ก๊ทธ์ธ ์๋ช ์ธก์ ๊ณผ KEEPALIVE
๊ฐ ์ฌ์ดํธ์ ๋ํด ๋น๋ฐ๊ฐ ์์ด ๋ค์ ๋ฉํ๋ฐ์ดํฐ๋ง ๋ฉ๋ชจ๋ฆฌ ๋๋ ์์ ์ฐ์ถ๋ฌผ์ ๊ธฐ๋กํ๋ค.
{
"site": "saramin|jobkorea|linkedin",
"authenticated_at": "ISO-8601",
"last_verified_at": "ISO-8601",
"session_age_seconds": 0,
"last_keepalive_at": "ISO-8601|null",
"proof": ["login marker names only"],
"state": "AUTHENTICATED"
}
authenticated_at: ์ด๋ฒ ์คํ์์ ๋ก๊ทธ์ธ ๋ง์ปค๋ฅผ ์ฒ์ ํ์ ํ ์๊ฐ. ๊ธฐ์กด ์ธ์ ์ด๋ฉดfirst_observed_authenticated_at์๋ฏธ๋ก ๊ธฐ๋กํ๋ฉฐ ์ค์ ์ฟ ํค ์์ฑ์๊ฐ์ด๋ผ๊ณ ๊ณผ์ฅํ์ง ์๋๋ค.last_verified_at: ๋ก๊ทธ์ธ ๋ง์ปค๋ฅผ ๋ง์ง๋ง์ผ๋ก ์ฌํ์ธํ ์๊ฐ.session_age_seconds: ํ์ฌ ์๊ฐ๊ณผauthenticated_at์ ์ฐจ์ด. ๊ณ์ฐ๊ฐ์ด๋ฉฐ ์ฟ ํค ๋ง๋ฃ์๊ฐ์ผ๋ก ๋ถ๋ฅด์ง ์๋๋ค.- ์ฟ ํค, storage state, ๊ณ์ ID, ๋น๋ฐ๋ฒํธ, profile ๋ณธ๋ฌธ์ ์ด ๊ธฐ๋ก์ ๋ฃ์ง ์๋๋ค.
KEEPALIVE ๊ท์น:
- ๋ง์ง๋ง ๋ก๊ทธ์ธ ํ์ธ ๋๋ keepalive ํ ์ฌ๋์ธยท์ก์ฝ๋ฆฌ์๋ 900์ด(15๋ถ), LinkedIn RPS๋ 1800์ด(30๋ถ) ์ด์ ์ง๋ฌ์ ๋๋ง ๊ฒํ ํ๋ค. ๊ณผ๊ฑฐ์
30๋ถ ํ๋๊ณตํต ์ฃผ๊ธฐ๋ ํ๊ธฐํ๋ค. - keepalive ์ง์ ์ ์ฌ๋ ํ๋์ ์๋ก ์ธก์ ํ๋ค.
HUMAN_ACTIVE,HUMAN_AUTH, ๊ฐ์ง ์คํจ๋ฉด ์ฆ์ SKIPํ๋ค. ์ด์ ์ ์ธก์ ํ idle ๊ฐ์ ์ฌ์ฌ์ฉํ์ง ์๋๋ค. - ๊ธฐ๋ณธ์ SKIP์ด๋ค. ํ์ฌ ํญ์ด AI ์ ์ฉ์ด๊ณ ๋ฏธ์ ์ฅ ํผ/dirty ์ ๋ ฅ์ด ์์ผ๋ฉฐ, ์ ํํ target id๊ฐ ์ ์ง๋๊ณ , ๋์ผ origin์ GET ์ฝ๊ธฐ ์ ์ฉ ๋งํฌ๊ฐ ๊ฒ์ฆ๋ ๊ฒฝ์ฐ๋ง ํด๋ฆญ/Browser Back ์๋ณต์ ํ์ฉํ๋ค.
- ํ์ฉ ๋์์ ์ด๋ฏธ ์ ์์ ์ผ๋ก ๋ฌด๋ฃ ์ด๋ํ๋ ํ๋กํ ์์ธ ๋๋ talent pool/home ์์ allowlist ๋งํฌ๋ค. ์ ํ๋ณด, ์ ๋ฃ/์ฐจ๊ฐ ํ๋กํ,
target=_blank, download, ํ์ , ๋ชจ๋ฌ, ์ ์ฅ, ์ ์, InMail, Send๋ 0ํ๋ค. - ํด๋ฆญ ์ source target id, ์ ํํ source URL,
Page.getNavigationHistory์ ํ์ฌ entry์ ์ด์ entry๋ฅผ ๊ธฐ๋กํ๋ค. - ์ฌ์ดํธ lease token + OS idle 2ํ + 1์ด dwell์ ์ mutation guard๋ฅผ ํต๊ณผํ ๋ค allowlist ๋งํฌ๋ฅผ ๋จ 1ํ ํด๋ฆญํ๋ค.
- ๋์ผ target id, ์์ํ destination URL, fresh ๋ก๊ทธ์ธ ๋ง์ปค, sourceโdestination history๋ฅผ ์ฐ์ 2ํ ํ์ธํ๋ค. auth probe ์งํ target/URL์ ๋ค์ ์ฝ์ด ์ฆ์ checkpoint๋ก redirect๋ ํ๋ณธ์ ์ฑ๊ณต์ผ๋ก ์ธ์ ํ์ง ์๋๋ค. ํ๋๋ผ๋ ๋ค๋ฅด๋ฉด ์ฑ๊ณต์ผ๋ก ๊ธฐ๋กํ์ง ์๊ณ ์ค๋จํ๋ค.
- ๋ณต์ ์ง์ lease/idle mutation guard๋ฅผ ์๋ก ํต๊ณผํ ํ
Page.navigateToHistoryEntry(previous_entry)๋ก Browser Backํ๋ค.goto(source_url)fallback๊ณผ ์ฌ์๋๋ ๊ธ์ง๋ค. - ํด๋ฆญ ํ ์ฌ๋ ํ๋์ด ๊ฐ์ง๋๊ฑฐ๋ ๋ ๋ฒ์งธ guard๊ฐ ์คํจํ๋ฉด Back์ ๋ณด๋ด์ง ์๊ณ
restore_pending=true๋ก ๋์ด ์ฌ๋์๊ฒ ์๋ณดํ๋ค. - ๋์ผ target idยท์ ํํ ์๋ URLยทfresh ๋ก๊ทธ์ธ ๋ง์ปคยท์๋ history entry๊ฐ ์ฐ์ 2ํ ๋ณต์๋ ํ์๋ง
last_verified_at,last_keepalive_at,session_age_seconds๋ฅผ ๊ฐฑ์ ํ๋ค. - ๋ก๊ทธ์ธ ํ๋ฉด์ผ๋ก ๋ฐ๋๋ฉด ๋ฐ๋ณต ์๋ก๊ณ ์นจํ์ง ์๊ณ
AUTH_LOST๋ก ์ ์ดํ๋ค.
KEEPALIVE๋ ์ธ์ ์๊ตฌ ๋ณด์ฅ์ ๋ปํ์ง ์๋๋ค. ์ค์ ๋ก ๊ด์ฐฐํ ์ง์์๊ฐ๋ง ๋ณด๊ณ ํ๋ค.
7. ์ข ๋ฃ์ ์ธ๊ณ
์ ์ ์ข ๋ฃ ์์:
- ๋ง์ง๋ง ๋ก๊ทธ์ธ ๋ง์ปค์ ์ํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋กํ๋ค.
- ์งํ ์ค์ธ ์ฌ๋ ์ ๋ ฅ์ด ์๋์ง ํ์ธํ๋ค.
- ์๋ํ ๋ฐฐ์ง๋ง ์ ๊ฑฐํ๋ค.
- raw CDP WebSocket๋ง ๋ซ๋๋ค.
- ๋ธ๋ผ์ฐ์ , ์ฐฝ, ํญ, ์์ ํ๋กํ์ ๊ทธ๋๋ก ๋๋ค.
- ๋ค์ ์์ ์์๊ฒ ์ฌ์ดํธ๋ณ ์ํ, ์ค์ endpoint, target id, ๋ง์ง๋ง ํ์ธ์๊ฐ, ์ฌ๋ ๊ฐ์ ์ฌ๋ถ๋ง ๋๊ธด๋ค. ๋น๋ฐ๊ฐ์ ๋๊ธฐ์ง ์๋๋ค.
๋ค์ ๋ฌธ์ฅ์ด ์ข ๋ฃ ๋ณด๊ณ ์ ์์ด์ผ ํ๋ค.
๋ธ๋ผ์ฐ์ ๋ณด์กด: ์ฐฝ/ํญ/ํ๋กํ ์ข
๋ฃ 0๊ฑด, CDP ์ฐ๊ฒฐ๋ง ํด์
8. ๋ฐ๋ก๋ณ ์ฆ์ ํ๋
| ์ํฉ | ์ฆ์ ํ๋ |
|---|---|
| ์ฌ๋์ด ๋ก๊ทธ์ธ ํผ์ ํ์ดํ ์ค | HUMAN_AUTH; ๋ฌด์กฐ์. ์ฑ๊ณต ๋ง์ปค + 15์ด ์กฐ์ฉํจ๊น์ง ๋๊ธฐ |
| ์ฌ๋์ด 3์ฌ ํฌํธ ํ๋ฉด์ ๋ง์ง๋ ์ค | HUMAN_ACTIVE; 60์ด idle๊น์ง ์๋ณด |
| ์ฌ๋์ด ์ ํ๋ธ ๋ฑ 3์ฌ ์ธ ํ๋ฉด ์ฌ์ฉ ์ค | ๊ฐ์ ์๋ โ ์๋ณด ์์ด ์งํ(2026-07-20 ์ฌ์ฅ๋ ์ง์) |
| ๋ก๊ทธ์ธ ์ฑ๊ณต ์งํ ์๋ํ ์์ ์ด ๋๋จ | HANDOFF; ๋ฐฐ์ง๋ง ์ ๊ฑฐํ๊ณ ์ฐฝยทํญยทํ๋กํ ์ ์ง |
| CDP ์ค์ ํฌํธ ๋ฌด์๋ต, ๊ฐ์ ํ๋กํ ํ๋ก์ธ์ค ์์กด | ์ฌ์คํ ๊ธ์ง; ์ค์ ํฌํธ ํ์ ํ ๊ธฐ๋ค๋ฆผ |
| ํญ์ด ์ฌ๋ฌ ๊ฐ ์์ | ์ ํ URLยท๋ก๊ทธ์ธ ๋ง์ปค๋ก 1๊ฐ ์ ํ; ๋๋จธ์ง ๋ซ์ง ์์ |
| ๋์ ํญ ์์, ๊ธฐ์กด ๋ธ๋ผ์ฐ์ ์์ | ์ ํญ 0๊ฐยท์ ์ฐฝ 0๊ฐ; ๊ธฐ๋ํ site/profile/endpoint๋ฅผ ํ์ํ๊ณ HANDOFF |
| captcha/2FA/checkpoint | ์์ ํ ๋ฒ ๋ณด์ฌ์ฃผ๊ณ HUMAN_AUTH; ์๋ ์ฐํยท์ฌ์ ์ถ 0ํ |
| LinkedIn ์ธ์ ์ถฉ๋ | AUTH_CONFLICT๋ก ์๊ตฌ ์ค๋จ; Continue/Confirmยท์๋ ๋ก๊ทธ์ธยท์ฌ๋ ์ธ์ฆ ์ธ๊ณยท์ฌ์๋ 0ํ |
| ๋ก๊ทธ์ธ ๋ง์ปค ์์ค | AUTH_LOST; ์๋ ๋ก๊ทธ์ธ 1ํ, ์ฑ๋ฆฐ์ง๋ฉด ์ฌ๋ ์ธ๊ณ |
| keepalive ์ค ์ ๋ฃ/์ ์ฅ ๋ชจ๋ฌ | ๋ซ๊ธฐ์กฐ์ฐจ ์๋์ผ๋ก ๋๋ฅด์ง ๋ง๊ณ ์ค๋จยท๋ณด๊ณ |
9. ์ธ ์์ด์ ํธ ์ค์น
์ ์ฅ์ ์ ๋ณธ์ ์ธ ๋ก์ปฌ ์คํฌ ์์น์ ๊ฐ์ ๋ฐ์ดํธ๋ก ์ค์นํ๋ค.
python3 -m tools.install_login_skill
์ค์น ์์น:
- Claude:
~/.claude/skills/login/ - Codex:
~/.codex/skills/login/ - Hermes:
~/.hermes/skills/login/
์ค์น๊ธฐ๋ login ํด๋์ ์ ๋ณธ ํธ๋ฆฌ(SKILL.md, browser-control-contract.json, scripts/ ์์ฐ)๋ฅผ ์ฌ์ ๊ฒ์ฆํ ํ ์ธ ์์น์ ๊ฐ์ ๋ฐ์ดํธ๋ก ์ฌ๊ท ์ค์นํ๋ฉฐ ๋ค๋ฅธ ์คํฌ์ ๊ฑด๋๋ฆฌ์ง ์๋๋ค. ์ค์น ํ ๊ฐ ์์ด์ ํธ๋ฅผ ์ ์ธ์
์์ ์์ํด login ๋ฐ๊ฒฌ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ค.
10. ์คํ ์ ยทํ ์ฒดํฌ๋ฆฌ์คํธ
์คํ ์ :
-
login์คํฌ์ ์ฝ์๋ค. - ์ฌ๋ ํ๋ ํ์ ์ ์ฑ๊ณตํ๊ณ ์ต๊ทผ ์ ๋ ฅ์ด๋ฉด ์๋ณดํ๋ค.
- ๋ชจ๋ ์คํ ์ค ๋ธ๋ผ์ฐ์ ยท์ค์ CDP endpointยท์์ ํ๋กํ์ ์กฐ์ฌํ๋ค.
- ๋ก๊ทธ์ธ ํ๋ฆ ์ ์ฒด์์ ์ ๋ธ๋ผ์ฐ์ ยท์ ์ฐฝยท์ ํญ์ ๋ง๋ค์ง ์์๋ค.
- AI ๋ฐฐ์ง์ ์คํ ์ฃผ์ฒด์ ์์ ๋ช ์ด ๋ง๋ค.
์คํ ํ:
- ์ฌ์ดํธ๋ณ ๋ก๊ทธ์ธ ๋ง์ปค๋ฅผ fresh DOM์์ ํ์ธํ๋ค.
-
authenticated_at,last_verified_at,session_age_seconds๋ฅผ ๊ธฐ๋กํ๋ค. - ์ฌ๋ ๊ฐ์ ์ค AI ์กฐ์์ 0ํ์๋ค.
- ์ ์ฐฝ์ 0๊ฐ์ด๋ฉฐ ์ ํญ๋ 0๊ฐ์๋ค.
- ๋ธ๋ผ์ฐ์ ยท์ฐฝยทํญยทํ๋กํ ์ข ๋ฃ๋ 0๊ฑด์ด๋ค.
- fresh guard๊ฐ ํ์ฉํ๋ฉด title/๋ฐฐ์ง๋ฅผ ๋ณต์ํ๊ณ , ๋งํ๋ฉด
cleanup_pending์ ๋ณด๊ณ ํ์ผ๋ฉฐ CDP ์ฐ๊ฒฐ๋ง ํด์ ํ๋ค.
11. ๋ค์ค ๊ธฐ๊ธฐ ์ด์ ํจํด โ ์ฃผ๋ ฅ PC์ ๊ฒ์ ์คํ๊ธฐ
์ด ํ๋ Hermes login preflight๊ฐ ๋งค ์คํ๋ง๋ค ์ฝ๋ ๊ธฐ๊ธฐ ์ญํ ์ ๋ณธ์ด๋ค. ๊ธฐ์กด ๋ก๊ทธ์ธ ์ธ์ ์ด ์๋ host๋ฅผ ์ ๋ก๊ทธ์ธ๋ณด๋ค ํญ์ ์ฐ์ ํ๋ค.
| ์ญํ | ํ์ฌ ๊ธฐ๊ธฐ | ๋น๊ณ |
|---|---|---|
| ์ฃผ๋ ฅ PC(primary) | Macmini | Discord gateway์ owner ๊ธฐ๋ณธ ์คํ๊ธฐ |
| AI Search ์คํ๊ธฐ | Macmini, MacBook Pro, WinPC | live session host ์ฐ์ , ์์ผ๋ฉด ํ ์์ |
| LinkedIn ์ฃผ๊ฐ | Macmini(์ฃผ๋ ฅ PC) | ๊ธฐ์กด RPS ์ธ์ ์ฐ์ |
| LinkedIn ์ผ๊ฐ | MacBook Pro ๋๋ WinPC | ํ์ฌ ํด owner ์์์ด ์์ ๋๋ง |
์ต์คํ ์ ๋ ๋ฆฝ ๋ก๊ทธ์ธ ํ๋ฉด ์ฆ๊ฑฐ ์๋ ์ ์ฅ
- ์ ์
session_guard human-auth๋ ์ฌ์ดํธ๋ณ fresh ๋ก๊ทธ์ธ ๋ง์ปค๋กAUTHENTICATED๋ฅผ ์ฆ๋ช ํ ๋ค, ์ฑ๊ณต์ ๋ฐํํ๊ธฐ ์ ์ ํ์ฌ exact target์ ํ๋ฉดยท๋ณธ๋ฌธ ์์์ฆ๊น์ง ์๋ ์ ์ฅํด ๊ฒฐ๊ณผ์evidence์ ํฌํจํ๋ค. ๋ณด์ ์ฑ๋ฆฐ์งยท์ธ์ ์ถฉ๋ ํ๋ฉด์ด๋ ์ฆ๊ฑฐ ์๋ ์ธ์ฆ์ ์ฑ๊ณต์ผ๋ก ๋ฐํํ์ง ์๋๋ค.
PYTHONPATH=. python3 -m tools.multi_position_sourcing.session_guard capture-evidence \
--site <saramin|jobkorea|linkedin_rps> --agent <Claude|Codex|Hermes> \
--task login --mode evidence --target-id <exact-target-id>
- ๋ณ๋ ๋ช
๋ น์ ์ด๋ฏธ ์ธ์ฆ๋ ํ๋ฉด์ ๋ค์ ์ฆ๋ช
ํ ๋ ์ฐ๋ ๊ณต์ฉ ์ง์
์ ์ด๋ค.
human-auth์ ๋ณ๋ ๋ช ๋ น ๋ชจ๋ exit 0 JSON์์capture_status=saved,screenshot_path,text_path,manifest_path, ๋ SHA-256์ ํ์ธํ๋ค. ์คํจํ๋ฉด ๋ก๊ทธ์ธ ์๋ฃ๋ผ๊ณ ๋ณด๊ณ ํ๊ฑฐ๋ ๊ฒ์์ ์์ํ์ง ์๋๋ค. - ์คํ๊ธฐ๋ site lease์ 60์ด ์ฌ๋ ์ฌ์ฉ ๊ฐ์ง๋ฅผ ์์ฒด ํ์ธํ๋ค. ํธ์ถ์๊ฐ ๋ง๋
AUTHENTICATED๋ฌธ์์ด์ด๋ ์ธ๋ถ payload๋ฅผ ์์ ์ฆ๋ช ์ผ๋ก ๋ฐ์ง ์๋๋ค. - ์ ์ฐฝยท์ ํญยทnavigateยทfocusยทclose๋ 0ํ๋ค. ๋ธ๋ผ์ฐ์ ๋ ๋ณด์กดํ๊ณ CDP WebSocket๋ง ํด์ ํ๋ค.