Introduction
서비스 특성상 SNS 연동을 핵심 기능으로 삼고 개발을 진행하던 중, Rate Limit이라는 문제에 직면하게 되었다.
인스타그램 API는 비교적 호출 한도가 여유 있었지만, X(Twitter) API는 훨씬 더 제한적인 호출 정책을 가지고 있었다.
특히 /2/users/:id/tweets 엔드포인트는 사용자별 15분당 5회라는 매우 낮은 호출 한도를 가지고 있어,
다수의 인플루언서 데이터를 동시에 처리해야 하는 서비스 환경에서는 사실상 실시간 조회가 불가능한 구조였다.
이 문제를 해결하기 위해 캐싱을 통한 호출 최적화를 도입했고,
그 결과 Rate Limit을 회피하면서 일정 수준의 실시간성을 확보할 수 있었다.
하지만 이후 실제 운영 환경에서 캐싱 정책의 한계와 예외 상황이 드러나면서, 추가적인 개선이 필요해졌다.
이 글은 그중 “1차 캐싱 도입” 단계의 내용을 정리한 것으로,
다음 글에서 이어질 “2차 개선(콜드스타트 및 since_id 보완)”과 구분하여 작성하고자 한다.
👀 What I Faced
X(Twitter) API 호출 시 rate limit(제한) 문제 발생
- 모든 조회 요청을 /2/users/:id/tweets 로 처리 → 인당 5회/15분 제한에 걸림
- 운영 중 트래픽이 증가하면 실시간으로 트윗을 못 불러오는 상황 발생
🧩 Root Cause / Theory
/2/users/:id/tweets 는 최근 트윗 전체를 가져오지만, Rate Limit 한도가 매우 낮아 (5회/15분), 사용자 수가 많을수록 즉시 한도 도달.
- 캐싱 없이 매번 호출하면, 같은 사용자의 트윗을 불필요하게 반복 요청하게 됨.
- 그러나 캐싱을 적용하면 “새 트윗이 생겼는지” 알 수 없어 TTL이 만료될 때까지 갱신 불가한 문제 존재.
🧰 How I Solved / How I Learned
1️⃣ 캐싱 방식 및 TTL 설정
- InMemoryCache 도입 (서버 메모리 내에 단순 key-value 저장)
- 트윗 본문/URL 등 문자열만 저장 → 10분 TTL
- → 수천 건 수준도 수백 MB 내로 충분히 관리 가능
- 추후 다중 서버 구성 시 Redis로 확장 고려
2️⃣ API 호출 구조 변경
- /2/users/:id/tweets → /2/tweets/search/recent 으로 부분 대체
- /search/recent은 최근 7일 내 게시물만 조회 가능하지만,API Rate Limit 특징
/2/users/:id/tweets 5회 / 15분 전체 조회, 리밋 심함 /2/tweets/search/recent 60회 / 15분 최근 7일, 효율적 - 호출 한도는 60회/15분으로 훨씬 여유 있음 👍
3️⃣ 알고리즘! (핵심!!)
[ X(Twitter) 트윗 조회 알고리즘 ]
- 초기 조회 (cold start)
- /2/users/:id/tweets 호출 → 결과 캐싱(10분 TTL)
- 5분 내 재조회
- /2/tweets/search/recent 호출
- meta.result_count + sinceId 비교 → 신규 트윗 여부 판단
- 신규 없음: 기존 캐시 반환
- 신규 있음: 신규데이터 병합 후 캐시 생신
- 429 Error (Rate Limit 초과)
- 마지막 캐시 반환
- 사용자 안내메시지 노출 (”잠시후 트윗을 재로딩합니다.”)
Caching Strategy
- Key: tw:media:{userId}:{fromYmd}:v1
- TTL: 10분
- Policy: Cache-Aside + Negative Caching
- Fallback: 429 → 캐시 리턴
- 확장성: 추후 Redis 분산 캐시로 교체 가능
Test & Verification
- 로컬 환경: 자동 갱신 동작 정상
- 개발 서버 테스트 결과
- 기존: 5회 이후 rate limit 초과 → API 차단
- 변경 후: /search/recent + 캐시로 20회 이상 조회 시도에도 정상 동작환경 호출 횟수 결과
기존 /users/:id/tweets 5회 429 에러 개선 /search/recent + 캐시 20회+ 정상
📋 Results
- 호출 한도 초과(429) 발생률 → 100% → 0%
- 응답속도 평균 2.1s → 0.8s
- 신규 트윗 반영 속도: TTL(15분) 기준으로 안정화
🔍 Key Takeaways
- /users/:id/tweets 단독 사용은 실무에서 불가능한 수준의 제한
- 캐싱 + search/recent 혼합 구조로 신선도/호출 한도 문제 모두 해결
- 트윗 구조가 안정적이라면 InMemory 캐시도 충분히 실용적
🧾 References / Links
- Twitter API v2 Rate Limits
- InMemoryCache in ASP.NET Core
- Cache Aside Pattern
🧭 Reflection
- 다중 서버 운영 시 Redis 분산 캐시 전환 필요
- sinceId 기반 캐시 동기화 검토 필요
- /search/recent의 7일 한계 → 장기 등록 캠페인 대응 방안 별도 설계 필요
'개발일지 > 개발로그 (실무)' 카테고리의 다른 글
| X(Twitter) API 캐싱 도입 (2편) (0) | 2025.11.04 |
|---|