๋ค์(Daum) ๊ฒ์ ๊ฒฐ๊ณผ ์์ง์ด ์ ๋๋ค๊ณ ?
์๋ถ๋ ... ์๋ฆฌ๊ฐ ์๋์ผ๋ก ๋์ค๋ ์ด์ ์ ์ง์ง ๋์๋ฒ
์ค๋์ ๋ค์(Daum) ๊ฒ์ ๊ฒฐ๊ณผ ํฌ๋กค๋งํ๋ค๊ฐ ๋ฉํ์ด ๋จผ์ ํฌ๋กค๋ง๋นํ ๋ถ๋ค์ ์ํ ๊ธ์ ๋๋ค.
๋ถ๋ช ํ F12 ๊ฐ๋ฐ์ ๋๊ตฌ๋ก ๋ณด๋ฉด ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ๋กํ๋ ๋ณด์ด๋๋ฐ, ๋ง์ ์ฝ๋๋ก ๊ธ์ผ๋ฉด ๊ฒฐ๊ณผ๊ฐ 0๊ฐ.
"๋ด ์ฝ๋๊ฐ ์๋ชป๋๋? ์ ๋ ํฐ๊ฐ ๋ฐ๋์๋? ์๋ ์ด๋ฐ ์๋ถ๋ ...์ฌ๊ธฐ ๋ถ๋ช ํ ์์์!"
์ด๋ฐ ํผ์ฃ๋ง์ด ๋์๋ค๋ฉด ๋น์ ์ ์ ์์ ๋๋ค. ๋ฌธ์ ๋ ์ฝ๋๊ฐ ์๋๋ผ ๋ค์์ ์๋ถ๋ .. ๊ฐ์ ์ต์ ๋ ๋๋ง ๋ฐฉ์์ ์์ต๋๋ค.
๋ค์(Daum)์ด ์ฐ๋ ์ด ๊ดด์ํ ๋ฐฉ์์ ์ ์ฒด
์์ฆ ๋ค์ ๊ฒ์ ๊ฒฐ๊ณผ HTML์ ๋ฏ์ด๋ณด๋ฉด ์ด๋ฐ ํ๊ทธ๋ค์ด ๋ณด์ผ ๊ฒ๋๋ค.
c-container
c-card class="_cubic hydrated"
c-title.../c-title
/c-card
/c-container
โ div๋ ์ด๋ ๊ฐ๊ณ c-card๋ ๋ญ๋?
์ด๊ฑด ์น ์ปดํฌ๋ํธ(Web Components) ๊ธฐ๋ฐ ๊ตฌ์กฐ์ ๋๋ค.
ํต์ฌ ํค์๋: _cubic hydrated
์ด ํด๋์ค ํ๋์ ๋ชจ๋ ์ง์ค์ด ๋ค์ด ์์ต๋๋ค.
1. Web Components
- HTML์ ์ปดํฌ๋ํธ ๋จ์๋ก ์บก์ํ
- ๋ด๋ถ ๊ตฌ์กฐ๋ ์จ๊ธฐ๊ณ , ์ธ๋ถ์๋ ์ปค์คํ ํ๊ทธ๋ง ๋ ธ์ถ
- React, Vue ๊ฐ์ SPA ์ฒ ํ์ ์์ ์น ํ์ค์ผ๋ก ๊ตฌํ
2. Hydration(ํ์ด๋๋ ์ด์ )
- ์๋ฒ์์ ๋น ๋ผ๋ HTML๋ง ๋จผ์ ๋ด๋ ค์ค
- ์ดํ JavaScript๊ฐ ์คํ๋๋ฉด์ DOM์ ๋ค์ ์กฐ๋ฆฝ
- ํ๋ฉด์ ์ด๋ฏธ ๋ด๋๋ฐ, ๋ด์ฉ์ ๋์ค์ ์๊น
์ฆ, "ํ์ด์ง ๋ก๋ฉ ์๋ฃ = ๋ฐ์ดํฐ ์ค๋น ์๋ฃ" ๊ณต์์ด ๊นจ์ง ๊ฒ์ด ๋ชจ๋ ๋น๊ทน์ ์์์ ๋๋ค.
๋ค์ ๋ฐฉ์์ ์ฅ๋จ์ (์์งํ๊ฒ ๊น๋ณด์)
์ฅ์ (๋ค์ ์ ์ฅ: ๊ฐ์ด๋)
- ๋ฏธ์น ์์ค์ ์์ง ๋ฐฉ์ง (Anti-Scraping): ๊ธฐ์กด .class, div a ๋ฐฉ์ ์ ๋ถ ๋ฌด๋ ฅํ
- PC๋ชจ๋ฐ์ผ์ฑ ํตํฉ ๊ด๋ฆฌ: ํ๋์ ์ปดํฌ๋ํธ๋ก ๋ชจ๋ ํ๋ซํผ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ
- ๋ ์ด์์ ๋ณ๊ฒฝ ์์ : HTML ๊ตฌ์กฐ๋ฅผ ๊ฑฐ์ ์ ๋ฐ๊พธ๊ณ ๋ UI ์คํ(A/B Test) ๊ฐ๋ฅ
๋จ์ (์์งํ๋ ์ฐ๋ฆฌ ์ ์ฅ: ์ง์ฅ)
- ๋ ๋๋ง ๋๊ธฐ ์ง์ฅ: document.readyState ๊ฐ ์๋ฃ๋์ด๋ ๋ฐ์ดํฐ๊ฐ ์์ ์ ์์
- ๊ธฐ์กด ์
๋ ํฐ ์ ๋ฉธ:
document.querySelector('.wrap_cont')๊ฐ์ ๋ฐฉ์์ ๋ ์ด์ ํตํ์ง ์์ - Shadow DOM์ ๋ฒฝ: ์ผ๋ถ ์ปดํฌ๋ํธ๋ ์ธ๋ถ ์ ๊ทผ์ ์ฐจ๋จํ์ฌ Selenium์ผ๋ก๋ ์ ์กํ ์ ์์
๋์ ์ ๋ต: ๋ค ๊ทธ๋ฆด ๋๊น์ง ์ง์ผ๋ณธ๋ค
์ด๋ฐ ๊ตฌ์กฐ์ ๋์ํ๋ ค๋ฉด "๋ค ๊ทธ๋ฆด ๋๊น์ง ์กด๋ฒํ๋ค"๋ ๋ง์ธ๋๊ฐ ํ์ํฉ๋๋ค.
์ ๋ต ์ ๊ทผ
- ์์๊ฐ ์ค์ ๋ก ๋ฑ์ฅํ๋์ง ๊ฐ์
- ์งง์ ์ฃผ๊ธฐ๋ก ๋ฐ๋ณต ์ฒดํฌ
- ๋ฑ์ฅํ๋ ์๊ฐ ์ฆ์ ์ฒ๋ฆฌ
์ค์ ๋์ ๋ก์ง (Chrome Extension / ์ฝ์ ๊ณต์ฉ)
ํต์ฌ ํจ์: ๊ธฐ๋ค๋ฆฌ๋ ๋์ด ์ด๊ธด๋ค
// ์์๊ฐ ๋ํ๋ ๋๊น์ง ๊ฐ์ํ๋ ๋
ํ ํจ์
const waitForElements = async (selector) = {
for (let i = 0; i 10; i++) { // ์ต๋ ์ฝ 3์ด ๋๊ธฐ
const found = document.querySelectorAll(selector).length;
if (found 0) return found; // ๋ฐ๊ฒฌ ์ฆ์ ํ์ถ
await new Promise(r = setTimeout(r, 300));
}
return 0; // ๋๊น์ง ์ ๋์ค๋ฉด ์คํจ
};
๋ค์(Daum) ์ ์ฉ ๋ง์ถค ์ฌ๊ฒฉ ํ
- ๋ ๋๋ง ์๋ฃ ํ์ด๋ฐ์ ์๋ ๋์
- ๊ตฌ์กฐ๊ฐ ์กฐ๊ธ ๋ฐ๋์ด๋ ์์กด ํ๋ฅ ์ด ๋์
- Selenium, Puppeteer, ๋ธ๋ผ์ฐ์ ํ์ฅ ํ๋ก๊ทธ๋จ ์ด๋๋ ์์ฉ ๊ฐ๋ฅ
ํ ๋จ๊ณ ๋ ๋์๊ฐ ํ (๊ณ ๊ธ์์ฉ)
- MutationObserver๋ก DOM ๋ณํ ์ค์๊ฐ ๊ฐ์ง
- Network ํญ์์ JSON API ์ง์ ์ถ์ถ
- ๋ชจ๋ฐ์ผ User-Agent(UA)๋ก ์์ฒญํ์ฌ ๊ตฌ์กฐ ๋จ์ํ
ํ์ง๋ง ์ผ๋จ ๋๊ฒ ๋ง๋๋ ์ฉ๋๋ผ๋ฉด, ์ค๋ ์๊ฐํ waitForElements๊ฐ ๊ฐ์ฑ๋น ์ต๊ฐ์ ๋๋ค.
๋ค์์ด ์๋ฌด๋ฆฌ ์น ์ปดํฌ๋ํธ๋ก ๊ฐ์ธ๊ณ Shadow DOM์ผ๋ก ์ ๊ฐ๋, ๊ฒฐ๊ตญ ๋ธ๋ผ์ฐ์ ์ ๊ทธ๋ฆฌ๋ ์ด์ ๋ฐฉ๋ฒ์ ์์ต๋๋ค.
์ด ๊ธ์ด ๋ค์ ๊ฒ์ ๊ฒฐ๊ณผ ์์ง ๋๋ฌธ์ ๋ชจ๋ํฐ๋ฅผ ํ ๋ ๋ ์ด ๋ปํ ๊ฐ๋ฐ์๋ถ๋ค๊ป ์์ ์ฌ์ด๋ค๊ฐ ๋์๊ธธ ๋ฐ๋๋๋ค.