์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

์›นํฌ๋กค๋ง ํ†บ์•„๋ณด๊ธฐ!

xeunnie 2025. 4. 7. 23:37
728x90
๋ฐ˜์‘ํ˜•

๐Ÿ•ธ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋„ ์•Œ์•„์•ผ ํ•  ์›น ํฌ๋กค๋ง์˜ ๋ชจ๋“  ๊ฒƒ

์•ˆ๋…•ํ•˜์„ธ์š”! ์˜ค๋Š˜์€ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ํ•œ ๋ฒˆ์ฏค ๊ถ๊ธˆํ•ดํ–ˆ์„ ์›น ํฌ๋กค๋ง(Web Crawling)์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ณ  ์‹ค์šฉ์ ์ธ ์ด์•ผ๊ธฐ๋ฅผ ํ’€์–ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

'์–ด...? ์›น ํฌ๋กค๋ง์€ ๋ฐฑ์—”๋“œ๋‚˜ ๋ฐ์ดํ„ฐ ์‚ฌ์ด์–ธํ‹ฐ์ŠคํŠธ๋“ค์ด๋‚˜ ํ•˜๋Š” ๊ฑฐ ์•„๋‹ˆ์•ผ?'๋ผ๊ณ  ์ƒ๊ฐํ•˜์…จ๋‹ค๋ฉด, ์˜ค๋Š˜ ๊ธ€์ด ๊ฝค ์ƒˆ๋กœ์šด ์‹œ์•ผ๋ฅผ ์—ด์–ด๋“œ๋ฆด ์ˆ˜ ์žˆ์„์ง€๋„ ๋ชฐ๋ผ์š”. ์ € ์—ญ์‹œ ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ–ˆ๋‹ค๊ฐ€, ํ”„๋กœ์ ํŠธ์—์„œ ์˜์™ธ๋กœ ํ•„์š”ํ•œ ์ˆœ๊ฐ„์ด ์ฐพ์•„์™”๊ณ , ๊ทธ๋•Œ ์ •๋ง ๋งŽ์€ ๊ฑธ ๋ฐฐ์› ๊ฑฐ๋“ ์š”.


๐Ÿ“Œ ์›น ํฌ๋กค๋ง์ด ๋ญ๊ธธ๋ž˜?

๋จผ์ € ์šฉ์–ด ์ •๋ฆฌ๋ถ€ํ„ฐ ํ•˜๊ณ  ๊ฐ€์ฃ .

  • ์›น ํฌ๋กค๋ง(Web Crawling): ์›น ํŽ˜์ด์ง€๋ฅผ ์ž๋™์œผ๋กœ ๋ฐฉ๋ฌธํ•˜๊ณ , ๊ทธ ์•ˆ์˜ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค.
  • ์›น ์Šคํฌ๋ž˜ํ•‘(Web Scraping): ํฌ๋กค๋ง์„ ํ†ตํ•ด ๊ฐ€์ ธ์˜จ HTML์—์„œ ์‹ค์ œ๋กœ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค.

์ฆ‰, ํฌ๋กค๋ง์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ–‰์œ„์ด๊ณ , ์Šคํฌ๋ž˜ํ•‘์€ ๊ทธ ๋ฐ์ดํ„ฐ์—์„œ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•˜๋Š” ๊ณผ์ •์ด์—์š”. ๋‘˜์€ ์ข…์ข… ํ˜ผ์šฉ๋˜์ง€๋งŒ ์—ญํ• ์ด ์กฐ๊ธˆ ๋‹ค๋ฅด์ฃ .


๐Ÿ’ก ์™œ ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ์›น ํฌ๋กค๋ง์„ ์•Œ์•„์•ผ ํ• ๊นŒ?

