
Astro 7 + Hono + D1 RSS 리더「feedge」: AI 다국어 실시간 번역 및 요약 기능 구현기
요약
Astro 7, Hono, Cloudflare D1을 활용한 오픈 소스 RSS 리더 'feedge'의 AI 번역 및 요약 기능 구현 사례를 소개합니다. Llama 3.2 3B 모델을 사용하여 에지 환경에서 저지연 성능을 확보하고, D1 데이터베이스를 통해 번역 결과를 캐싱하여 효율성을 극대화했습니다.
핵심 포인트
- Astro 7, Hono, Cloudflare D1 기반의 모던 웹 스택 활용
- Llama 3.2 3B 모델 채택으로 에지 환경에서의 레이턴시 최소화
- D1 데이터베이스를 이용한 번역 결과 캐싱 및 비용 절감
- 사용자 권한에 따른 AI 이용 상한 관리 및 UX 설계
1. 서론
모던 RSS 리더 feedge는 Astro 7, Hono (Workers), Cloudflare D1, pnpm 모노레포(Monorepo) 구성으로 개발되고 있는 오픈 소스 제품입니다.
해외의 최신 기술 뉴스(The Hacker News, TechCrunch, arXiv, GitHub Trending 등)를 구독할 때, 영어로 된 장문 기사를 신속하게 파악하고 싶다는 니즈는 매우 높습니다.
이번에 feedge에 「AI 3줄 요약 기능」 및 **「AI 번역 기능(제목 및 본문의 실시간 일본어화)」**을 구현하였으며, D1 데이터베이스를 통한 캐시 영속화, 이용 횟수 제한 관리, 문맥 이해(Context Awareness)에 기반한 자연스러운 일본어 번역을 실현했습니다. 본 기사에서는 경량 LLM 모델을 채택한 배경과 그 성능을 극대화하기 위한 프롬프트 엔지니어링(Prompt Engineering)의 노하우에 대해 해설합니다.
2. 기능 개요 및 UX 설계
이번에 추가된 AI 번역·요약 기능의 주요 사양과 UX(User Experience) 설계는 다음과 같습니다.
AI 3줄 요약:- 모달 표시 시 원터치로 기사 본문을 요약. 불렛 포인트 3개의 요약문을 생성하여 즉시 시각화.
-
요약 데이터는 데이터베이스에 직접 저장되어, 새로고침 후에도 영구적으로 유지.
AI 번역:- 해외 영어 기사를 열었을 때, 「🌐 이 기사를 일본어로 AI 번역」 버튼을 통해 제목과 본문을 자연스러운 일본어로 실시간 변환.
-
이미 일본어로 작성된 기사(Yahoo! 뉴스, Qiita, Zenn 등)는 도메인 판정 및 문자 판정을 통해 번역 버튼을 자동으로 숨김.
1일 AI 이용 상한 관리 (권한 역할 동기화):- 일반 사용자를 위해 1일 AI 이용 상한(5회)을 카운트 표시.
- 무제한 권한을 가진 사용자는 횟수 제한 배지를 자동으로 숨겨 심리스(Seamless)하게 이용 가능.
- 상한 도달 시 요약·번역 버튼 양쪽의 enabled/disabled 스타일(소등된 애쉬 컬러)을 100% 통일.
3. 아키텍처 및 데이터베이스 설계
3.1 D1 번역 캐시 테이블 구조
AI의 중복 실행을 방지하고 빠른 응답 속도와 무료 티어 절약을 실현하기 위해, 생성된 번역 결과는 D1 데이터베이스의 article_translations 테이블에 캐시 및 영속화됩니다.
-- 기사 번역 캐시 테이블
CREATE TABLE IF NOT EXISTS article_translations (
id TEXT PRIMARY KEY,
...
3.2 Hono 백엔드 API 구현
번역 API 엔드포인트(POST /translate-endpoint)에서는 먼저 D1 캐시의 존재를 확인하고, 캐시가 존재하는 경우 즉시 응답을 반환합니다. 미생성 상태인 경우 LLM / 뉴럴 번역 엔진을 호출하여 DB에 저장합니다.
// 번역 처리 API 엔드포인트 구현 이미지
app.post('/translate-endpoint', authMiddleware, async (c) => {
const userId = c.var.userId
...
4. 초경량 LLM (3B 모델) 채택과 성능을 끌어올리는 기술적 노하우
4.1 왜 3B 클래스의 초경량 모델을 채택하는가?
Cloudflare Workers AI 상에서 번역·요약 태스크를 실행함에 있어, 모델로는 @cf/meta/llama-3.2-3b-instruct (파라미터 수 약 30억 개의 초경량 모델)를 채택하고 있습니다.
대형 모델(70B 클래스 등)이 아닌 3B 클래스를 채택한 이유는 다음 3가지입니다.
레이턴시(Latency) 최소화: 에지(Edge, Cloudflare Workers) 환경에서 사용자를 기다리게 하지 않는 밀리초~수 초 수준의 초고속 응답 실현.
컴퓨팅 리소스 효율화: 무료 티어 및 저비용 운용에 있어 리소스 제한 내에 확실히 수용.
높은 병렬 처리 내성: 모바일 환경이나 다수의 동시 접속 시에도 대기 시간을 발생시키지 않음.
4.2 경량 모델 특유의 과제와 솔루션
3B 클래스의 경량 모델은 빠르고 가벼운 반면, 대형 모델과 비교하여 다음과 같은 특유의 약점이 있습니다.
- 지시 따르기 (Instruction Following)의 "여백" 부족: 복잡한 프롬프트를 주면 JSON 형식 이외의 서두 텍스트(예:
Here is the JSON output:등)를 출력하기 쉽습니다. - 직역 경향: 문맥 추론 용량이 작기 때문에, IT 보안 용어와 같은 전문적인 고유명사(예:
Aikido Security)를 "합기도"와 같이 단어 그대로 직역해 버리는 경우가 있습니다.
이러한 약점을 극복하고, 경량 모델로부터 대형 모델 수준의 고품질 번역 결과를 끌어내기 위해 다음과 같은 기술적 기법을 도입했습니다.
① Few-Shot Prompting (모범 사례 쌍 주입)
시스템 프롬프트 내에 "입력 제목·본문"과 "이상적인 번역 JSON 출력 쌍"을 구체적인 예시로 제시했습니다. 경량 모델은 예시를 모방하는 능력이 매우 높기 때문에, 프롬프트 지시를 훨씬 더 잘 준수하게 됩니다.
② Context Priming (정보 소스 미디어 정보의 컴팩트한 주입)
사용자 프롬프트 서두에 【정보 소스 미디어】: The Hacker News나 【기사 제목】을 컴팩트하게 주입했습니다. 경량 모델의 제한된 컨텍스트 윈도우 (Context Window)를 압박하지 않으면서, "이 기사는 사이버 보안 영역의 뉴스이다"라는 도메인 지식을 자극할 수 있습니다.
③ 엄격한 Temperature 저감
번역 시의 샘플링 난수 파라미터 (Sampling Random Parameter)를 temperature: 0.1로 설정했습니다. 할루시네이션 (Hallucination, 환각)이나 지나치게 자유로운 의역을 배제하고, 원문의 수치 데이터나 고유명사에 충실한 출력을 보장합니다.
④ 견고한 응답 파싱 이중망
만약 AI가 서두 텍스트를 출력했을 경우에 대비하여, 백엔드 측에서 정규 표현식 추출(match(/\{[\s\S]*\}/))과 유니코드 이스케이프 해제(cleanTranslationText)를 수행하여, 흔들림 없이 클린한 JSON만을 추출하여 DB에 저장합니다.
// 5. Workers AI를 통한 번역 실행 (@cf/meta/llama-3.2-3b-instruct)
const model = c.env.TRANSLATION_MODEL || '@cf/meta/llama-3.2-3b-instruct'
const systemPrompt =
...
5. 직면했던 난관과 본질적인 솔루션
5.1 단어 치환 (임시방편적인 오역 방지)의 한계와 컨텍스트 인지형 프롬프트로의 전환
【과제】
사이버 보안 기업인 **Aikido (Aikido Security)**를 포함한 영어 뉴스를 번역했을 때, 번역 엔진이 고유명사임을 인식하지 못하고 무술인 **"합기도"**로 직역하여, "합기도는 나중에 868개의 패키지를 보고했습니다"라는 부자연스러운 문장이 발생했습니다.
초기 대응으로 "합기도" ➔ "Aikido"와 같이 단어를 치환하는 가드 코드를 넣는 방안을 검토했으나, 이를 수행할 경우 동물원이나 일반 뉴스에서 실제 "합기도"나 "뱀 (Python)"이 등장했을 때 예기치 않은 오역이나 잘못된 덮어쓰기를 일으킬 위험이 있었습니다.
【해결 접근 방식】
단어 수준의 후처리 치환 (정규 표현식 가드)은 완전히 폐지하고, 앞서 언급한 **Few-Shot Prompting + Context Priming을 통한 문맥 이해 (Context Awareness)**로 접근 방식을 일원화했습니다.
단순한 문자열 치환 규칙에 의존하지 않고, AI에게 문맥을 주어 판단하게 함으로써 다른 분야의 기사에 악영향을 미치지 않고도 전문 용어의 정확한 번역이 가능해졌습니다.
5.2 페이지 새로고침 시 번역 결과가 사라지는 SQL JOIN 버그
【과제】
한 번 "AI 번역"을 완료했음에도 불구하고, 화면을 새로고침하면 번역 카드가 표시되지 않고 "🌐 이 기사를 한국어로 AI 번역" 버튼으로 돌아가 버리는 문제가 발생했습니다.
【원인과 대처】
기사 목록 취득 API의 SQL 쿼리에서, article_translations 테이블과의 LEFT JOIN 조건에 uf.target_lang (사용자 개별 피드 언어 설정)이 포함되어 있었기 때문에, 피드 설정이 존재하지 않는 경우 결합 술어(Join Predicate)가 불일치하여 translated_title
또는 translated_content가 NULL로 처리되고 있었습니다.
JOIN 조건을 기본 언어 'ja'로 고정하여 결합하도록 수정하였으며, 리로드 후에도 DB에서 번역 캐시가 100% 확실하게 추출될 수 있도록 개선했습니다.
-- 수정 전
LEFT JOIN article_translations trans
ON a.id = trans.article_id AND trans.target_lang = COALESCE(uf.target_lang, 'ja')
...
6. 마치며
AI 3줄 요약과 다국어 실시간 번역 기능의 추가로, **feedge (피지)**를 통해 해외 기술 정보를 캐치업(Catch-up)하는 경험이 대폭 향상되었습니다.
에지(Edge)에서 동작하는 3B 클래스의 초경량 모델이라 할지라도, 퓨샷 프롬프팅 (Few-Shot Prompting), 컨텍스트 프라이밍 (Context Priming), 템퍼러처 (Temperature) 제어 등을 적절히 조합함으로써 대형 모델에 필적하는 자연스럽고 고정밀한 번역 출력을 실현할 수 있음을 증명할 수 있었습니다.
앞으로도 사용자의 정보 수집 효율을 극대화하는 모던한 프로덕트 개발을 계속해 나가겠습니다!
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기