Repository navigation
Releases
v1.13.2
TodayPick v1.13.2
피드 화면이 그려지는 속도를 개선했습니다. 첫 페이지 카드를 서버에서 미리 그려 보내고, 첫 줄 썸네일을 바로 받습니다. Production Lighthouse에서 모바일 LCP가 7.6초에서 3.9초로, 데스크톱 LCP가 2.1초에서 1.3초로 줄었습니다.
주요 변경 사항
첫 페이지를 서버에서 미리 그리기
- 피드 화면과 홈 "오늘 읽어볼 콘텐츠"의 카드가 페이지와 함께 도착해 로딩 스켈레톤 없이 보입니다.
- 다음 페이지, 탭을 바꾼 뒤 목록, 검색은 지금처럼 브라우저에서 요청합니다.
- 서버 조회가 실패하면 브라우저에서 다시 조회합니다.
첫 줄 썸네일 바로 받기
- 데스크톱 첫 줄(앞 3장) 카드 이미지는 지연 로딩하지 않습니다. 우선순위 힌트는 첫 장에만 둡니다.
- 첫 화면 이미지는 받기 전부터 자리에 보이게 둡니다. 이전에는 이미지를 받은 뒤 JS가 투명도를 풀어야 보였습니다.
개선 사항
- 피드 조회 로직(관심 분야 정렬, 스크랩 상태)을 서버 함수로 분리해 API와 페이지가 함께 씁니다.
버그 수정
- 없음
데이터베이스 및 운영 반영
- 없음
/와/feeds는 요청마다 서버에서 렌더링됩니다.
검증
- lint, type-check, test 590개, production build 통과
- 이슈 PR과 릴리스 PR의
CI / verify, Vercel 검사 통과 - Production HTML에 첫 페이지 카드 12개가 들어 있고, 1장 우선 로딩·2~3장 즉시 로딩·4장부터 지연 로딩임을 확인
- Production Lighthouse(테크 블로그, 각 3회 중앙값)
| v1.13.1 | v1.13.2 | |
|---|---|---|
| 모바일 점수 / LCP | 76 / 7.6초 | 88 / 3.9초 |
| 데스크톱 점수 / LCP | 90 / 2.1초 | 97 / 1.3초 |
알려진 제한 사항
- 페이지 첫 바이트(TTFB)가 서버 조회만큼 늘었습니다(약 0.21초).
- 모바일에서는 화면 밖인 2~3장 이미지도 지연 로딩하지 않습니다.
- 측정 기록: performance/2026-10-14-feed-ssr.md
관련 이슈
전체 변경 내역
v1.13.1
TodayPick v1.13.1
Vercel 함수를 Supabase DB와 같은 서울(icn1)에서 실행하도록 지정했습니다. 피드 API 응답이 0.56~1.1초에서 약 0.2초로 줄었습니다.
주요 변경 사항
API 응답 속도 개선
- 함수가 미국 워싱턴(iad1)에서 실행돼 서울 DB까지 요청마다 태평양을 2~3번 왕복하던 문제를 고쳤습니다.
- 피드뿐 아니라 프로필, 통계, 글쓰기 등 DB를 쓰는 모든 API에 적용됩니다.
개선 사항
- 함수 지역을 대시보드 설정이 아니라
vercel.json("regions": ["icn1"])으로 지정해 배포마다 같은 지역을 씁니다.
버그 수정
- 없음
데이터베이스 및 운영 반영
- 없음
검증
- 이슈 PR과 릴리스 PR의 GitHub Actions
CI / verify, Vercel 검사 통과 - Production 응답 헤더
x-vercel-id: icn1::icn1확인 - 피드 API(12개) 응답 시간
| 변경 전 (iad1) | 변경 후 (icn1) | |
|---|---|---|
| 테크 블로그 | 0.56~1.10초 | 0.19~0.49초 (대부분 0.2초 안팎) |
| IT 뉴스 | 0.56~1.02초 | 0.19~0.39초 (대부분 0.2초) |
알려진 제한 사항
- 함수가 오래 쉬었다가 처음 실행될 때는 0.4초 안팎이 걸립니다.
관련 이슈
전체 변경 내역
v1.13.0
TodayPick v1.13.0
RSS를 피드를 열 때마다 가져오던 방식에서 3시간마다 미리 수집해 DB에 저장하는 방식으로 바꿨습니다. 피드를 열 때 출처를 기다리지 않고, RSS에서 밀려난 글도 1년 동안 남으며, 글 제목으로 검색할 수 있습니다.
주요 변경 사항
예약 수집과 DB 저장
- Supabase 예약 작업(pg_cron)이 3시간마다(UTC 매 3시간 5분) 수집 API를 불러 RSS 30곳을 수집하고
feed_items에 저장합니다. - 카드에 보이는 값(제목, 요약 300자, 썸네일 주소, 작성자, 출처, 발행일, 관심 분야)만 저장하고 본문과 이미지 파일은 저장하지 않습니다. 발행 후 1년이 지난 글은 지웁니다.
- 출처 하나가 실패해도 나머지는 저장되고, 이미 저장된 글은 그대로 보입니다.
- 서비스 롤 키 없이, Vault에 둔 비밀값을 확인하는 DB 함수로만 저장합니다.
이어 보기와 맞춤 정렬
- "더보기"는 마지막으로 받은 글을 기준으로 이어 읽습니다. 스크롤 중 새 글이 수집돼도 이미 본 글이 다시 나오지 않습니다. 새로 수집된 글은 새로고침하면 보입니다.
- 관심 분야를 고른 회원은 최근 글(테크 블로그 30일, IT 뉴스 3일) 중 관심 분야가 많이 맞는 글을 먼저 보고, 그보다 오래된 글은 최신순으로 이어서 봅니다. 1년치 글이 쌓여도 오래된 관심 글이 오늘 글보다 앞서지 않습니다.
- 관심 분야 칩을 고르면 그 분야 글만 최신순으로 봅니다.
제목 검색
- IT 뉴스·테크 블로그 탭에서 2글자 이상 입력하면 제목에 그 단어가 든 글을 최신순으로 보여 줍니다. 관심 분야 칩과 함께 쓸 수 있습니다.
- 결과가 없으면 검색어를 담은 빈 상태 문구를 보여 줍니다.
개선 사항
- 피드를 열 때 외부 출처를 기다리지 않아 첫 화면이 빨라졌습니다. Production에서 한 페이지 응답이 약 0.6~1.2초입니다.
- 독립 코드 리뷰 결과(Critical 0, Important 3)를 릴리스 전에 반영했습니다.
버그 수정
- 없음
데이터베이스 및 운영 반영
- migration:
supabase/migrations/20261014090000_add_feed_items.sql— 운영 DB 적용 완료feed_items테이블과 RLS(읽기만 허용),upsert_feed_items함수,pg_net확장,collect-feeds예약 작업
- Supabase Vault
feed_collector_secret등록 완료 - Vercel 환경 변수
FEED_COLLECTOR_SECRET추가 (Production, Preview) - 배포 직후 첫 수집 실행 완료
- 운영 절차와 되돌리기:
docs/feed-collection.md
검증
-
lint, type-check, test 582개, production build 통과
-
각 PR과 릴리스 PR의 GitHub Actions
CI / verify, Vercel 검사 통과 -
Production 확인
- 수집 API는 비밀값 없이 부르면 401
- IT 뉴스 50개, 테크 블로그 342개 저장. 커서로 끝까지 이어 읽었을 때 중복 0
- 최신순 정렬, 관심 분야 칩(프론트엔드 27개 모두 해당 분야), 제목 검색("쿠버네티스" 1개, 없는 단어 0개)
- 잘못된 커서와
q=**, 1글자 검색어는 400 - 테크 블로그 화면과 320px 모바일 검색 화면
-
회원 맞춤 정렬은 단위 테스트로 확인했고, Production 로그인 계정으로는 확인하지 않았습니다.
알려진 제한 사항
- 테크 블로그 글 수가 이전(약 590개)보다 줄었습니다. 발행 후 1년이 지난 글은 저장하지 않기 때문입니다.
- 과거 글은 수집 시점에 RSS에 남아 있던 만큼만 저장됩니다.
- 검색은 제목만 대상으로 하고, 검색어는 주소에 남지 않아 새로고침하면 비워집니다.
- 밀리초보다 정밀한 발행 시각이 저장되면 같은 밀리초 글을 건너뛸 수 있습니다. 지금 수집 코드는 밀리초 단위로만 저장합니다.
- 출처가 41곳을 넘으면 한 번의 수집이 2000개 상한을 넘습니다. 지금은 30곳입니다.
- 수집 실패 알림은 없습니다.
net._http_response와cron.job_run_details로 확인합니다.
관련 이슈
- #220 RSS 글 저장 테이블과 예약 수집 migration을 추가한다
- #221 RSS 예약 수집 API를 추가한다
- #222 피드 조회를 DB와 커서 방식으로 전환한다
- #223 피드 제목 검색을 추가한다
- #229 v1.13.0 리뷰 지적 사항을 고친다
- #224 v1.13.0 RSS 예약 수집과 DB 저장 릴리스
전체 변경 내역
v1.12.1
TodayPick v1.12.1
테크 블로그 출처를 21곳에서 29곳으로 늘렸습니다. 꾸준히 기술 글을 올리는 기업 블로그 8곳을 추가 기준(robots.txt, 봇 응답, 이용약관, 기술 글 비중)으로 확인한 뒤 넣었습니다.
주요 변경 사항
기술 블로그 출처 8곳 추가
- flex, 삼성전자, 미리디, 비브로스, 하이퍼엑셀, 한글과컴퓨터, CJ온스타일, SK플래닛의 새 글이 테크 블로그 탭에 나옵니다.
- 출처 안내(
/sources)의 수집 중인 출처 목록에도 반영됩니다. - 비브로스·하이퍼엑셀·한글과컴퓨터·SK플래닛은 원 출처 이미지를 썸네일로 보여 주고, RSS에 이미지가 없는 flex·삼성전자는 기본 썸네일로 나옵니다.
개선 사항
- 출처 정책 문서에 후보 32곳의 검토 결과(추가·제외·보류와 근거)를 기록했습니다.
- 썸네일 허용 호스트 테스트를 추가했습니다.
버그 수정
- 없음
데이터베이스 및 운영 반영
- 없음
검증
- lint, type-check, test 523개, production build 통과
npm run check:feeds30곳 실패 0- 이슈 PR과 릴리스 PR의 GitHub Actions
CI / verify, Vercel Preview 통과 - Production에서
/sources와 테크 블로그 피드 API에 새 출처가 포함된 것을 확인
알려진 제한 사항
- 포스타입은 무단 복제·스크래핑 금지 고지로 제외했고, 컴투스플랫폼은 홍보성 글 비중 때문에 보류했습니다.
- medium 출처(미리디, CJ온스타일, 기존 당근마켓 등)는 설명이 비어 나오는 글이 있습니다.
- 삼성전자 기술 블로그는 비상업적 이용 조건으로 추가했습니다. 수익화하면 다시 검토합니다.
관련 이슈
전체 변경 내역
TodayPick v1.12.0 회원 직접 탈퇴와 가입 동의
TodayPick v1.12.0
개인정보처리방침·이용약관과 실제 기능을 맞춘 릴리스입니다. 이제 프로필에서 비밀번호를 확인한 뒤 직접 탈퇴할 수 있고, 회원가입 때 만 14세 이상 확인과 약관·개인정보처리방침 동의를 필수로 받아 기록합니다.
주요 변경 사항
프로필에서 직접 탈퇴할 수 있습니다
- 프로필 맨 아래 회원 탈퇴에서 비밀번호를 확인하면 계정, 읽은 글·스크랩·퀴즈·CS 기록·작성한 글, 프로필 이미지가 즉시 삭제됩니다.
- 비밀번호가 틀리면 아무것도 지워지지 않고 안내 문구가 표시됩니다. 시도가 많아 잠시 막힌 경우는 따로 안내합니다.
- 탈퇴가 끝나면 로그아웃된 상태로 홈으로 이동합니다.
- 이전에는 메일로 요청해야 했습니다. 로그인할 수 없는 경우에는 지금도 메일로 요청할 수 있습니다.
회원가입 때 필수 동의를 받습니다
- "만 14세 이상입니다", "이용약관과 개인정보처리방침에 동의합니다" 두 항목을 모두 체크해야 가입할 수 있습니다. 두 문서는 새 탭에서 열립니다.
- 동의한 시각과 약관 시행일(버전)을 기록합니다. 동의 기록은 수정할 수 없습니다.
정책 문서를 실제 기능에 맞췄습니다
- 개인정보처리방침: 처리 항목에 동의 기록을 추가하고, 보유 기간·파기·이용자 권리를 직접 탈퇴 기준으로 수정했습니다.
- 이용약관: 만 14세 이상과 가입 시 동의, 직접 탈퇴 방법을 명시했습니다.
개선 사항
- 계정 삭제는 로그인한 본인만, 그리고 방금 비밀번호를 다시 확인한 세션만 실행할 수 있습니다. 세션 토큰만으로 비밀번호 확인을 건너뛸 수 없습니다.
- 서비스 롤 키 없이 동작하도록 설계했습니다.
- API 테스트 도구가 로그인·로그아웃·Storage 목록 조회를 지원합니다.
버그 수정
- 없음
데이터베이스 및 운영 반영
- migration:
supabase/migrations/20261013090000_add_account_deletion_and_consent.sqlusers.terms_agreed_at,users.terms_version컬럼- 가입 트리거
handle_new_user가 동의 기록 - 동의 값 보호 트리거
prevent_terms_consent_update - 계정 삭제 함수
delete_own_account()(최근 비밀번호 인증 필요)
- 운영 DB 적용 완료 (2026-10-13, 릴리스 병합 전)
- 환경 변수, 외부 서비스, 배포 설정 변경: 없음
검증
- 이슈 PR #209~#213과 릴리스 PR #214의 GitHub Actions
CI / verify, Vercel 검사 통과 npm run lint,npm run type-check,npm test(518 테스트),npm run build통과- 전체 변경을 새 리뷰어가 검토하고 Important 2건을 수정했습니다(#212).
- Production(
tdpick.vercel.app)에서 일회용 테스트 계정으로 확인- 가입: 체크 전·하나만 체크하면 버튼 비활성, 둘 다 체크하면 가입 후 홈 이동
- 동의 기록:
terms_agreed_at기록,terms_version=2026-10-13. 본인이 동의 값 수정 시도 → 403terms consent columns are read-only - 비밀번호 로그인 320초 뒤의 토큰으로 rpc 직접 호출 → 403
recent password sign-in required(계정 유지) - 프로필 탈퇴: 틀린 비밀번호 → "비밀번호가 일치하지 않습니다."와 입력 유지 → 올바른 비밀번호 → 홈 이동, 헤더가 로그인 상태 해제
- 탈퇴 후 같은 계정 로그인 → 400
invalid_credentials, 업로드한 프로필 이미지 공개 주소 → 400(삭제됨) - anon으로 rpc 호출 → 401
permission denied, 비로그인DELETE /api/account→ 401
알려진 제한 사항
- 기존 회원의 동의 기록은 비어 있습니다. 재동의 화면은 포함하지 않았습니다.
- 동의 기록을 운영자가 고치려면 보호 트리거를 잠시 꺼야 합니다.
- 로그인 서버 장애도 "비밀번호가 일치하지 않습니다"로 안내될 수 있습니다.
- 로그인 시도 제한은 서버 IP 단위라 여러 사용자가 함께 영향을 받을 수 있습니다(기존 로그인과 같음).
- 탈퇴 직후 브라우저의 Supabase 클라이언트에 세션 정보가 잠시 남을 수 있습니다. 화면은 이미 로그아웃 상태이고 서버 세션은 삭제됩니다.
관련 이슈
- #205 v1.12.0 회원 직접 탈퇴와 가입 동의 릴리스
- #206 계정 삭제 함수와 가입 동의 컬럼 migration을 추가한다
- #207 프로필에서 회원 탈퇴를 할 수 있게 한다
- #208 회원가입에 필수 동의 절차를 추가한다
전체 변경 내역
TodayPick v1.11.2 피드 썸네일 개선
TodayPick v1.11.2
피드 썸네일을 글의 실제 이미지로 더 많이 채우고, 이미지가 없는 카드는 TodayPick 기본 이미지 하나로 통일한 패치 릴리스입니다.
주요 변경 사항
글의 실제 이미지를 썸네일로 더 많이 씁니다
RSS 본문에 이미지가 있는데도 쓰지 못하던 글이 약 120건 있었습니다. 이제 데브시스터즈, 인프랩, 우아한형제들, 네이버 D2 글이 본문의 첫 이미지를 썸네일로 보여 줍니다.
- 본문 이미지가 상대 경로(
/static/...png)여도 글 주소 기준으로 찾아 씁니다. - 주소에 확장자가 없는 본문 이미지도 씁니다. 허용한 출처의 이미지 서버만 쓰는 기준은 그대로입니다.
- 우아한형제들(
techblog.woowa.in)과 네이버 D2(pstatic.net)의 이미지 서버를 허용했습니다.
이미지가 없는 카드는 기본 이미지로 통일했습니다
RSS에 이미지가 없는 글, 이미지를 불러오지 못한 글, 썸네일 없는 게시글은 TodayPick 기본 이미지를 보여 줍니다. v1.11.1의 출처·관심 분야 대체 썸네일을 대신합니다. 예전에 스크랩하거나 읽은 글도 같은 방식으로 보입니다.
개선 사항
- 기본 이미지는 서비스에서 직접 제공해 외부 요청이 없고, 화면 크기에 맞게 최적화됩니다.
npm run check:feeds도 서비스와 같은 기준으로 썸네일을 판정합니다.
버그 수정
- 본문 이미지가 상대 경로라 썸네일을 찾지 못하던 문제
- 이미지 주소의 숫자 HTML 엔티티(
=등)를 풀지 못하던 문제
데이터베이스 및 운영 반영
- migration: 없음
- 환경 변수, 외부 서비스, 배포 설정 변경: 없음
- RSS 캐시 키를
rss-category-feeds-v8로 올려 배포 후 피드를 새로 수집합니다.
검증
- 이슈 PR #201~#203과 릴리스 PR #204의 GitHub Actions
CI / verify, Vercel 검사 통과 npm run lint,npm run type-check,npm test(491 테스트),npm run build통과npm run check:feeds: 소스 22곳, 실패 0- Production(
tdpick.vercel.app)/,/feeds,/sources,/images/default-thumbnail.jpg응답 200- 테크 블로그 최근 50건 중 38건이 글 이미지 사용, 네이버 D2 글 이미지 표시 확인
- 테크 블로그 탭 카드 12장: 원본 직접 로드 10, 기본 이미지 2
- IT 뉴스 탭 12장과 게시글 탭 4장이 기본 이미지로 표시
알려진 제한 사항
- RSS에 이미지가 없는 7곳(카카오, 라인, 뱅크샐러드, NHN, 44BITS, 카카오뱅크, GeekNews)은 기본 이미지로 표시됩니다. 원문 페이지를 따로 읽지 않는다는 출처 정책 때문입니다.
- 본문 첫 이미지가 다이어그램이나 스크린샷일 수 있습니다.
관련 이슈
전체 변경 내역
TodayPick v1.11.1 뉴스 출처 정밀 검토 반영
TodayPick v1.11.1
v1.11.0에서 보류했던 뉴스 출처의 이용 조건을 정밀 검토해 반영하고, 이미지 없는 피드 카드를 출처와 관심 분야를 담은 대체 썸네일로 바꾼 패치 릴리스입니다.
주요 변경 사항
뉴스 출처를 이용 조건에 맞게 정리했습니다
- IT동아 제외: robots.txt가 모든 봇의 RSS 경로(
/feeds/) 수집을 막고 있습니다. - IT데일리 제외: 저작권보호정책이 승낙 없는 복제·전송·배포를 금지합니다.
- GeekNews 유지: RSS 수집을 허용하고, 과도한 부하를 주는 자동화 접근만 금지합니다.
- 대체할 뉴스 출처 14곳도 검토했지만, 국내 IT 언론사는 모두 무단 전재를 금지하고 공공기관 보도자료는 개발과 관련 있는 글이 적어 추가하지 않았습니다.
- 소스 수: 24곳 → 22곳 (테크 블로그 21, IT 뉴스 1)
"IT 기사" 탭이 "IT 뉴스"가 됐습니다
남은 출처인 GeekNews는 개발자 커뮤니티가 고른 기술 소식을 요약하는 곳이라, 탭·제목·설명을 실제 성격에 맞췄습니다. 프로필의 스크랩 필터와 출처 안내 페이지도 같은 이름을 씁니다. 기존 스크랩은 그대로 이 필터에 나옵니다.
이미지 없는 카드에 대체 썸네일을 보여 줍니다
- 이미지가 없는 글은 모두 같은 외부 사진이나 출처 로고로 표시됐습니다. 이제 출처 이름과 관심 분야를 담은 썸네일을 보여 주고, 색은 관심 분야마다 다릅니다.
- 이미지를 불러오지 못한 카드도 빈 영역 대신 대체 썸네일로 바뀝니다.
- 예전에 스크랩하거나 읽은 글도 같은 방식으로 보입니다.
- 썸네일 없는 게시글은 목록에서 작성자 이름으로 만든 썸네일을 보여 주고, 상세 화면에서는 이미지 영역을 두지 않습니다.
개선 사항
- 피드 썸네일 후보에서 채널 로고를 뺐습니다. GeekNews(50건 전부)와 네이버 D2(20건 중 18건)가 같은 로고를 반복해 쓰던 문제가 사라졌습니다.
- 출처 관리 기준 문서에 뉴스 3곳과 대체 후보 14곳의 검토 결과를 기록했습니다.
버그 수정
- RSS 제목·설명에
"같은 숫자 HTML 엔티티가 그대로 보이던 문제를 고쳤습니다. "처럼 이중 인코딩된 문자열이 두 번 풀리던 문제를 함께 고쳤습니다.
데이터베이스 및 운영 반영
- migration: 없음
- 환경 변수, 외부 서비스, 배포 설정 변경: 없음
- RSS 캐시 키를
rss-category-feeds-v7로 올려 배포 후 피드를 새로 수집합니다.
검증
- 이슈 PR #192~#196과 릴리스 PR #197의 GitHub Actions
CI / verify, Vercel 검사 통과 npm run lint,npm run type-check,npm test(491 테스트),npm run build통과npm run check:feeds: 소스 22곳, 실패 0- Production(
tdpick.vercel.app)/,/feeds,/sources,/privacy,/terms,/cs,/glossary응답 200- IT 뉴스 피드 12건이 모두 GeekNews, 남은 숫자 엔티티 0건, 대체 썸네일로 표시
- 테크 블로그 탭: 실제 썸네일 9건이 원본 서버에서 로드
- 게시글 탭: 썸네일 없는 게시글 4건이 대체 썸네일로 표시
- 출처 안내에서 IT동아·IT데일리가 빠지고 "IT 뉴스" 라벨 확인
- 홈 320px 가로 넘침 없음
알려진 제한 사항
- IT 뉴스의 출처가 GeekNews 한 곳입니다. KISA 보호나라 보안공지는 이용 조건 문의 후 검토합니다.
- 네이버 D2의 글 이미지 호스트(
pstatic.net)가 허용 목록 밖이라 D2 글은 대체 썸네일로 표시됩니다.
관련 이슈
- #187 v1.11.1 뉴스 출처 정밀 검토 반영 릴리스
- #188 IT동아와 IT데일리를 피드 출처에서 제외한다
- #189 IT 기사 라벨을 IT 뉴스로 바꾼다
- #190 RSS 텍스트의 숫자 HTML 엔티티를 변환한다
- #191 이미지 없는 카드에 대체 썸네일을 표시한다
전체 변경 내역
TodayPick v1.11.0 콘텐츠 출처 정비
TodayPick v1.11.0
외부 콘텐츠 출처를 정비하고 출처·개인정보·이용 조건을 공개한 릴리스입니다. 피드가 사라졌거나 1년 넘게 갱신되지 않은 소스를 정리했고, 외부 썸네일을 더 이상 TodayPick 서버에서 복제하지 않습니다. 모든 페이지 하단에서 출처 안내, 이용약관, 개인정보처리방침을 확인할 수 있습니다.
주요 변경 사항
출처와 정책을 화면에서 확인할 수 있습니다
- 공통 푸터: 모든 페이지 하단에 출처 안내 · 이용약관 · 개인정보처리방침 · 문의 링크가 생겼습니다.
- 출처 안내 (
/sources): TodayPick이 외부 글을 어디까지 보여 주는지(제목, 설명 일부, 원문 링크, 원본에서 직접 불러오는 썸네일), 권리자의 삭제·수정 요청 방법, 지금 수집 중인 출처 목록을 안내합니다. - 개인정보처리방침 (
/privacy): 처리하는 항목, 목적, 보유 기간(읽은 글 기록은 최근 30일·최대 100개), 처리 위탁(Supabase 서울 리전, Vercel)과 국외 이전, 파기, 이용자 권리, 쿠키(로그인 세션만 사용)를 안내합니다. - 이용약관 (
/terms): 작성한 글의 저작권은 작성자에게 있고 서비스는 공개 글을 보여 주는 데 필요한 범위에서만 이용합니다. 금지 행위, 운영자 조치, 서비스 중단과 책임의 한계를 정했습니다.
피드 출처를 정리했습니다
- 제거 (7곳): 넷마블(피드가 RSS 대신 HTML을 반환), SK C&C·카카오엔터프라이즈·직방·쿠팡·지마켓·29cm(마지막 글이 1년 이상 지남)
- 추가 (1곳): 카카오뱅크 기술 블로그
- 수정: 우아한형제들·카카오·44BITS의 RSS 주소를 리다이렉트 최종 주소로 갱신, "네이버 플래이스" → "네이버 플레이스"
- 소스 수는 30곳에서 24곳(테크 블로그 21, IT 기사 3)이 됐습니다.
- 이미 스크랩하거나 읽은 글은 저장된 정보로 표시되므로 출처가 빠져도 그대로 남습니다.
썸네일을 원본 서버에서 직접 불러옵니다
피드 썸네일이 Vercel 이미지 최적화를 거치지 않고 원 출처 서버에서 바로 로드됩니다. TodayPick 서버에 외부 이미지 복제본이 남지 않고, 원 출처에 사용자가 보던 TodayPick 페이지 주소를 넘기지 않습니다(no-referrer).
개선 사항
npm run check:feeds: 모든 RSS 소스를 실제로 요청해 실패, 리다이렉트, 1년 이상 미갱신, 허용 목록 밖 썸네일 호스트를 표로 보여 줍니다. 이번 정리와 신규 소스 검토에 이 스크립트를 사용했습니다.- RSS 요청·검증·파싱 코드를
src/services/rssSourceReader.ts로 분리해 서비스와 점검 스크립트가 같은 코드를 씁니다. - 출처 관리 기준 문서 (
docs/content-sources-policy.md): 표시 범위, 소스 추가·제거 기준, 삭제 요청 처리 절차와 결정 기록
버그 수정
- 넷마블 소스가 요청할 때마다 실패하던 문제를 소스 제거로 해결했습니다.
- 우아한형제들 등 리다이렉트를 거치던 소스의 요청 단계를 줄였습니다.
데이터베이스 및 운영 반영
- migration: 없음
- 환경 변수, 외부 서비스, 배포 설정 변경: 없음
- devDependency
tsx추가 (런타임 영향 없음)
검증
- 이슈 PR #176~#185와 릴리스 PR #186의 GitHub Actions
CI / verify, Vercel 검사 통과 npm run lint,npm run type-check,npm test(474 테스트),npm run build통과npm run check:feeds: 소스 24곳, 실패 0- Production(
tdpick.vercel.app):/,/feeds,/sources,/privacy,/terms,/glossary,/cs,/login응답 200, 출처 목록에 카카오뱅크 표시 - Production 테크 블로그 탭: 피드 카드 12개 썸네일이 모두 원본 서버에서 로드됨(
/_next/image경유 0개,no-referrer12개) - 로컬 프로덕션 빌드에서
/sources,/privacy,/terms와 푸터를 1280px·320px로 확인 (가로 넘침 없음)
알려진 제한 사항
- 회원 탈퇴 기능이 없어 계정 삭제는 메일(
dhdbsdk33@gmail.com)로 요청받습니다. - 정책 문구(개인정보처리방침, 이용약관)는 법률 자문을 거치지 않았습니다.
- 뉴스 3곳(IT데일리, IT동아, GeekNews)의 언론사 약관은 정밀 검토하지 않았습니다. 요청이 오면 즉시 제외합니다.
- 올리브영(RSS 약 12MB), TVING(홍보 글 중심), DEVOCEAN(robots.txt 차단), 요즘IT(RSS 발행일 없음)는 추가하지 않았습니다.
관련 이슈
- #169 v1.11.0 콘텐츠 출처 정비 릴리스
- #170 RSS 소스 상태 점검 스크립트를 추가한다
- #171 깨지거나 오래된 RSS 소스를 정리한다
- #172 활동 중인 기술 블로그 소스를 추가한다
- #173 외부 피드 썸네일을 원본 서버에서 직접 불러온다
- #174 출처 안내와 개인정보처리방침 페이지를 추가한다
- #175 콘텐츠 출처 정책과 소스 추가 기준을 문서화한다
- #182 이용약관 페이지를 추가한다
전체 변경 내역
TodayPick v1.10.0 테스트 안전망 구축
TodayPick v1.10.0
API route와 상태 로직이 있는 컴포넌트에 테스트 안전망을 만든 릴리스입니다. 이전에는 테스트 241개가 전부 순수 함수만 검증해서, 인증 분기나 화면 상태 전이가 깨져도 npm test가 통과했습니다.
안전망을 만드는 과정에서 실제 버그 두 개가 잡혔습니다. 그중 하나는 사용자가 비공개로 만든 글이 공개로 바뀔 수 있는 문제였습니다. 이번 릴리스의 가장 실질적인 성과입니다.
주요 변경 사항
비공개로 만든 글이 공개로 바뀌지 않습니다
피드나 프로필의 읽은 글에서 인용하여 글쓰기를 시작하면 초안이 비공개로 만들어집니다. 그런데 글쓰기 화면은 이 초안을 공개로 표시하고, 사용자가 아무것도 건드리지 않았는데도 변경된 상태로 취급했습니다. 공개 여부를 그대로 두고 저장하면 초안이 공개로 바뀌었습니다.
이제 저장된 공개 여부를 그대로 보여줍니다. 인용해서 시작한 초안은 비공개로 열리고, 손대지 않았다면 저장 버튼이 활성화되지 않습니다.
/write 주소에서 쓰이지 않던 newDraft 파라미터가 사라집니다. 예전 주소로 들어와도 동작은 같습니다.
글 저장이 실패하면 알려줍니다
이전에는 글 저장이 실패해도 저장 버튼이 저장 중...에서 원래대로 돌아오는 것 말고는 아무 변화가 없었습니다. 저장이 됐는지 실패했는지 알 수 없었습니다. 이제 실패 이유를 저장 버튼 아래에 보여줍니다. 입력한 내용은 그대로 남아 다시 저장할 수 있습니다.
오류 메시지에 내부 정보가 섞이지 않습니다
서버 오류가 났을 때 데이터베이스의 내부 오류 문구가 응답에 실려 나가는 경로가 있었습니다. 이제 정해진 안내 문구만 나가고 원인은 서버 로그에만 남습니다.
개선 사항
- 테스트 241개 → 468개. API route 11개와 상태 로직이 있는 컴포넌트 5개가 새로 덮였습니다.
- 테스트 환경 정비. 순수 함수와 API route는 node에서, 컴포넌트는 jsdom에서 돌도록 나눴습니다. Supabase 응답을 주입하는 공용 fake와 요청·렌더 헬퍼를 만들었습니다.
- API 오류 응답 통일. 오류 응답 84곳을 공용 헬퍼로 교체해 상태 코드와 문구 형식을 맞췄습니다. 한 곳만 영어였던 인증 문구도 통일했습니다.
- CI 정비.
actions/checkout과actions/setup-node를 v5로 올려 Node 20 지원 종료 경고를 없앴습니다. - 문서. 테스트 작성 기준을
docs/testing-guide.md에 정리하고,AGENTS.md에 API 오류 응답 규칙과 테스트 작성 규칙, 이슈 종료 시점 규칙을 추가했습니다.
버그 수정
- 인용으로 만든 비공개 초안이 저장 시 공개로 바뀔 수 있던 문제 (#161)
- 글 저장 실패가 화면에 드러나지 않던 문제 (#162)
- 서버 오류 응답에 데이터베이스 내부 문구가 섞여 나가던 문제 (#149)
- 명언 스크랩 여부 조회가 인증 실패 시 잘못된 값으로 표시되던 문제 (#149)
데이터베이스 및 운영 반영
- migration 없음. 스키마 변경이 없어 DB 작업 없이 배포했습니다.
- 환경 변수 변경 없음.
- 배포 설정 변경 없음. GitHub Actions의 action 버전만 올렸습니다.
API 변경
GET /api/quotes?quoteId=...의 응답이 true/false에서 { isScraped: boolean }으로 바뀝니다. 같은 앱 안에서만 쓰는 내부 API이고 호출하는 화면을 함께 고쳤습니다.
검증
| 항목 | 결과 |
|---|---|
npm run lint |
통과 |
npm run type-check |
통과 |
npm test |
42 files / 468 tests 통과 |
npm run build |
통과 |
GitHub Actions CI / verify |
각 이슈 PR과 릴리스 PR, master push 모두 통과 |
| Vercel Production | 배포 성공 |
- 오류 응답 상태 코드 분포를 변경 전후로 대조해 보존을 확인했습니다.
- 오류 경로마다 주입한 내부 문구가 응답에 없는지 테스트로 확인했습니다.
- CI 로그에서 Node 20 지원 종료 경고가 0건인지 확인했습니다.
확인하지 못한 사용자 흐름
- 프로필 읽은 글에서 글쓰기로 진입하는 흐름. 에디터가 비공개로 열리는지 화면에서 확인하지 못했습니다. 피드에서 시작하는 같은 흐름은 테스트로 덮었고, 변경은 두 곳 모두 링크 문자열 한 줄입니다.
- 저장 실패 문구의 화면 위치와 색. 저장 API가 실패하는 상황을 만들기 어려워 테스트로 대신했습니다.
알려진 제한 사항
- 권한 경계는 쿼리 조건 수준까지만 검증합니다. 테스트용 fake가 필터를 실제로 적용하지 않으므로 "소유자 조건이 쿼리에 들어갔는지"만 확인합니다. 실제 행 격리는 데이터베이스의 Row Level Security가 담당합니다.
- 표시 전용 컴포넌트는 테스트가 없습니다. 상태 전이가 있는 5개만 다뤘고 나머지 35개 남짓은 대상이 아닙니다.
- 글쓰기의 썸네일 업로드 경로(multipart)는 테스트로 덮지 못했습니다. JSON 경로만 검증합니다.
- 관심 분야 중복을 합치는 동작이 의도인지 확인하지 않고 현재 동작을 테스트로 고정했습니다. 중복을 거절하려던 것이었다면 이 테스트가 잘못된 동작을 굳힌 셈입니다.
- 새 글의 기본 공개 여부가 공개인 것이 의도인지 확인하지 않았습니다. 이번 릴리스에서 바꾸지 않았습니다.
npm audit이 보고하는 취약점 6건(brace-expansion,postcss,sharp,nanoid,js-yaml)이 이전부터 있습니다. 수정하면next가 함께 올라가므로 별도 작업으로 다뤄야 합니다.
관련 이슈
- #148 테스트 인프라와 공용 헬퍼를 구축한다
- #149 API 응답과 오류 규약을 통일한다
- #150 학습 기록 API route에 테스트를 추가한다
- #151 콘텐츠 API route에 테스트를 추가한다
- #152 글쓰기와 프로필 API route에 테스트를 추가한다
- #153 상태 로직이 무거운 컴포넌트에 테스트를 추가한다
- #156 GitHub Actions를 Node 20 기반 버전에서 올린다
- #161 WriteEditor의 startAsPublic이 새 글에서 무의미하고 저장된 비공개 설정을 덮어쓴다
- #162 WriteEditor에서 글 저장 실패가 화면에 드러나지 않는다
- #142 README에 CS 지식과 IT 용어사전을 반영한다
- #144 AGENTS.md에 README 갱신 규칙을 추가한다
- #146 문서 전용 이슈의 종료 시점을 AGENTS.md에 명문화한다
- #154 v1.10.0 테스트 안전망 구축 릴리스 (릴리스 관리)
전체 변경 내역
v1.9.0 CS 지식 정착과 IT 용어사전
CS 지식을 일일 학습 흐름에 자리 잡게 하고, 모르는 용어를 바로 찾아볼 수 있는 IT 용어사전을 추가했습니다. 호환성을 깨는 변경은 없습니다.
IT 용어사전 (신규)
/glossary에 용어 121개를 추가했습니다. 표제어와 간단한 정의를 목록으로 보여주고, 항목을 누르면 상세 화면에서 사전적 설명을 확인할 수 있습니다.- 표제어와 영문 별칭으로 검색할 수 있습니다. 검색어는 URL에 남아 뒤로 가기와 공유가 됩니다.
- 상세 화면에서 관련 CS 지식 문항과 관련 용어로 이어집니다.
- 모바일 하단 내비게이션을 피드 · CS · 오늘 · 용어 · 프로필 5개로 재배치하고 홈을 가운데에 뒀습니다.
CS 지식
- 홈 체크리스트에 CS 지식 항목이 생겼습니다. 질문을 채점하면 그날의 활동으로 기록됩니다.
- 체크리스트와 주간 리포트, 프로필 주간 현황의 집계 기준을 피드 읽기 · 퀴즈 · CS 지식으로 통일했습니다. 홈에 접속하기만 해도 자동으로 기록되던 명언 확인은 집계에서 뺐습니다. 명언 기록과 홈의 오늘의 명언 섹션은 그대로입니다.
- 채점 결과의 키워드에서 용어 정의로 바로 이동할 수 있습니다. 용어사전에 있는 키워드에 점선 밑줄이 붙습니다. 현재 문항 80개의 고유 키워드 373개 중 42개가 연결되며, 용어를 추가하면 자동으로 늘어납니다.
- 힌트 사용 여부 표시와 저장을 없앴습니다. 점수에 반영되지 않는 값이었습니다. 힌트 보기 기능은 그대로입니다.
성능과 렌더링
/cs질문 목록을 서버 컴포넌트로 전환했습니다. 초기 HTML에 질문이 담기고, 분야 필터는 자바스크립트 없이도 동작합니다.- 문항 데이터가 클라이언트 번들에서 빠졌습니다. 클라이언트 청크 총합 1359.2KB → 1306.3KB(비압축).
- 한글 문단이 음절 단위로 끊기지 않도록 전역 타이포그래피 설정(
word-break: keep-all)을 추가했습니다. 모든 페이지에 적용됩니다.
연속 학습일
계산 기준을 바꾸지 않았습니다. 읽기 목표 달성일 기준 그대로이며, 회귀 테스트를 추가했습니다.
데이터베이스
daily_activities.cs_completed컬럼 추가 (20260807000000_add_daily_cs_completed.sql). 기존 CS 채점 기록이 있는 날짜는 완료로 백필했습니다.
API 변경
GET /api/cs-reviews응답에reviewQuestions,progress,keywordLinks가 추가되고used_hint가 빠졌습니다.- 통계 API 응답의
dailyProgress.quoteView가dailyProgress.csComplete로 바뀌었습니다. - 주간 리포트의 학습일과 목표 완료일이 새 기준으로 다시 계산됩니다. 목표 완료일은 CS를 풀지 않은 과거 날짜에서 줄어듭니다.
문서
docs/content-data-policy.md— 콘텐츠를 코드와 DB 중 어디서 관리할지에 대한 기준과 이전 시점
전체 변경 사항: v1.8.0...v1.9.0