์ด ์งˆ๋ฌธ์ด ์ œ์ผ ์ค‘์š”ํ•˜์ฃ .

  • ๐Ÿ” SEO ํ…Œ์ŠคํŠธ์šฉ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ™•์ธ: SSR๋œ HTML์— ์ž˜ ๋ฐ•ํ˜”๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์„ ๋•Œ.
  • ๐Ÿ“Š ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ UI ํ…Œ์ŠคํŠธ: ์˜คํ”ˆ API๊ฐ€ ์—†๊ฑฐ๋‚˜ ์ œํ•œ์ ์ผ ๋•Œ, ๋น„๊ณต์‹์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•๋ณดํ•ด์•ผ ํ•  ๋•Œ.
  • ๐Ÿงช ๋””์ž์ธ QA๋‚˜ UI ๋ณ€ํ™” ์ถ”์ : ํŠน์ • ํŽ˜์ด์ง€ ๊ตฌ์กฐ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ๋•Œ.
  • ๐Ÿงต ํผ๋ธ”๋ฆฌ์‹ฑ ์ž๋™ํ™”: ์ปจํ…์ธ ๋ฅผ ๊ฐ€์ ธ์™€ UI์— ์ž๋™ ๋ฐ˜์˜ํ•˜๊ฑฐ๋‚˜ ๋น„๊ตํ•  ๋•Œ.

๊ฐœ๋ฐœ์ž๋กœ์„œ ๋„๊ตฌ๋Š” ๋งŽ์„์ˆ˜๋ก ์ข‹์Šต๋‹ˆ๋‹ค. ํฌ๋กค๋ง์€ ์ƒ๊ฐ๋ณด๋‹ค ์œ ์šฉํ•œ ๋„๊ตฌ์˜ˆ์š”.


๐Ÿ”ง ์›น ํฌ๋กค๋ง ๋„๊ตฌ ์ด์ •๋ฆฌ (ํ”„๋ก ํŠธ์—”๋“œ ๊ด€์ )

1. axios + cheerio ์กฐํ•ฉ (Node ๊ธฐ๋ฐ˜, ๊ฐ€๋ณ๊ณ  ๋น ๋ฆ„)

npm install axios cheerio
import axios from "axios";
import * as cheerio from "cheerio";

const crawl = async () => {
  const { data } = await axios.get("https://example.com");
  const $ = cheerio.load(data);

  const title = $("title").text();
  const headlines = $("h1").map((_, el) => $(el).text()).get();

  console.log("Title:", title);
  console.log("Headlines:", headlines);
};

crawl();

๐Ÿ’ก cheerio๋Š” jQuery ๋ฌธ๋ฒ• ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ, ํ”„๋ก ํŠธ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ํŠนํžˆ ์ต์ˆ™ํ•ฉ๋‹ˆ๋‹ค.


2. puppeteer (ํ—ค๋“œ๋ฆฌ์Šค ๋ธŒ๋ผ์šฐ์ €, ๋ Œ๋”๋ง ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ๋„ ๊ฐ€๋Šฅ)

SPA์ฒ˜๋Ÿผ JavaScript๋กœ ๊ทธ๋ ค์ง€๋Š” ์›น์‚ฌ์ดํŠธ๋„ ์ž˜ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ์–˜๊ฐ€ ํ•„์š”ํ•ด์š”.

npm install puppeteer
import puppeteer from "puppeteer";

const crawl = async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto("https://example.com", { waitUntil: "networkidle2" });

  const data = await page.evaluate(() => {
    return {
      title: document.title,
      h1: Array.from(document.querySelectorAll("h1")).map(el => el.innerText),
    };
  });

  console.log(data);
  await browser.close();
};

crawl();

๐Ÿง  ์ฐธ๊ณ : puppeteer-core๋Š” Chrome ์—†์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ณ , playwright๋Š” ๋ฉ€ํ‹ฐ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.


3. playwright (puppeteer๋ณด๋‹ค ๊ณ ๋„ํ™”๋จ)

