Skip to content

Latest commit

ย 

History

History
67 lines (56 loc) ยท 4.66 KB

50_client.md

File metadata and controls

67 lines (56 loc) ยท 4.66 KB

50. Client โ€” ๋ถ๋งˆํฌ๋ฆฟยท์‹คํ–‰๊ธฐยทํƒ€๊ฒŸ ๋“ฑ๋ก

์ฑ…์ž„: ํƒ€๊ฒŸ ํŽ˜์ด์ง€์— ์ฃผ์ž…๋˜์–ด ์„œ๋ฒ„ ๋ช…๋ น์„ ๋ฐ›์•„ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฌด์†์‹ค ์ „์†กํ•œ๋‹ค. ๋ชจ๋“ˆ: src/arachne/client/{bookmarklet.js, executor.js, install.html} + ํƒ€๊ฒŸ ๋“ฑ๋ก(settings.TARGETS)

โš ๏ธ v1(ํ˜„ ๊ตฌํ˜„, ์•„๋ž˜) = payload.script eval. v2 ๋ชฉํ‘œ = ์ปค๋งจ๋“œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ(specs/16) โ€” ํด๋ผ๋Š” TS ์ธํ„ฐํ”„๋ฆฌํ„ฐ(ES2017), ์„œ๋ฒ„๊ฐ€ ํƒ€์ž… ์ปค๋งจ๋“œ๋กœ ํ†ต์ผ ์ œ์–ด. ๋ถ๋งˆํฌ๋ฆฟ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ v1ยทv2 ๋™์ผ(์ˆœ์ˆ˜ ๋กœ๋”, <script src>๋งŒ) โ€” ๋‹จ v2์—” D-csp-script-src ๋Œ€์‘์šฉ ๋‘ ๋ฒˆ์งธ ํ˜•ํƒœ(์ธ๋ผ์ธ, ๋กœ๋” ์ „์ฒด๋ฅผ ๋ณธ๋ฌธ์— ์ง์ ‘ ์ž„๋ฒ ๋”ฉ โ€” ๋” ์ด์ƒ "์ˆœ์ˆ˜"๊ฐ€ ์•„๋‹˜)๊ฐ€ ์ถ”๊ฐ€๋๋‹ค(docs/00_ARCHITECTURE.md D-csp-script-src, specs/15 ยง4).


ํƒ€๊ฒŸ ๋“ฑ๋ก Contract (settings.TARGETS)

JSON(ํ™˜๊ฒฝ๋ณ€์ˆ˜ TARGETS ๋˜๋Š” .env). 1์ฐจ ๋ฌดUI โ€” ์ •์  ๋“ฑ๋ก:

{ "example.com": { "version": 3, "script": "return {title: document.title}", "actions": [{"type":"scroll","args":{"to":"bottom"}}] } }
  • ์‹คํƒ€๊ฒŸ ์˜ˆ์‹œ(m.news.nate.com ์ตœ์‹ ๋‰ด์Šค)๋Š” tests/e2e์˜ ๋ผ์ด๋ธŒ ํ…Œ์ŠคํŠธ(-m live) ์ฐธ์กฐ.

๋ถ๋งˆํฌ๋ฆฟ (๋กœ๋”, ๋กœ์ง 0 โ€” op ํ† ํฐ๋งŒ ๋ฐ•ํž˜)

