Skip to content

amazingbutuseless/cartwheel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

39 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Cartwheel; Headless Browser๋ฅผ ์ด์šฉํ•œ ์›น ์‚ฌ์ดํŠธ ๋ณ€๊ฒฝ ํ•œ ๋ˆˆ์— ํŒŒ์•…ํ•˜๊ธฐ

๋ฐ๋ชจ ์ด๋ฏธ์ง€ - oxfordreadingclub.com

์˜†๊ตฌ๋ฅด๊ธฐ ํ•˜๋ฉด์„œ ๋ด๋„ ์•Œ๊ณ  ์‹ถ๋‹ค,

Cartwheel๋Š” Oxford Reading Club Expansion - ์ •ํ™•ํžˆ๋Š” ORC ๋ฒ ํŠธ๋‚จ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด์„œ "๋‹ค๋ฅธ ํ™˜๊ฒฝ์˜ ์›น์‚ฌ์ดํŠธ ๋˜๋Š” ์ด์ „ ๋ฒ„์ „ ์›น์‚ฌ์ดํŠธ์™€ UI ์ฐจ์ด์ ์„ ํ•œ ๋ˆˆ์— ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹๊ฒ ๋‹ค"๋ผ๋Š” ํ•„์š”์„ฑ์„ ๋А๋ผ๊ณ  ์‹œ์ž‘ํ•œ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค.

์ด๋ฒˆ์— ORC ๋ฒ ํŠธ๋‚จ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด์„œ ํฌํƒˆ ์›น์‚ฌ์ดํŠธ์˜ ์ „์ฒด ์›น ํŽ˜์ด์ง€ ์ค‘ 70% ์ •๋„์— ํ•ด๋‹นํ•˜๋Š” ํŽ˜์ด์ง€๋“ค์˜ HTML ๋งˆํฌ์—…, CSS์™€ JS๋ฅผ ์žฌ์ž‘์„ฑ ํ–ˆ๋Š”๋ฐ์š”, ์˜๋„์ ์ธ UI ๋ณ€๊ฒฝ(e.g., ๋””์ž์ธ ์‹œ์Šคํ…œ ๋ฐ˜์˜, ํผ ๊ธฐ๋Šฅ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ๋””์ž์ธ ๋ณ€๊ฒฝ, Footer ์œ„์น˜ ๋ณ€๊ฒฝ, etc)๋„ ์žˆ์—ˆ์ง€๋งŒ, ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” ์ตœ๋Œ€ํ•œ ๊ธฐ์กด ์›น์‚ฌ์ดํŠธ์˜ ๋ชจ์–‘์„ ์œ ์ง€ํ•˜๊ณ ์ž ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ ์ž‘์—… PC์—๋Š” ๋””์ž์ธ ํŒŒ์ผ, ํ˜„์žฌ ๋ฐฐํฌ๊ฐ€ ๋œ ํ™˜๊ฒฝ์˜ ํฌํƒˆ ํŽ˜์ด์ง€, ์ž‘์—… ์ค‘์ธ ํ™˜๊ฒฝ์˜ ํฌํƒˆ ํŽ˜์ด์ง€๊ฐ€ ์—ด๋ ค ์žˆ์–ด์•ผ ํ–ˆ๊ณ , ์‹ฌ์ง€์–ด๋Š” ์ž‘์—… ์ค‘์ธ ํŽ˜์ด์ง€์™€ ์ž‘์—… ์ค‘์ธ ํŽ˜์ด์ง€๋กœ ์˜ํ–ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ค‘์ธ ํŽ˜์ด์ง€๊นŒ์ง€ ๊ฐ™์ด ๋ด์•ผํ•˜๋Š” ๊ณ ํ†ต์ด ๊ณ„์† ๋˜์—ˆ์–ด์š”.

FE๊ฐœ๋ฐœ์ž์˜ ๋ชจ๋‹ˆํ„ฐ - ๋‚˜๋งŒ ์ด๋Ÿฌ๋Š” ๊ฑด ์•„๋‹๊ฑฐ์ž–์•„์š”

๋ณ€๊ฒฝ ์ž‘์—… ์ค‘ ๋ชจ๋‹ˆํ„ฐ ์ƒํ™ฉ; ์ƒ์šฉ ๋ฒ„์ ผ - ์ž‘์—… ๋ฒ„์ ผ - ์ž‘์—…์— ์˜ํ–ฅ์„ ๋ฐ›๋Š” ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋ฅผ ๋™์‹œ์— ํ™•์ธ

