Skip to content

Services

โ€œMinjung edited this page Sep 26, 2026 · 1 revision

Services

Fetchers (src/fetchers/)

๊ฐ fetcher๋Š” ํŠน์ • ๋‰ด์Šค ์†Œ์Šค์—์„œ ๊ธฐ์‚ฌ๋ฅผ ์ˆ˜์ง‘ํ•˜์—ฌ Article ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Tech Fetcher (src/fetchers/tech.py)

Hacker News API์—์„œ ์ƒ์œ„ ๊ธฐ์ˆ  ๋‰ด์Šค๋ฅผ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์†Œ์Šค: hacker-news.firebaseio.com/v0

๋™์ž‘ ํ๋ฆ„:

  1. /topstories ์—”๋“œํฌ์ธํŠธ์—์„œ ์ƒ์œ„ ์Šคํ† ๋ฆฌ ID ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ
  2. ์ƒ์œ„ 50๊ฐœ ์Šคํ† ๋ฆฌ์˜ ์ƒ์„ธ ์ •๋ณด fetch (๋ณ‘๋ ฌ ์•„๋‹˜, ์ˆœ์ฐจ + ์žฌ์‹œ๋„)
  3. ๋น„๊ธฐ์ˆ  ํ‚ค์›Œ๋“œ ํ•„ํ„ฐ๋ง (์ •์น˜, ์Šคํฌ์ธ , ์œ ๋ช…์ธ ๋“ฑ)
  4. ์ ์ˆ˜์ˆœ ์ •๋ ฌ ํ›„ ์ƒ์œ„ 5๊ฐœ ๋ฐ˜ํ™˜

ํ•„ํ„ฐ๋ง ๊ทœ์น™:

NON_TECH_PATTERNS = re.compile(
    r"\b(politics|election|president|congress|senate|democrat|republican|"
    r"nfl|nba|mlb|fifa|olympics|weight loss|diet pill|celebrity|...)\\b",
    re.IGNORECASE,
)

Stocks Fetcher (src/fetchers/stocks.py)

์ฃผ์‹ ์‹œ์žฅ ๋‰ด์Šค๋ฅผ ์–ธ์–ด๋ณ„๋กœ ๋‹ค๋ฅธ ์†Œ์Šค์—์„œ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค.

์˜์–ด ์†Œ์Šค: Yahoo Finance RSS (finance.yahoo.com/news/rssurl) ํ•œ๊ตญ์–ด ์†Œ์Šค: Google News Korea RSS (news.google.com/rss/search?q=์ฃผ์‹+์ฝ”์Šคํ”ผ)

ํ‚ค์›Œ๋“œ ํ•„ํ„ฐ๋ง:

  • ์˜์–ด: stock, market, S&P, NASDAQ, earnings, dividend, IPO, bitcoin ๋“ฑ
  • ํ•œ๊ตญ์–ด: ์ฃผ์‹, ์ฝ”์Šคํ”ผ, ์ฝ”์Šค๋‹ฅ, ์ฆ์‹œ, ์ฃผ๊ฐ€, ์ƒ์žฅ, ๋ฐฐ๋‹น, ETF ๋“ฑ

Real Estate Fetcher (src/fetchers/realestate.py)

๋ถ€๋™์‚ฐ ๋‰ด์Šค๋ฅผ ์–ธ์–ด๋ณ„๋กœ ๋‹ค๋ฅธ ์†Œ์Šค์—์„œ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค.

์˜์–ด ์†Œ์Šค:

  • Zillow Research (zillow.com/research/feed/)
  • HousingWire (housingwire.com/feed/)
  • CNBC Real Estate (search.cnbc.com/rs/...)

ํ•œ๊ตญ์–ด ์†Œ์Šค: Google News Korea RSS

Summarizer (src/summarizer.py)

๊ธฐ์‚ฌ ๋ณธ๋ฌธ์„ ์ถ”์ถœํ•˜๊ณ  AI๋กœ ์š”์•ฝํ•ฉ๋‹ˆ๋‹ค.