javascript:(function(){var s=document.createElement('script');
 s.src='https://<server>/agent/loader.js?op=op_a1b2c3...';document.body.appendChild(s);})();
  • ์„ค์น˜๋ณธ๋ณ„๋กœ op ํ† ํฐ์ด ๋ฐ•ํžŒ ๋ถ๋งˆํฌ๋ฆฟ(์„œ๋ฒ„ ๋ฐœ๊ธ‰, specs/15 ยง1). ์–ด๋А ๋„๋ฉ”์ธ์„œ ์‹คํ–‰ํ•ด๋„ ๊ฐ™์€ op โ†’ ๋„๋ฉ”์ธ ๋„˜๋Š” ํ†ตํ•ฉ.
  • loader.js ๋™์ž‘(specs/15 ยง4): client_id ํ™•๋ณด(localStorage ๋žœ๋คยทGA์‹, ์ง€๋ฌธ ๋ฏธ์‚ฌ์šฉ) โ†’ POST /agent/register(op+client) โ†’ GET /agent/payload โ†’ actions/script โ†’ collect. ๋ชจ๋“  collect ๋ด‰ํˆฌ์— op_idยทclient_idยทtask_id ๋™๋ด‰(๋งค๊ฐœ).

์‹คํ–‰๊ธฐ (executor) โ€” ๋ฌด์†์‹ค + 2๋‹จ๊ณ„

window._aaq = window._aaq || [];          // Matomo _paq ํŒจํ„ด: ๋กœ๋“œ ์ „ ๋ฒ„ํผ๋ง(์œ ์‹ค 0)
// 1) actions ์ˆ˜ํ–‰ โ†’ flush #1
for (const a of payload.actions) await runAction(a);
_aaq.push(['collect', {stage:'action', data: collectedSoFar}]);
// 2) script ์‹คํ–‰ โ†’ flush #2
const result = await new Function('return (async()=>{'+payload.script+'})()')();
_aaq.push(['collect', {stage:'script', data: result}]);
  • ์‹คํ–‰ ์ˆœ์„œ ๋ถˆ๋ณ€: action โ†’ collect โ†’ script โ†’ collect (00_ARCHITECTURE ยง4.3).
  • runAction ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ: scrollยทclickยทwaitยทswipe(m.nate.com ๋žญํ‚น ๋ณธ๋ฌธ ์Šค์™€์ดํ”„, docs/80 GT-real์—์„œ ์š”๊ตฌ). swipe={args:{to,times}} โ€” ํ„ฐ์น˜ ์Šค์™€์ดํ”„(ํ”ฝ์Šค์ฒ˜์—์„  scroll๋กœ ๋™๋“ฑ ์ฒ˜๋ฆฌ). ๊ทธ ์™ธ ๋™์ž‘์€ 2์ฐจ ํ™•์žฅ.

CSP ๋ฌด๋ ฅํ™” ์ „์†ก

  • ๋ช…๋ น ์ˆ˜์‹ : <script src="/agent/payload.js?..."> โ†’ _aaq.push(['payload',{...}]).
  • ๊ฒฐ๊ณผ ์ „์†ก: fetch PUT /api/v1/collect; ์ฐจ๋‹จ ์‹œ ํด๋ฐฑ new Image().src="/api/v1/collect.json?envelope=<urlenc>".
  • ํ•œ๊ณ„(์ด์Šˆ): GET ๋น„์ฝ˜ URL ๊ธธ์ด โ†’ ๋Œ€์šฉ๋Ÿ‰์€ ์ฒญํฌ/์••์ถ•(๊ฒ€์ฆ ์–ด๋ ค์šฐ๋ฉด BLOCKER ๊ธฐ๋ก ํ›„ ์ง„ํ–‰).

v2 ์ธํ„ฐํ”„๋ฆฌํ„ฐ ๋ณด์•ˆ ๊ฐ€๋“œ (โ˜… ์ „์ˆ˜ ๋ฆฌ๋ทฐ ๋ฐ˜์˜ โ€” ์ƒ์„ธ specs/16 ยง8)

