진실이 가장 중요할 때 언어 장벽을 허물다

발행: (2026년 3월 16일 오전 05:37 GMT+9)
8 분 소요
원문: Dev.to

Source: Dev.to

Cover image for Breaking the Language Barrier When Truth Matters Most

Samar Shetye

Article illustration

전 세계적인 갈등이 불붙으면, 가장 먼저 희생되는 것은 종종 진실이다. 지역 선전 기계가 이야기를 꾸미고, 외부 뉴스 사이트가 차단되며, 국제 기자들의 중요한 업데이트는 거대한 장벽, 즉 언어 뒤에 가두어져 있다.

제가 LingualNews 코딩을 시작하기 전, 제 “백지 캔버스”는 이 거대한 정보 비대칭에 의해 형성되었습니다. 저는 빠른 프론트엔드(React + Vite)와 견고한 API 세트(Lingo.dev와 Groq)를 결합한 솔루션을 구축해야 했으며, 그 핵심 사명은 다음과 같습니다:

누구든, 어디서든, 전 세계 뉴스 매체의 URL을 붙여넣기만 하면 즉시 자신의 모국어로 읽거나—듣거나—할 수 있다면 어떨까요?

제가 해결하고자 하는 문제는 필터링되지 않은 현실에 대한 접근성입니다. LingualNews는 진실이 여러분의 지리적 위치나 사용 언어에 의해 결코 차단되지 않도록 함으로써 세상을 더 나은 곳으로 만듭니다.

고수준 아키텍처

LingualNews를 **“스마트 프록시 퍼널”**이라고 생각하세요.

  1. Input – 외국어 뉴스 URL을 붙여넣습니다.
  2. CORS Bypass – React 클라이언트가 요청을 동적으로 백업 프록시를 통해 라우팅합니다.
  3. Scraping – 휴리스틱 DOM 스크래퍼가 원시 HTML을 정리하고 광고와 잡음을 제거합니다.
  4. AI Pipeline
    • Lingo.dev는 정밀 번역을 담당합니다.
    • **Groq (LLaMA 3.1)**은 간결한 요약을 생성하고 번역 대체 수단으로 작동합니다.
  5. Output – 네이티브 Web Speech API가 번역된 텍스트를 음성으로 출력합니다.

마법이 일어나는 곳

실제 마법은 scraperService.jstranslationService.js에 있습니다. 이 모듈들은 혼란스럽고 광고가 가득한 외국 웹사이트를 밀리초 안에 깔끔하고 현지화된 읽기 쉬운 컴포넌트로 변환합니다.

가장 큰 기술적 돌파구를 꼽자면, 번역 레이어의 몇 줄에 불과합니다. 지정학적 위기 상황에서는 트래픽이 급증하고 API가 실패할 수 있습니다. 기본 번역 API가 중단되면 앱은 깨져서는 안 됩니다.

돌파구 코드 (줄별 설명)

} catch (err) {
  console.warn('Lingo.dev translation failed, falling back to Groq:', err.message);
  // Fallback to Groq
  const { translateWithGroq } = await import('./aiService.js');
  return await translateWithGroq(text, targetLang);
}
  • catch (err) – 기본 Lingo.dev API에서 발생하는 모든 실패를 가로챕니다.
  • console.warn(...) – UI를 중단시키지 않고 오류를 부드럽게 로그에 남깁니다.
  • Dynamic importawait import('./aiService.js')는 필요할 때만 무거운 Groq 모듈을 지연 로드하여 초기 번들 크기를 작고 빠르게 유지합니다.
  • return await translateWithGroq(...) – Groq를 통해 LLaMA 3.1을 보조 방어선으로 사용하여 사용자가 즉시 현지화된 뉴스를 받을 수 있도록 보장합니다.

가장 답답한 버그

공식 Lingo.dev SDK를 통합하는 것은 악몽이었습니다. 이 SDK는 Node 환경용으로 만들어졌으며, Vite 빌드를 깨뜨리는 모호한 번들링 오류를 발생시켰습니다.

해결책: SDK를 버리고, 문서에서 REST 엔드포인트를 역공학한 뒤, 커스텀 X-API-Key 헤더를 포함한 순수 fetch POST 요청을 직접 만들었습니다. 때때로 순수 HTTP가 다듬어진 SDK보다 낫습니다.

깔끔한 디자인이 혼란스러운 현실을 만났을 때

My initial design assumed a simple querySelector('article') would extract text from any news site perfectly. Reality: web scraping is a nightmare of custom ad‑blockers, captchas, and chaotic “ nests.

  • 무슨 일 있었나요: 깔끔한 디자인이 즉시 깨졌습니다.
  • 해결책: 나는 휴리스틱 CSS 선택자와 “노이즈” 필터(.cookie-banner, .advertisement 등)의 방대한, 복잡한 배열을 만들었습니다.
  • 최후의 수단: 엄격한 프롬프트와 함께 원시 HTML을 직접 Groq에 전달합니다:

오직 기사 본문 텍스트만 반환하십시오.”

Technical Debt & Trade‑Offs

빠르게 배포하기 위해 프런트엔드 환경(import.meta.env)에 API 키를 삽입했습니다. Vite는 개발 단계에서 키를 가려 주지만, 클라이언트‑사이드 fetch는 규모가 커질수록 위험합니다. MVP 단계에서 이 부채를 감수하고, V2에서는 키를 엣지 함수로 옮길 계획입니다.

직접 해보세요

git clone https://github.com/Samar-365/LingualNews
cd LingualNews
npm install
# Add a .env file with VITE_GROQ_API_KEY and VITE_LINGO_API_KEY
npm run dev

다음은?

오늘 이 저장소를 포크한다면 가장 눈에 띄는 누락된 부분은 오프라인 PWA 지원(Service Workers)입니다. 뉴스를 읽는 데 지속적이고 안정적인 인터넷 연결이 필요하지 않아야 합니다—특히 불안정한 지역에 사는 사용자들에게는 더욱 그렇습니다. 로컬 캐싱은 이 앱의 생명을 구하는 잠재력을 크게 향상시킬 수 있습니다.

코드는 단순한 구문을 넘어, 우리가 세상을 연결하는 방식입니다.

언어 장벽을 허물기 위해 어떤 것을 만들고 있나요?

리소스

레포지토리를 확인해 보세요: LingualNews

해커톤 내내 지속적인 지도와 이 훌륭한 기회를 제공해 주신 @sumitsaurabh927@maxprilutskiy에게 특별히 감사드립니다.

코딩을 즐기세요!

0 조회
Back to Blog

관련 글

더 보기 »

트라비고

Gemini와 함께 말하는 속도만큼 빠르게 여행하세요! 라이브 에이전트가 몰입형 스토리텔링 및 3D 내비게이션과 만나는 곳. 이 프로젝트는 Gemini Live Ag...에 진입하기 위해 만들어졌습니다.