๋ณธ๋ฌธ ์ถ”์ถœ:

  1. trafilatura.extract() โ€” ๋ฉ”์ธ ์ฝ˜ํ…์ธ  ์ถ”์ถœ
  2. Hacker News text ํ•„๋“œ โ€” HN ์ž์ฒด ๊ฒŒ์‹œ๊ธ€์ธ ๊ฒฝ์šฐ
  3. HN ๋Œ“๊ธ€ ๋ณธ๋ฌธ โ€” URL ์—†๋Š” Ask HN/Show HN ๋“ฑ

์š”์•ฝ ์—”์ง„:

  • ์ฃผ ์—”์ง„: Groq API (qwen/qwen3.8-27b)
  • ํด๋ฐฑ: Google Translate (๋ฌด๋ฃŒ API)

์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ:

ํ•œ๊ตญ์–ด: "ํ•œ๊ตญ ํ…Œํฌ ๋ธ”๋กœ๊ฑฐ๊ฐ€ ๊ฐœ๋ฐœ์ž ์นœ๊ตฌ์—๊ฒŒ ์„ค๋ช…ํ•˜๋Š” ๋А๋‚Œ์œผ๋กœ 3๋ฌธ์žฅ ์š”์•ฝ.
        ๋”ฑ๋”ฑํ•œ '~ํ–ˆ์Šต๋‹ˆ๋‹ค' ๋Œ€์‹  '~ํ–ˆ์–ด์š”', '~์ธ ์…ˆ์ด์ฃ ' ๋“ฑ ์‚ฌ์šฉ."
์˜์–ด:   "Summarize in 3 sentences in English. Casual, friendly tone."

์žฌ์‹œ๋„ ๋กœ์ง:

  • Rate limit ์‹œ ์ง€์ˆ˜ ๋ฐฑ์˜คํ”„: 5์ดˆ โ†’ 10์ดˆ โ†’ 20์ดˆ
  • ์ตœ๋Œ€ 3ํšŒ ์žฌ์‹œ๋„
  • ์‹คํŒจ ์‹œ ๋นˆ ๋ฌธ์ž์—ด ๋ฐ˜ํ™˜ (์š”์•ฝ ์—†์ด ๊ธฐ์‚ฌ ์ œ๋ชฉ๋งŒ ๋ฐœ์†ก)

Notifier (src/notifier.py)

HTML ์ด๋ฉ”์ผ์„ ์ƒ์„ฑํ•˜์—ฌ Gmail SMTP๋กœ ๋ฐœ์†กํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฉ”์ผ ๊ตฌ์„ฑ:

  • ๋ชจ๋ฐ”์ผ ์นœํ™”์  HTML ํ…œํ”Œ๋ฆฟ
  • ๊ธฐ์‚ฌ๋ณ„: ์ˆœ๋ฒˆ, ์ œ๋ชฉ (๋งํฌ), AI ์š”์•ฝ, HN ๋Œ“๊ธ€ ๋งํฌ
  • ํ•˜๋‹จ: ๊ตฌ๋… ํ•ด์ง€ ๋งํฌ
  • ํ† ํ”ฝ๋ณ„ ์ด๋ชจ์ง€ ํ—ค๋” (๐Ÿ’ป Tech, ๐Ÿ“ˆ Stocks, ๐Ÿ  Real Estate)

๋ณด์•ˆ:

  • URL sanitization: http://, https:// ์Šคํ‚ด๋งŒ ํ—ˆ์šฉ
  • HTML escape: ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ฐ’
  • ์ด๋ฉ”์ผ ์ฃผ์†Œ HTML escape

๋ฐœ์†ก ๋ฐฉ์‹:

  • ๋‹จ์ผ SMTP SSL ์—ฐ๊ฒฐ๋กœ ๋ชจ๋“  ์ด๋ฉ”์ผ ์ฒ˜๋ฆฌ
  • SMTP_SSL (465) ์‹œ๋„ โ†’ ์‹คํŒจ ์‹œ STARTTLS (587) ํด๋ฐฑ
  • ๋ฐœ์†ก ์‹คํŒจ ์‹œ ๋กœ๊ทธ ํ›„ ๋‹ค์Œ ๊ตฌ๋…์ž๋กœ ๊ณ„์†

Subscriber Management (src/subscribers.py)