v2 loader.v2.js(ts/loader.ts ๋‹จ์ผ ์†Œ์Šค)๋Š” ์‹ ๋ขฐ ๊ฒฝ๊ณ„(์ปจํŠธ๋กค ์„œ๋ฒ„ ์‘๋‹ต)๋ฅผ ํ•˜๋“œ๋‹ํ•œ๋‹ค.

  • script opt-in(D-script-optin): new Function eval์€ ๊ธฐ๋ณธ ์ฐจ๋‹จ, ๋กœ๋” src ?allowScript=1์—์„œ๋งŒ.
  • beacon ์˜ค๋ฆฌ์ง„ ์ œํ•œ(D-beacon-origin): ์†ก์ถœ ๋Œ€์ƒ์€ SERVER_ORIGIN๋งŒ(์ž„์˜ exfil ์ฐจ๋‹จ).
  • ๋‚œ์ˆ˜ crypto(D-client-crypto): client_idยทtask_idยทJSONP ์ฝœ๋ฐฑ๋ช… crypto.getRandomValues ์šฐ์„ .
  • ์ค‘๋ณต ์ฃผ์ž… ๊ฐ€๋“œ: ์ž๊ฐ€ commands.js ๋กœ๋“œยทํด๋ง ๋ถ€์ž‘์šฉ์€ 1ํšŒ๋งŒ(__arachneV2Loaded).
  • op ๋ณด๊ฐ„ ์ƒˆ๋‹ˆํƒ€์ด์ฆˆ(D-op-sanitize): v1 /agent/loader.js?op=๋Š” ์„œ๋ฒ„๊ฐ€ op๋ฅผ ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ ์ •๊ทœํ™” ํ›„ ๋ณธ๋ฌธ ์‚ฝ์ž…(specs/15) โ€” ๋ฐ˜์‚ฌํ˜• ์ธ์ ์…˜ ์ฐจ๋‹จ.
  • iframe ํŽ˜์ด์ง€ ์ œ์–ด(D-frame, v1.1.0): frame_extract/frame_tour๋Š” ๊ฐ™์€ ์ถœ์ฒ˜ ์ƒ์„ธ๋งŒ iframe ๋กœ๋“œ(cross-origin ํด๋ผ ์ฆ‰์‹œ ๊ฑฐ๋ถ€ + ์„œ๋ฒ„ 422). extractItems๋ฅผ iframe contentDocument root๋กœ ์žฌ์‚ฌ์šฉ. ์ตœ์ƒ์œ„ ๋ฌธ์„œ ๋ถˆ๋ณ€ โ†’ ๋กœ๋”/์„ธ์…˜ ๋น„๋‹จ์ ˆ (specs/22).

install.html (๋ฌดUI ์›์น™)

  • ์ตœ์†Œ ์ •์ : ๋ถ๋งˆํฌ๋ฆฟ ๋“œ๋ž˜๊ทธ ์•ˆ๋‚ด ํ•œ ํŽ˜์ด์ง€. โŒ ๋””์ž์ธ ์‹œ์Šคํ…œยทํ”„๋ฆฌ๋ฏธ์—„ UI ๊ธˆ์ง€(๊ณจ๋“œํ”Œ๋ ˆ์ดํŒ…).

Negative (ํ•˜์ง€ ๋ง ๊ฒƒ)

  • โŒ ๋ถ๋งˆํฌ๋ฆฟ์— ์ˆ˜์ง‘ ๋กœ์ง ํ•˜๋“œ์ฝ”๋”ฉ(์„œ๋ฒ„ ๋™์  ๋ฐœํ–‰ ์›์น™).
  • โŒ runAction ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ ๋ฐ– ์ž„์˜ ๋™์ž‘.
  • โŒ install.html ๊ณผ์ž‰ ๋””์ž์ธ.

Golden Test ๋งคํ•‘

  • GT-client: executor 2๋‹จ๊ณ„ flush ์ˆœ์„œยท_aaq ๋ฒ„ํผ๋ง(jsdom ๋˜๋Š” E2E). ์ „์ฒด ํ•ฉ๋ฅ˜๋Š” docs/80 GT-E2E.

ํด๋ผ์ด์–ธํŠธ E2E๋Š” Phase 2(Playwright). 1์ฐจ๋Š” ์„œ๋ฒ„์ธก ์‹œ๋“œ(GT-seed)๋กœ ํ•ฉ๋ฅ˜ ์ฆ๋ช….