ํŽ˜์ด์ง€ ๋ณ„-์ž‘์—… ํžˆ์Šคํ† ๋ฆฌ ๋ณ„-ํ™˜๊ฒฝ ๋ณ„๋กœ ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€ ์—†๋Š”์ง€, ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค๋ฉด ์–ด๋””์— ์–ผ๋งˆ๋‚˜ ์žˆ๋Š”์ง€ ์•Œ๊ณ  ์‹ถ๋‹ค, ์ด์™•์ด๋ฉด ์ข€ ์‰ฝ๊ฒŒ ์•Œ๊ณ  ์‹ถ๋‹ค! ๊ทธ๋Ÿฐ ๋ฐ”๋žŒ์œผ๋กœ Cartwheel - ์˜†๊ตฌ๋ฅด๊ธฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

Cartwheel์€ ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

  1. Crawl a website
    1. ์„ค์ •๋œ ์›น ์‚ฌ์ดํŠธ ์ฃผ์†Œ(e.g., https://local.oxfordreadingclub.com)์— ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.
    2. ์ ‘์†ํ•œ ์›นํŽ˜์ด์ง€์—์„œ ๋ชจ๋“  <a>๋ฅผ ์ฐพ๊ณ , ๊ฑฐ๊ธฐ์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š” ์‚ฌ์ดํŠธ ๋‚ด๋ถ€ ๋งํฌ(i.e., Hostname์ด ๋™์ผํ•œ ์›นํŽ˜์ด์ง€ ์ฃผ์†Œ)๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.
    3. 2์—์„œ ์ฐพ์€ ๋‚ด๋ถ€ ๋งํฌ๋กœ ์ ‘์†ํ•˜์—ฌ, ํ•ด๋‹น ์›นํŽ˜์ด์ง€์— ํฌํ•จ๋œ ๋ชจ๋“  ์‚ฌ์ดํŠธ ๋‚ด๋ถ€ ๋งํฌ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.
  2. Take screenshots; (๊ฐ™์€ ํŽ˜์ด์ง€์— ์ค‘๋ณต ์ ‘์†ํ•˜์ง€ ์•Š๋„๋ก ์ค‘๋ณต์„ ์ œ๊ฑฐ ํ•ด๊ฐ€๋ฉฐ) 2~3์„ ๋ฐ˜๋ณตํ•˜๋ฉฐ ์Šคํฌ๋ฆฐ์ƒท์„ ์ฐ์Šต๋‹ˆ๋‹ค.
  3. Create sitemap; ์Šคํฌ๋ฆฐ์ƒท์„ ์ฐ์€ ํŽ˜์ด์ง€์— ๋Œ€ํ•ด Request Path, ํŽ˜์ด์ง€ ํƒ€์ดํ‹€, ์Šคํฌ๋ฆฐ์ƒท ํŒŒ์ผ ์ •๋ณด๋ฅผ ๋‹ด์€ Sitemap์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  4. Compare the screenshots
    • (๋™์ผํ•œ Request URL์— ๋Œ€ํ•ด ์ด์ „์— ์ฐ์–ด ๋‘” ์Šคํฌ๋ฆฐ์ƒท์ด ์žˆ๋‹ค๋ฉด) ๋‘ ๊ฐœ ์Šคํฌ๋ฆฐ์ƒท์„ ๋น„๊ตํ•˜๊ณ  10% ์ด์ƒ ๋ณ€๊ฒฝ์ด ์žˆ๋‹ค๋ฉด, ๋‹ค๋ฅธ ์˜์—ญ์„ ํ‘œ์‹œํ•˜๋Š” diff ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • (์›น์‚ฌ์ดํŠธ ์„ค์ •์‹œ Remote ํ™˜๊ฒฝ์„ ์„ค์ •ํ–ˆ๋‹ค๋ฉด) ๋ฆฌ๋ชจํŠธ Hostname + Request Path๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ๋ฆฌ๋ชจํŠธ ํ™˜๊ฒฝ ์›นํŽ˜์ด์ง€ ์Šคํฌ๋ฆฐ์ƒท์„ ์ฐ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ๊ณผ ๋ฆฌ๋ชจํŠธ ํ™˜๊ฒฝ์˜ ์Šคํฌ๋ฆฐ์ƒท์„ ๋น„๊ตํ•˜์—ฌ 10% ์ด์ƒ ๋ณ€๊ฒฝ์ด ์žˆ๋‹ค๋ฉด, ๋‹ค๋ฅธ ์˜์—ญ์„ ํ‘œ์‹œํ•˜๋Š” diff ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

Headless Browser๋ฅผ ์ด์šฉํ•œ ํ…Œ์ŠคํŠธ (via Playwright)

Headless Browser == Web Browser - Graphical User Interface

Headless Browser๋Š” GUI ์—†์ด Command-Line Interface (CLI) ๋˜๋Š” Network Communication์„ ์ด์šฉํ•˜์—ฌ ์›นํŽ˜์ด์ง€๋ฅผ ์ œ์–ด ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ €์ž…๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค๋ฅธ Application์— ์›นํŽ˜์ด์ง€ ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜์ง€๋งŒ, ๋ฐ์ดํ„ฐ ์ถ”์ถœ์ด๋‚˜ ์›นํŽ˜์ด์ง€ ํ…Œ์ŠคํŠธ ์šฉ๋„๋กœ๋„ ๋„๋ฆฌ ์‚ฌ์šฉ ์ค‘์ž…๋‹ˆ๋‹ค.

ํŠนํžˆ ์›นํŽ˜์ด์ง€ ํ…Œ์ŠคํŠธ์— ํ—ค๋“œ๋ฆฌ์Šค ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ์ด์œ ๋Š” ํ—ค๋“œ๋ฆฌ์Šค ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ •๋ง๋กœ ๋ธŒ๋ผ์šฐ์ €๋ผ๋Š” ์  ๋•Œ๋ฌธ(!)์ž…๋‹ˆ๋‹ค. ํ—ค๋“œ๋ฆฌ์Šค ๋ธŒ๋ผ์šฐ์ €๋Š” ์ผ๋ฐ˜์ ์ธ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์›นํŽ˜์ด์ง€๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ์™„์ „ํžˆ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์›นํŽ˜์ด์ง€๋ฅผ ํŒŒ์‹ฑํ•˜๊ณ , ๋ Œ๋”๋งํ•˜๊ธฐ ๋•Œ๋ฌธ์—, "๋ธŒ๋ผ์šฐ์ €์™€ ์œ ์‚ฌํ•œ(๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ปจํŠธ๋กค ํ•˜๋Š” ๋ฐฉ์‹์˜)" ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ๋„๊ตฌ๋“ค์ด ์ผ๋ฐ˜์ ์œผ๋กœ ์ œ๊ณตํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ธฐ๋Šฅ, ์˜ˆ๋ฅผ ๋“ค์ž๋ฉด Javascript๋‚˜ AJAX ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Playwright - Chromium, Firefox, WebKit headless browser๋ฅผ ํ•˜๋‚˜์˜ API๋กœ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“  Node ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  1. Headless Browser๋ฅผ ์‹คํ–‰
const browser = await playwright.chromium.launch();

if (ignoreHTTPSErrors) await browser.newContext({ ignoreHTTPSErrors });
  1. ์›นํŽ˜์ด์ง€๋กœ ์ด๋™
const page = await this.browser.newPage();
await page.goto(url);
  1. ์Šคํฌ๋ฆฐ์ƒท ์ƒ์„ฑ
await page.setViewportSize({ width, height });
await page.screenshot({ fullPage, path });

์‚ฌ์šฉ์ž์˜ PC์— ์„ค์น˜ ๋˜๋Š” ์›น ์„œ๋ฒ„ (via Electron)

๋ชฉ์ ์€ ์กฐ๊ธˆ ๋‹ฌ๋ž์ง€๋งŒ ์‚ฌ์‹ค ์˜†๊ตฌ๋ฅด๊ธฐ๋Š” 2017๋…„์— Spindle Weather๋ผ๋Š”, ์ง€๊ธˆ์˜ AWS Alarm Bot์˜ ์ดˆ๊ธฐ ๋ชจ๋ธ์ด๋ผ๊ณ ๋„ ํ•  ์ˆ˜ ์žˆ๋Š” Automatic API Test Application์—๋„ ๋“ค์–ด ์žˆ๋˜ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

Spindle Weather๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฏธ๋ฆฌ ์ •์˜ํ•ด ๋‘” API ์ŠคํŽ™์„ ๊ธฐ์ค€์œผ๋กœ API๊ฐ€ ์ •์ƒ ์‘๋‹ต์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธ
  • ๋ฏธ๋ฆฌ ์ •์˜ํ•ด ๋‘” ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ์›น์‚ฌ์ดํŠธ์—์„œ ์ •์ƒ์ ์œผ๋กœ ๋กœ๊ทธ์ธ์ด ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธ
  • ์›น์‚ฌ์ดํŠธ์— ๋งํฌ๋œ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ •์ƒ HTTP Status๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€๋ฅผ ํ™•์ธ
  • ์›น ์‚ฌ์ดํŠธ๋ฅผ ์Šคํฌ๋ฆฐ์ƒท์œผ๋กœ ๊ธฐ๋กํ•˜๊ณ , ์ง€์ •ํ•œ ์ˆ˜์ค€ ์ด์ƒ์œผ๋กœ ๋ณ€๊ฒฝ์ด ์ƒ๊ธฐ๋Š”์ง€๋ฅผ ํ™•์ธ

์›น ์‚ฌ์ดํŠธ๋Š” PantomJS๋ผ๋Š” ํ—ค๋“œ๋ฆฌ์Šค ๋ธŒ๋ผ์šฐ์ ธ๋ฅผ ์ด์šฉํ•ด์„œ, ์ง€๊ธˆ์˜ ์˜†๊ตฌ๋ฅด๊ธฐ์™€ ๊ฑฐ์˜ ๋˜‘๊ฐ™์€ ์ž‘์—…(ํฌ๋กค๋ง - ์Šคํฌ๋ฆฐ์ƒท ์ƒ์„ฑ)์„ ํ–ˆ๋Š”๋ฐ์š”, ๋ฌธ์ œ๋Š” ์ด ์ž‘์—…์ด ์ €๋ ด์ด ์„œ๋ฒ„์—์„œ ๋Œ์•„๊ฐ€๊ธฐ์—” ์ ํ•ฉํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. Memory Allocate ๋ฌธ์ œ ๋“ฑ์œผ๋กœ ์„œ๋ฒ„๊ฐ€ ์žฅ์•  ์ƒํƒœ์— ๋น ์ง€๊ณ , ์ด๊ฒŒ API ๋ชจ๋‹ˆํ„ฐ๋ง์ฒ˜๋Ÿผ ์ค‘์š”๋„๊ฐ€ ๋†’์€ ์ž‘์—…์— ์˜ํ–ฅ์„ ์ฃผ๊ฒŒ ๋˜๋‹ค๋ณด๋‹ˆ, ๊ฒฐ๊ตญ์—” ์Šคํฌ๋ฆฐ์ƒท๊ณผ ๊ด€๋ จ๋œ ๊ธฐ๋Šฅ์€ ๊ฐœ๋ฐœ๋œ ์ดํ›„ ํ™œ์•ฝ ํ•œ ๋ฒˆ ํ•ด๋ณด์ง€ ๋ชปํ•œ ์ฑ„๋กœ ๋น„ํ™œ์„ฑํ™” ์ƒํƒœ๋กœ ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค.

์ผ๋ ‰ํŠธ๋ก ์—์„œ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ์— ๋Œ€ํ•œ ์ œ์•ฝ์ด ์ค„์–ด ๋“ค์—ˆ๊ณ , ๋ถ€๊ฐ€์ ์œผ๋กœ๋Š” ๊ฐœ๋ฐœ์ค‘์ธ ์›น์‚ฌ์ดํŠธ(localhost)์— ๋Œ€ํ•œ ์Šคํฌ๋ฆฐ์ƒท ์ƒ์„ฑ๊ณผ ๋น„๊ต๊ฐ€ ๊ฐ€๋Šฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ! ํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ! ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ!

๋กœ๊ทธ์ธ ์ดํ›„์˜ ์›นํŽ˜์ด์ง€๋กœ ํ™•์ธ ๋Œ€์ƒ์„ ๋„“ํžˆ๊ธฐ

ํ˜„์žฌ ์˜†๊ตฌ๋ฅด๊ธฐ์—์„œ๋Š” ๋กœ๊ทธ์ธ ์ „ ์‚ฌ์šฉ์ž๊ฐ€ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋Š” ํŽ˜์ด์ง€์— ๋Œ€ํ•ด์„œ๋งŒ ํฌ๋กค๋ง๊ณผ ์Šคํฌ๋ฆฐ์ƒท ์ƒ์„ฑ ๋ฐ ๋น„๊ต๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ phase์—์„œ๋Š” ์›น์‚ฌ์ดํŠธ ์„ค์ •์— ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ๊ธฐ์ž…ํ•˜๊ณ , ํ•ด๋‹น ์ •๋ณด๋ฅผ ํ™œ์šฉํ•ด์„œ ๋กœ๊ทธ์ธ ์ดํ›„ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€์— ๋Œ€ํ•ด์„œ๋„ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๋งŒ๋“ค์–ด ๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

SEO๋ฅผ ๊ณ ๋ คํ•œ ๋งˆํฌ์—… (ํŽ˜์ด์ง€ ์ด๋™์„ ๊ตณ์ด JS๋กœ ํ•ด์•ผ๋งŒ ํ–ˆ๋ƒ์•„!)

๊ฒ€์ƒ‰ ์—”์ง„์„ ๋น„๋กฏํ•˜์—ฌ ์ „ํ†ต์ ์ธ ์›น์‚ฌ์ดํŠธ ํฌ๋กค๋ง์€ ํ™ˆํŽ˜์ด์ง€(์ธ๋ฑ์Šค ํŽ˜์ด์ง€)์—์„œ "์ด๋™ ๊ฐ€๋Šฅํ•œ ๋งํฌ๋ฅผ ์ฐพ๋Š” ๊ฒƒ"๋ถ€ํ„ฐ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํŽ˜์ด์ง€์— ์ด๋™ ๊ฐ€๋Šฅํ•œ ๋งํฌ(<a>)๊ฐ€ ์—†๋‹ค๋ฉด, ํฌ๋กค๋ง ํ•  ์ˆ˜ ์žˆ๋Š” ํŽ˜์ด์ง€ ์ˆ˜๋Š” ์ œํ•œ์ ์ผ ์ˆ˜ ๋ฐ–์— ์—†๊ณ , ์ด์— ๋”ฐ๋ผ์„œ ์›ํ•˜๋Š” ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋ฒ„ํŠผ ๋ชจ์–‘ ๋งํฌ vs ์ง„์งœ ๋ฒ„ํŠผ

Learn more๋ฅผ ๋ˆ„๋ฅด๋ฉด ์‹œ๋ฆฌ์ฆˆ ์†Œ๊ฐœ ํ™”๋ฉด์ด ์žˆ๋Š”๋ฐ, ์™œ ์Šคํฌ๋ฆฐ์ƒท์€ ์—†์„๊นŒ์š”? ์ € Learn more๋Š” ๋ฒ„ํŠผ ๋ชจ์–‘์˜ ๋งํฌ๊ฐ€ ์•„๋‹ˆ๋ผ ์ •๋ง๋กœ ๋ฒ„ํŠผ์ด์—ˆ์Šต๋‹ˆ๋‹ค;

SEO์˜ ๊ธฐ์ดˆ - ํŽ˜์ด์ง€ ๋งํฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์ด๋ ‡๊ฒŒ ๋ฉ๋‹ˆ๋‹ค

"์•ˆ ๋ผ, ์•ˆ ์ฐพ์•„์ค˜, ์ฐพ์•„์ค„ ์ƒ๊ฐ ์—†์–ด, ๋Œ์•„๊ฐ€."์˜€๋˜ ORC ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ

๋‹จ์ˆœ ์›นํŽ˜์ด์ง€ ์ฐจ์ด ํ™•์ธ์ด ์•„๋‹Œ, Behaviour์™€ ๊ทธ์— ๋”ฐ๋ฅธ ๊ฒฐ๊ณผ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•œ UI ํ…Œ์ŠคํŠธํˆด๋กœ ํ™•์žฅ

์ฒ˜์Œ ์˜†๊ตฌ๋ฅด๊ธฐ๋ฅผ "ํ™˜๊ฒฝ-์ž‘์—… ๋ฒ„์ ผ-์˜ํ–ฅ ๋ฐ›๋Š” ์ž‘์—…์˜ ์ฐจ์ด๋ฅผ ํ•œ ๋ˆˆ์— ๋ณด๊ณ  ์‹ถ๋‹ค"๋ผ๋Š” ์ƒ๊ฐ์œผ๋กœ ๋งŒ๋“  ๋งŒํผ, UI ํ…Œ์ŠคํŠธํˆด๋กœ์จ ์˜†๊ตฌ๋ฅด๊ธฐ๋Š” ์•„์ฃผ ์ œํ•œ์ ์ธ ๋ถ€๋ถ„๋งŒ์„ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. ํ—ค๋“œ๋ฆฌ์Šค ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ œ๊ณต ํ•˜๋Š” ๊ธฐ๋Šฅ์˜ ๊ทนํžˆ ์ผ๋ถ€๋งŒ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ์š”, ํ˜„์žฌ ๊ฐœ๋ฐœ์ค‘์ธ ๋‚ด์šฉ์„ ์ข€ ๋” ์•ˆ์ •ํ™” ์‹œํ‚จ ํ›„์—๋Š” ํŠน์ • ํŽ˜์ด์ง€ ์•ˆ์—์„œ Form์„ ์ „์†กํ•˜๊ฑฐ๋‚˜, Javascript ์‹คํ–‰ ํ›„ ๋ณ€๊ฒฝ๋˜๋Š” ํ™”๋ฉด์„ ์ถ”๊ฐ€ ์Šคํฌ๋ฆฐ์ƒท์œผ๋กœ ๋‚จ๊ฒจ ๋‘๋Š” ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ ํ•  ์ƒ์ƒ(...)๋„ ํ•ด๋ดค์Šต๋‹ˆ๋‹ค.

์ธํ„ฐ๋„ท์œผ๋กœ ํ˜ธ์ŠคํŒ… ๋˜์ง€ ์•Š(์•„๋„ ๋˜)๋Š” ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜

์•ž์„œ ์–˜๊ธฐํ–ˆ๋˜ Spindle Weather์™€ ๋˜‘๊ฐ™์ด, ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…์ด ๋งŽ์€ ์›น ์„œ๋ฒ„ ์ž์›์„ ์‚ฌ์šฉํ•ด์„œ ์ข…์ข… ์„œ๋ฒ„๊ฐ€ ์žฅ์•  ์ƒํƒœ๊ฐ€ ๋˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ QMS์—์„œ ๋„์„œ์— ์‚ฌ์šฉ๋œ ๋‹จ์–ด์™€ ๋ฌธ์žฅ์„ ์ถ”์ถœํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” SAT Analyzer์ž…๋‹ˆ๋‹ค. ์•„์ฃผ ๊ฐ„๋‹จํ•œ Natural Language Processing์„ ํ•˜๊ณ  ์žˆ๋Š” ์ด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋™์‹œ์— ์ฑ… 5๊ถŒ์— ๋Œ€ํ•œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ํ•ด๋‘์—ˆ๋Š”๋ฐ, ์ด๋Ÿฐ ์ œํ•œ์„ ๋’€์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋„์„œ์˜ ํŠน์„ฑ์— ๋”ฐ๋ผ์„œ๋Š” ์„œ๋ฒ„๊ฐ€ ๋ป—๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋” ์žˆ๋‹ค๋ฉด Electron์„ ํ™œ์šฉํ•ด์„œ ํ”Œ๋žซํผ์„ ๋ฐ”๊ฟ”๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค!

[๋ถ€๋ก] ์ฒ˜์Œ์œผ๋กœ Electron์„ ์ด์šฉํ•ด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๋ฉด์„œ ์ด๋Ÿฐ ์–ด๋ ค์›€(aka ์‚ฝ์งˆ)์„ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค.

1. Uncaught TypeError: Cannot read property 'getPath' of undefined

์ผ๋ ‰ํŠธ๋ก ์— Main Process์™€ Renderer Process๊ฐ€ ๋”ฐ๋กœ ์กด์žฌํ•˜๊ณ , ๊ฐ๊ฐ์˜ ํ”„๋กœ์„ธ์Šค์—์„œ ์“ธ ์ˆ˜ ์žˆ๋Š” API๊ฐ€ ์ •ํ•ด์ ธ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ชจ๋ฅด๊ณ  ๊ตฌํ˜„๋ถ€ํ„ฐ ํ•˜๋‹ค๋ณด๋‹ˆ ๋ด์•ผ ํ–ˆ๋˜ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ž…๋‹ˆ๋‹ค. ์›น ์‚ฌ์ดํŠธ ์„ค์ •๊ฐ’์ด๋‚˜ ์Šคํฌ๋ฆฐ์ƒท, ์‚ฌ์ดํŠธ๋งต ํŒŒ์ผ ๋“ฑ์˜ ๋ฐ์ดํ„ฐ๋ฅผ Electron์—์„œ ์ง€์ •ํ•œ userData ๋””๋ ‰ํ† ๋ฆฌ์— ์ €์žฅํ•˜๋ ค๊ณ  ํ–ˆ๋Š”๋ฐ ๋ Œ๋” ํ”„๋กœ์„ธ์Šค์—์„œ๋Š” app API๋ฅผ ์ด์šฉ ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด ๊ฒฝ๋กœ๋ฅผ ์กฐํšŒํ•˜๊ฑฐ๋‚˜ ์ ‘๊ทผ ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ ipcMain/ipcRender๋ฅผ ์ด์šฉํ•ด์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ํ˜•์‹์œผ๋กœ ๊ตฌํ˜„์„ ํ–ˆ์ง€๋งŒ, Main Process์— Express๋กœ ์›น์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ณ , ๊ทธ ์›น์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ์š”์ฒญ์„ ์ฃผ๊ณ  ๋ฐ›๋Š” ํ˜•์‹์ด ๋˜์—ˆ์–ด๋„ ์ข‹์•˜์„ ๊ฒƒ ๊ฐ™๋‹ค๋ผ๋Š” ์ƒ๊ฐ์„ ๋’ค๋Šฆ๊ฒŒ ํ•˜๊ธฐ๋„ ํ–ˆ์–ด์š”. ์ด๊ฑด ๋˜๋‹ค๋ฅธ ์‚ฝ์งˆ์ด ๋˜์—ˆ๊ฒ ์ง€์š”;

2. Not allowed to load local resource

์Šคํฌ๋ฆฐ์ƒท์„ userData ๋””๋ ‰ํ† ๋ฆฌ(MacOS ๊ธฐ์ค€์œผ๋กœ ~/Library/Application Support/Electron/)์— ์ €์žฅํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ์ €์žฅ๋œ ์ด๋ฏธ์ง€๋ฅผ ํ™”๋ฉด์— ๋ถˆ๋Ÿฌ ์˜ค๋ ค๊ณ  ํ–ˆ๋”๋‹ˆ(img src=file://), ๋กœ์ปฌ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฑธ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. (์ด๊ฒƒ ๋•Œ๋ฌธ์— 1์—์„œ ์–˜๊ธฐํ•œ ๋Œ€๋กœ Express ์„œ๋ฒ„๋ฅผ ์ง„์งœ ์˜ฌ๋ฆด๊นŒ ๊ณ ๋ฏผํ•จ) ๊ฒฐ๊ตญ์—๋Š” ๋กœ์ปฌ ํŒŒ์ผ์„ Electron์˜ API์ธ, nativeImage๋กœ ๋ถˆ๋Ÿฌ์˜จ ๋‹ค์Œ, base64 ํ˜•ํƒœ๋กœ ์ธ์ฝ”๋”ฉํ•˜์—ฌ ํ™”๋ฉด์— ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

const image = nativeImage.createFromPath(`${ localImagePathInUserData }`);
image.toDataURL();

3. ์—ฌ์ „ํžˆ ์‚ฝ์งˆ ์ค‘; Node module was compiled against a different Node.js version

Native Node modules are supported by Electron, but since Electron is very likely to use a different V8 version from the Node binary installed on your system, the modules you use will need to be recompiled for Electron.

Using Native Node Modules | Electron

Error: The module '/path/to/native/module.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION $XYZ. This version of Node.js requires
NODE_MODULE_VERSION $ABC. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or `npm install`).

Automattic/node-canvas#348 (comment)

Automattic/node-canvas#788 (comment)

SOHU-Co/kafka-node#881 (comment)

https://medium.com/flawless-app-stories/gyp-no-xcode-or-clt-version-detected-macos-catalina-anansewaa-38b536389e8d

About

๐Ÿคธ๐Ÿปโ€โ™€๏ธ ์˜† ๊ตฌ๋ฅด๊ธฐ ํ•˜๋ฉด์„œ๋„ ์•Œ ์ˆ˜ ์žˆ๋Š” UI ๋ณ€๊ฒฝ์‚ฌํ•ญ

Topics

Resources

Stars

Watchers

Forks

Contributors