โ€ข ๋ฉ€ํ‹ฐ ๋ธŒ๋ผ์šฐ์ € (Chromium, Firefox, WebKit)

โ€ข ๋ชจ๋ฐ”์ผ ์—๋ฎฌ๋ ˆ์ด์…˜ ์ง€์›

โ€ข ํ…Œ์ŠคํŠธ ์ž๋™ํ™”์™€์˜ ๊ถํ•ฉ๋„ ๊ตฟ

npm install playwright
import { chromium } from "playwright";

const crawl = async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto("https://example.com");

  const content = await page.innerText("h1");
  console.log(content);

  await browser.close();
};

crawl();

๐Ÿงฑ ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ ํŒ

ํฌ๋กค๋ง์˜ ์ ˆ๋ฐ˜์€ HTML์„ ์–ด๋–ป๊ฒŒ ํ•ด์„ํ•˜๋А๋ƒ์— ๋‹ฌ๋ ค ์žˆ์–ด์š”.

โ€ข cheerio๋Š” jQuery ์Šคํƒ€์ผ์ด๋ผ ์ง๊ด€์ ์ด์ง€๋งŒ, JS ๋ Œ๋”๋ง๋œ ๋‚ด์šฉ์€ ์•ˆ ๋ณด์ผ ์ˆ˜ ์žˆ์–ด์š”.

โ€ข puppeteer๋‚˜ playwright๋Š” ๋ Œ๋”๋ง๋œ DOM๊นŒ์ง€ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋‹ˆ ๋ณต์žกํ•œ ํŽ˜์ด์ง€์— ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

โ€ข setTimeout, waitForSelector, networkidle2 ๊ฐ™์€ ํƒ€์ด๋ฐ ์ œ์–ด๊ฐ€ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.


โš–๏ธ ์›น ํฌ๋กค๋ง์˜ ์œค๋ฆฌ์™€ ๋ฒ•์  ๊ณ ๋ ค

ํฌ๋กค๋ง์€ ์œค๋ฆฌ์ ์ด๊ณ  ํ•ฉ๋ฒ•์ ์ธ ์„ ์„ ์ง€์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ๊ผญ ๊ณ ๋ คํ•ด ์ฃผ์„ธ์š”.

โ€ข robots.txt ํŒŒ์ผ ํ™•์ธํ•˜๊ธฐ (ํฌ๋กค๋ง ํ—ˆ์šฉ ์—ฌ๋ถ€ ๋ช…์‹œ๋จ)

โ€ข API๊ฐ€ ์žˆ์œผ๋ฉด ๊ทธ๊ฑธ ๋จผ์ € ์“ฐ๊ธฐ

โ€ข ํŠธ๋ž˜ํ”ฝ ํญํƒ„ ์ฃผ์˜ (interval ๋‘๊ณ  ์š”์ฒญํ•˜๊ธฐ)

โ€ข ๋กœ๊ทธ์ธ ๊ธฐ๋ฐ˜ ์ •๋ณด, ๊ฐœ์ธ์ •๋ณด๋Š” ์ ˆ๋Œ€ ์ˆ˜์ง‘ํ•˜์ง€ ์•Š๊ธฐ

โ€ข ์ƒ์—…์  ๋ชฉ์ ์€ ํŠนํžˆ ์ฃผ์˜


๐Ÿงช ์‹ค์ „ ์˜ˆ์ œ: ํŠน์ • ๋ธ”๋กœ๊ทธ ๊ธ€ ์ œ๋ชฉ ๊ธ์–ด์˜ค๊ธฐ

import axios from "axios";
import * as cheerio from "cheerio";

const crawlBlogTitles = async () => {
  const { data } = await axios.get("https://velog.io/@username");
  const $ = cheerio.load(data);
  const titles = $(".sc-bxivhb").map((_, el) => $(el).text()).get();
  console.log(titles);
};

