일본 전용 읽기‑나중에 보기 PWA 구축: Pocket 종료에서 출시까지
출처: Dev.to
Mozilla가 2025년 7월에 Pocket을 종료했을 때, 나는 가장 좋아하던 읽어‑두기 도구를 잃게 되었다. 영어 기반 대안들(Instapaper, Readwise, Matter, Raindrop) 중 어느 것도 일본어 UI를 제공하지 않았고, 일본어 페이지에 대한 기사 추출 성능도 좋지 않았다.
그래서 직접 만들었다: Readbox – 일본어 우선(영어도 지원) 읽어‑두기 프로그레시브 웹 앱. 출시하면서 배운 점을 정리한다.
스택
- Next.js 15 App Router + TypeScript strict (any 사용 금지)
- Supabase (Postgres + Auth + Row‑Level Security)
- Stripe (JPY + USD 가격, 로케일 라우팅)
- Tailwind CSS
- PWA 설치 + 오프라인 독서를 위한 Service Worker
겪은 3가지 문제
1. Vercel 서버리스 환경에서의 기사 추출
첫 시도는 Mozilla Readability + jsdom을 사용했지만, ESM 호환성 문제와 50 MB 서버리스 함수 크기 제한 때문에 Vercel에 번들링되지 않았다. Webpack externals, 동적 import, edge runtime 등 여섯 가지 방법을 시도했지만 깔끔하게 해결되지 않았다.
결국 Jina Reader 를 사용했다. Jina Reader는 어떤 URL이든 깨끗한 Markdown/HTML을 반환한다.
트레이드‑오프: 제3자 의존성이 생기고 규모가 커지면 호출 제한에 걸릴 수 있지만, 현재는 무료이며 바로 동작한다.
2. 기사 본문을 디바이스에 저장하기
수백만 개의 기사 HTML을 Supabase에 보관하고 싶지 않았다(비용 + 프라이버시). 해결책은 추출된 HTML을 브라우저의 IndexedDB에만 저장하고(Dexie 사용) 메타데이터(URL, 제목, 태그, 읽음 상태)만 서버와 동기화하는 것이었다.
트레이드‑오프: 본문 내용의 기기 간 동기화가 매끄럽지 않다. 보통은 저장한 기기에서 바로 읽는 “읽어‑두기” 흐름에선 충분히 허용 가능한 수준이다.
3. i18n 라우팅 — 눈에 띄지 않는 sitemap 파괴자
일본어 + 영어를 하나의 코드베이스에서 제공하기 위해 app/[locale]/ 세그먼트를 사용했고, 영어는 /en 프리픽스를 두었다(일본어는 기존 URL 유지 차원에서 프리픽스 없이 기본). 미들웨어는 쿠키 또는 Accept-Language 헤더를 감지해 리다이렉트한다.
함정(런치 당일 한 시간 소요): 미들웨어 매처에서 _next, api, 이미지 확장자를 제외했지만 .xml, .txt, .webmanifest 를 빼는 것을 깜빡했다. 그 결과 sitemap.xml과 robots.txt가 /ja/sitemap.xml 등으로 재작성돼 존재하지 않아 404가 반환되었다.
해결 방법
// next.config.js
export const config = {
matcher: [
'/((?!api|_next|.*\\.(?:xml|txt|webmanifest|svg|png|jpg|jpeg|gif|webp|ico)$).*)',
],
};
i18n 라우팅을 메타데이터 라우트(sitemap, robots, manifest)와 함께 구현한다면, 위와 같은 설정을 테스트 플랜에 포함하라.
현재 Readbox 상황
Readbox는 유료 플랜(¥450 / 월, $3 / 월)과 최대 100개의 기사까지 무료로 이용할 수 있는 티어를 제공한다. Pocket CSV 가져오기는 기존 5열 형식과 최신 6열 형식을 모두 지원하며, 한 번에 최대 5,000개의 기사를 처리한다.
- 일본어 사이트:
- 영어 사이트:
Pocket에서 마이그레이션한 분이라면, 여러분의 읽어‑두기 워크플로와 어떤 도구를 선택했는지 이야기를 들려주세요.