subscribers.json ํŒŒ์ผ ๊ธฐ๋ฐ˜์˜ ๊ตฌ๋…์ž CRUD ๊ด€๋ฆฌ์ž…๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๋ชจ๋ธ:

[
  {
    "email": "user@example.com",
    "language": "ko",
    "topics": ["tech", "stocks"]
  }
]

์ œ๊ณต ํ•จ์ˆ˜:

ํ•จ์ˆ˜ ์„ค๋ช…
load_subscribers() JSON์—์„œ ๊ตฌ๋…์ž ๋ชฉ๋ก ๋กœ๋“œ
save_subscribers() ๊ตฌ๋…์ž ๋ชฉ๋ก์„ JSON์œผ๋กœ ์ €์žฅ
add_subscriber() ์ƒˆ ๊ตฌ๋…์ž ์ถ”๊ฐ€ (์ค‘๋ณต ๊ฒ€์‚ฌ, ์ตœ๋Œ€ 500๋ช…)
remove_subscriber() ์ด๋ฉ”์ผ๋กœ ๊ตฌ๋…์ž ์ œ๊ฑฐ
update_subscriber() ์–ธ์–ด/ํ† ํ”ฝ ๋ณ€๊ฒฝ

Cloudflare Worker (worker/src/index.js)

๊ตฌ๋… ํŽ˜์ด์ง€์—์„œ์˜ ์š”์ฒญ์„ GitHub Actions repository_dispatch๋กœ ํ”„๋ก์‹œํ•ฉ๋‹ˆ๋‹ค.

์—ญํ• :

  • GitHub PAT ํ† ํฐ์„ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ์— ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด๊ด€
  • CORS origin ๊ฒ€์ฆ (ํ”„๋กœ๋•์…˜ ๋„๋ฉ”์ธ๋งŒ ํ—ˆ์šฉ)
  • Rate limiting (IP๋ณ„ ๋ถ„๋‹น 5๊ฑด, ์‹œ๊ฐ„๋‹น 20๊ฑด)
  • ์ž…๋ ฅ ๊ฒ€์ฆ ๋ฐ ํ•„ํ„ฐ๋ง

๋ณด์•ˆ ์กฐ์น˜:

โœ… CORS: https://minjungsung.github.io๋งŒ ํ—ˆ์šฉ
โœ… ํ•„๋“œ ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ: email, language, topics, action๋งŒ
โœ… ์–ธ์–ด/ํ† ํ”ฝ ๊ฐ’ ๊ฒ€์ฆ: ํ—ˆ์šฉ๋œ ๊ฐ’๋งŒ
โœ… Request body ํฌ๊ธฐ ์ œํ•œ: 1KB
โœ… ์ด๋ฉ”์ผ ๊ธธ์ด ์ œํ•œ: 254์ž
โœ… IP ๊ธฐ๋ฐ˜ Rate limiting

Cache (src/cache.py)

GitHub Actions Cache๋ฅผ ํ™œ์šฉํ•œ ์ผ๊ฐ„ ์บ์‹ฑ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค.

์บ์‹œ ํŒŒ์ผ:

  • data/cache/articles_{topic}.json โ€” ํ† ํ”ฝ๋ณ„ ๊ธฐ์‚ฌ ์บ์‹œ
  • data/cache/summaries_{language}.json โ€” ์–ธ์–ด๋ณ„ ์š”์•ฝ ์บ์‹œ

์บ์‹œ ์ „๋žต:

  • ๊ฐ™์€ ๊ธฐ์‚ฌ๋ฅผ ์—ฌ๋Ÿฌ ๊ตฌ๋…์ž์—๊ฒŒ ๋ฐœ์†กํ•  ๋•Œ ์ค‘๋ณต Groq API ํ˜ธ์ถœ ๋ฐฉ์ง€
  • ๊ธฐ์‚ฌ URL์„ ํ‚ค๋กœ ์‚ฌ์šฉํ•˜์—ฌ ์š”์•ฝ ๊ฒฐ๊ณผ ์ €์žฅ
  • ์‹คํ–‰๋งˆ๋‹ค ์ƒˆ ์บ์‹œ ์ƒ์„ฑ, ์ด์ „ ์‹คํ–‰์˜ ์บ์‹œ์—์„œ ๋ณต์› (hackdigest-v2- prefix)