결론부터. Reddit JSON API는 2023년부터 인증 없이 쓰면 403이 옵니다. 그런데 RSS 피드(서브레딧 주소 뒤에 new.rss)는 아직 인증 없이 열려 있어요. 단, User-Agent를 보내야 하고 호출 간격을 넉넉히 둬야 합니다.
9편에서 수집한 글을 로컬 LLM으로 거른다고 했죠. 그런데 순서가 좀 뒤바뀌었네요. 사실 그 앞, 글을 가져오는 첫 단계에서 벽을 먼저 만났거든요. Reddit이었습니다.
문서대로 했는데 403이 왔어요
Reddit에서 글 목록을 가져오는 방법은 검색하면 금방 나옵니다. 주소 끝에 .json을 붙이면 JSON으로 받을 수 있다는 거죠.
옛날엔 그랬습니다. 지금은 403이 옵니다.
2023년에 Reddit이 API 정책을 바꾸면서 인증 없는 접근을 막았어요. 앱을 등록하고 OAuth 인증을 붙여야 합니다. 검색으로 나오는 예제 코드 상당수가 그 이전 것이라, 그대로 따라 하면 안 됩니다.
여기서 선택지가 갈렸어요.
| 방법 | 비용 |
|---|---|
| OAuth 인증 붙이기 | 앱 등록 + 토큰 갱신 로직 |
| 스크래핑 | HTML 구조 바뀌면 매번 깨짐 |
| RSS 피드 | 인증 없음 |
RSS는 아직 열려 있었어요
Reddit은 오래전부터 RSS를 제공해왔고, 그게 아직 살아 있습니다.
https://www.reddit.com/r/서브레딧이름/new.rss이걸 부르면 최신 글 목록이 Atom 형식 XML로 옵니다. 인증이 필요 없어요.
4편에서 K-Startup이 XML을 준다고 했는데, 여기서 또 XML을 만났어요. 다만 이쪽은 표준 Atom 형식이라 훨씬 다루기 쉬웠습니다. 글마다 제목·링크·본문이 정해진 자리에 들어 있어요.
막혔다고 포기하지 않고 다른 문을 찾은 게 이 편의 핵심입니다. 정문이 잠겼어도 옆문이 열려 있을 수 있어요.
사람인 척은 해야 합니다
인증은 필요 없지만 조건이 하나 있었어요. User-Agent를 보내야 합니다.
"나는 어떤 프로그램입니다" 하고 알리는 값인데, 안 보내거나 기본값으로 두면 막혀요. Reddit이 권장하는 형식이 있어서 그대로 맞췄습니다.
python:앱이름:버전 (by /u/사용자명)무엇을 만든 누구인지 밝히는 형식이에요. 차단하려면 차단하라는 뜻이기도 하죠. 숨기고 우회하는 것보다 이게 낫다고 봤습니다.
본문에 HTML이 섞여 있었어요
RSS로 받은 본문은 HTML 태그가 그대로 들어 있습니다. 사람이 읽을 화면용이니 당연한데, 저는 텍스트만 필요했어요.
그냥 넘기면 LLM이 태그까지 읽고 판단합니다. 그래서 태그를 지우고, 특수기호를 원래 글자로 되돌린 다음, 300자로 잘라서 넘겼어요.
자른 이유는 판단에 필요한 만큼만 주면 되기 때문이에요. 긴 글을 통째로 넣으면 로컬 모델이 느려지고, 정작 핵심은 앞부분에 있는 경우가 많았습니다.
그런데 절반만 성공했어요
여기가 이 편에서 가장 솔직해야 할 부분입니다. 우회는 됐지만 완전히 풀리진 않았어요.
서브레딧 다섯 개를 순서대로 부르는데, 로그를 세어보니 429(과다호출)가 이렇게 났어요.
| 서브레딧 | 429 발생 |
|---|---|
| r/androidapps | 2회 |
| r/iosapps | 262회 |
| r/AppIdeas | 325회 |
| r/startups | 326회 |
| r/SideProject | 325회 |
첫 번째만 통과하고 나머지 넷은 거의 매번 막힙니다. 호출 사이에 2초를 쉬게 해뒀는데 그게 부족했어요. 결과적으로 알림 건수가 이렇게 나왔습니다.
r/androidapps → 알림 46건
r/iosapps → 3건
r/AppIdeas → 2건
r/startups → 0건
r/SideProject → 0건다섯 개를 붙였는데 실질적으로 하나만 일하고 있습니다.
왜 아직 안 고쳤나
이유는 두 가지예요.
① 봇이 죽지 않기 때문입니다. 429가 오면 그 서브레딧만 건너뛰고 다음으로 가요. 하나가 막혀도 전체가 안 멈추게 짜뒀거든요. 그래서 눈에 안 띄었어요. 로그에 경고는 찍히는데 알림은 계속 오니까 "돌아가네" 하고 넘어갔죠.
② 아이디어 발굴은 급하지 않았어요. 이 봇의 본업은 공고 알림이고, 아이디어 쪽은 덤입니다. 급한 것부터 하다 보니 밀렸어요.
고칠 방법은 어렵지 않아요. 쉬는 시간을 늘리거나, 서브레딧을 사이클마다 하나씩 돌려가며 부르면 됩니다. 한 시간에 한 번 도는 봇이니 5분씩 쉬어도 상관없어요.
이번에 글을 쓰면서 로그를 세어보고 처음 알았어요. 블로그를 쓰는 게 점검이 된 셈입니다.
마무리 — 남의 서비스는 언제든 문을 닫는다
이 편의 교훈은 이래요.
외부 API는 내 것이 아닙니다. 어제 되던 게 오늘 막힐 수 있어요. Reddit은 정책을 바꿨고, 제가 할 수 있는 건 다른 문을 찾는 것뿐이었습니다.
그래서 소스마다 파일을 따로 둔 게 여기서 값을 했어요(4편). Reddit 쪽이 막혀도 공고 수집기들은 아무 영향 없었습니다. 한 소스가 죽어도 나머지가 도는 구조였던 거죠.
그리고 하나 더 — 조용히 절반만 성공하는 상태가 있다는 걸 알았어요. 완전히 죽으면 알아채는데, 부분적으로 죽으면 모르고 넘어갑니다. 6편·9편에서도 같은 종류였어요. 이 시리즈에서 세 번째로 만난 함정이네요.
다음 편
이제 마지막입니다. 두 달 넘게 돌린 이 봇이 실제로 제 결정을 바꾼 날의 이야기로 마무리하겠습니다. → 11편·완결 — 봇이 알려준 공고로 이사를 검토했습니다
'개발 실험실 > 공고 알림봇(SBNotifier)' 카테고리의 다른 글
| 공고 알림봇, 혼자 만든 기록 (11편·완결) — 봇이 알려준 공고로 이사를 검토했습니다 (0) | 2026.08.06 |
|---|---|
| 공고 알림봇, 혼자 만든 기록 (9편) — LM Studio 로컬 LLM으로 수집 결과를 걸렀습니다 (0) | 2026.08.05 |
| 공고 알림봇, 혼자 만든 기록 (8편) — 윈도우 작업 스케줄러로 파이썬 봇을 자동 실행했습니다 (0) | 2026.08.04 |
| 공고 알림봇, 혼자 만든 기록 (7편) — 텔레그램 봇 인라인 키보드로 버튼을 달았습니다 (0) | 2026.08.04 |
| 공고 알림봇, 혼자 만든 기록 (6편) — 한 공고가 일곱 번 올 뻔했습니다 (0) | 2026.08.03 |