๐Ÿงต ํด๋ผ์ด์–ธํŠธ์—์„œ ์ง์ ‘ ํฌ๋กค๋ง์€ ๋ณด์•ˆ, CORS, ์„ฑ๋Šฅ ๋ฌธ์ œ ๋•Œ๋ฌธ์— ๋ฐฑ์—”๋“œ๋‚˜ ์„œ๋ฒ„๋ฆฌ์Šค ํ•จ์ˆ˜๋กœ ์šฐํšŒํ•˜๋Š” ๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.


๐ŸŽฏ ํ”„๋ก ํŠธ์—”๋“œ์— ๋งž์ถ˜ ํ™œ์šฉ ์•„์ด๋””์–ด

โ€ข UI ํ…Œ์ŠคํŠธ์šฉ ๋ชฉ์—… ๋ฐ์ดํ„ฐ ํ™•๋ณด (API ์—†์Œ โ†’ HTML ํฌ๋กค๋ง โ†’ JSON ๊ฐ€๊ณต)

โ€ข ๋‰ด์Šค ํ‚ค์›Œ๋“œ ํŠธ๋ Œ๋“œ ๋ถ„์„

โ€ข ํฌ๋กค๋ง โ†’ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ €์žฅ โ†’ ํ”„๋ก ํŠธ์—์„œ ์ฐจํŠธ๋กœ ์‹œ๊ฐํ™”

โ€ข ์ •์  ์‚ฌ์ดํŠธ SEO ํ…Œ์ŠคํŠธ ์ž๋™ํ™”

โ€ข ๋ธ”๋กœ๊ทธ ์ž๋™ ์š”์•ฝ๊ธฐ ๋งŒ๋“ค๊ธฐ


๐Ÿ“š ์ถ”์ฒœ ์ž๋ฃŒ & ๋ ˆํผ๋Ÿฐ์Šค

โ€ข ๊ณต์‹ puppeteer ๋ฌธ์„œ

โ€ข playwright docs

โ€ข cheerio docs

โ€ข robots.txt validator


๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐโ€ฆ

์‚ฌ์‹ค ํ”„๋ก ํŠธ์—”๋“œ๋ผ๊ณ  ํ•ด์„œ ์›น์˜ โ€˜๋ณด๋Š” ์ชฝโ€™์—๋งŒ ๊ตญํ•œ๋˜๋ฉด, ์ ์  ์ˆ˜๋™์ ์ธ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๊ธฐ ์‰ฌ์šด ๊ฒƒ ๊ฐ™์•„์š”.

์›น์ด๋ผ๋Š” ๊ณต๊ฐ„์— ์กด์žฌํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์Šค์Šค๋กœ ์ˆ˜์ง‘ํ•˜๊ณ  ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํž˜์„ ๊ฐ–์ถ”๋Š” ๊ฑด, ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“œ๋Š” UI๋ฅผ ๋” ์ฃผ์ฒด์ ์œผ๋กœ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

ํฌ๋กค๋ง์€ ์–ด๋ ต์ง€ ์•Š์ง€๋งŒ, ์•Œ๊ณ  ๋‚˜๋ฉด ํ™•์‹คํžˆ ๊ฐœ๋ฐœ์ž์˜ ๋ฌด๊ธฐ๊ฐ€ ํ•˜๋‚˜ ๋Š˜์–ด๋‚œ ๋А๋‚Œ์ด์—์š”.

ํ˜น์‹œ ๋น„์Šทํ•œ ์ฃผ์ œ๋กœ ๊ด€์‹ฌ ์žˆ์œผ์‹  ๋ถ„์ด ์žˆ๋‹ค๋ฉด, ๋ฐ์ดํ„ฐ ์‹œ๊ฐํ™”๋‚˜ ์ž๋™ํ™”๋„ ํ•จ๊ป˜ ๊ณต๋ถ€ํ•ด๋ณด์‹œ๊ธธ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

728x90
๋ฐ˜์‘ํ˜•