Summary
#258 에서 정의한 SourceAdapter 인터페이스의 Instagram 구현체. Instagram 유저/해시태그에서 fashion-decode 포맷(좌: 인물 착장 / 우: 아이템 그리드) 이미지를 수집해 공용 R2 버킷(decoded-media) 및 warehouse.source_media 테이블에 적재한다.
파싱·seed 투입은 #258 의 공용 파이프라인이 담당 — 이 이슈는 Instagram 수집만.
Related:
수집 타겟
| Source type |
예시 |
비고 |
user |
@bpinkstyles, @outfitsbreakdown |
fashion-decode 전문 계정 |
hashtag |
#fashiondecode, #outfitbreakdown, #celebstyle |
|
search |
키워드 검색 |
v2 (선택) |
- v1: 피드 이미지만 (릴스/Story 제외)
platform='instagram', external_id=shortcode (예: C1a2B3c4D5e)
기술적 고려
Instagram 안티봇은 Pinterest보다 강력 — 옵션 비교:
| 옵션 |
장점 |
단점 |
| Graph API (공식) |
안정적, 합법 |
비즈니스 계정만, 본인 컨텐츠만 읽기 가능 (유저 피드 ❌) |
| Hyperbrowser / Browserbase |
JS 렌더링, 세션 관리 |
비용, 로그인 세션 관리 필요 |
| Instaloader + 프록시 |
오픈소스, 무료 |
계정 차단 리스크, rate-limit |
→ Hyperbrowser 권장 (#214 Pinterest 와 동일 스택 재사용). 필요 시 쿠키 세션 로테이션.
Phase 1: 어댑터 구현
새 파일
| 파일 |
역할 |
packages/ai-server/src/services/media/adapters/instagram.py |
InstagramAdapter(SourceAdapter) |
packages/ai-server/src/services/media/adapters/_instagram_client.py |
Hyperbrowser 기반 Instagram 크롤러 (내부) |
시그니처
class InstagramAdapter:
platform: str = 'instagram'
async def fetch(
self, source: MediaSource, limit: int = 50
) -> list[RawMedia]:
# source.source_type: 'user' | 'hashtag'
# source.source_identifier: '@username' | '#hashtag'
...
platform_metadata 예시
{
\"shortcode\": \"C1a2B3c4D5e\",
\"owner_id\": \"1234567890\",
\"is_video\": false,
\"like_count\": 15234,
\"posted_at\": \"2026-04-10T12:34:56Z\"
}
Phase 2: 환경변수
INSTAGRAM_SESSION_COOKIE 또는 INSTAGRAM_USERNAME / INSTAGRAM_PASSWORD
- (Hyperbrowser 재사용 시 별도 env 불필요)
Phase 3: 스케줄링
Phase 4: Rate-limit / 차단 대응
- 유저당 최대 요청 수 제한
- 차단 감지 시
media_sources.is_active=false 자동 비활성화 + 알림
- 에러 핸들링: 429/401/차단 페이지 감지
검증
Open questions
🤖 Generated with Claude Code
2026-04-29 기준 변경사항 (CIOI 검토)
본문 초안 대비 코드베이스·파이프라인을 기준으로 정리한 진행 방향이다. 구현·PR은 다음 표를 참고하면 된다.
| 구분 |
본문 초안 |
변경·제시 방향 |
| 패키지 경로 |
services/media/adapters/instagram.py 등 |
#258 이후 monorepo 실제는 packages/ai-server/src/services/raw_posts/adapters/ 에서 SourceAdapter / FetchRequest 계약 (Pinterest 어댑터와 동일 레이어). |
| 적재 |
R2 decoded-media + warehouse.source_media |
assets 의 public.raw_posts 및 기존 raw posts 파이프라인(R2·키 규약은 Pinterest/raw_posts 쪽과 정합). |
| 크롤 스택 |
Hyperbrowser 권장 (#214 와 동일) |
instaloader + instaloader -l 로 만든 세션 사용 (INSTAGRAM_SESSION_USERNAME 등으로 세션 파일 로드). |
| 수집 타겟 v1 |
user + hashtag 표기 |
우선 user만 구현. hashtag 는 후속. |
| 캐러셀·dedup |
Open questions: v1 은 첫 이미지만 |
슬라이드별 external_id = shortcode__N , platform_metadata.carousel_index 로 정리한다. 단일 이미지는 팀 규약에 맞춰 __0 또는 단일 shortcode 유지. |
| 검증 |
여러 항목·E2E 등 |
Phase 1 어댑터 범위에서는 실 DB 연결 스모크로 한 게시 분량 정도까지로 한정 가능. |
| Phase 3~4 |
2시간 스케줄·차단 시 소스 비활성화 등 |
어댑터 PR과 분리; 후속 작업으로 쪼개기. |
Summary
#258 에서 정의한
SourceAdapter인터페이스의 Instagram 구현체. Instagram 유저/해시태그에서 fashion-decode 포맷(좌: 인물 착장 / 우: 아이템 그리드) 이미지를 수집해 공용 R2 버킷(decoded-media) 및warehouse.source_media테이블에 적재한다.Related:
수집 타겟
user@bpinkstyles,@outfitsbreakdownhashtag#fashiondecode,#outfitbreakdown,#celebstylesearchplatform='instagram',external_id=shortcode(예:C1a2B3c4D5e)기술적 고려
Instagram 안티봇은 Pinterest보다 강력 — 옵션 비교:
→ Hyperbrowser 권장 (#214 Pinterest 와 동일 스택 재사용). 필요 시 쿠키 세션 로테이션.
Phase 1: 어댑터 구현
새 파일
packages/ai-server/src/services/media/adapters/instagram.pyInstagramAdapter(SourceAdapter)packages/ai-server/src/services/media/adapters/_instagram_client.py시그니처
platform_metadata 예시
{ \"shortcode\": \"C1a2B3c4D5e\", \"owner_id\": \"1234567890\", \"is_video\": false, \"like_count\": 15234, \"posted_at\": \"2026-04-10T12:34:56Z\" }Phase 2: 환경변수
INSTAGRAM_SESSION_COOKIE또는INSTAGRAM_USERNAME/INSTAGRAM_PASSWORDPhase 3: 스케줄링
fetch_media_job(platform='instagram')에 등록Phase 4: Rate-limit / 차단 대응
media_sources.is_active=false자동 비활성화 + 알림검증
external_idUNIQUE) 확인platform_metadata에 Instagram 고유 필드 보존 확인Open questions
🤖 Generated with Claude Code
2026-04-29 기준 변경사항 (CIOI 검토)
본문 초안 대비 코드베이스·파이프라인을 기준으로 정리한 진행 방향이다. 구현·PR은 다음 표를 참고하면 된다.
services/media/adapters/instagram.py등packages/ai-server/src/services/raw_posts/adapters/에서SourceAdapter/FetchRequest계약 (Pinterest 어댑터와 동일 레이어).decoded-media+warehouse.source_mediapublic.raw_posts및 기존 raw posts 파이프라인(R2·키 규약은 Pinterest/raw_posts 쪽과 정합).instaloader+instaloader -l로 만든 세션 사용 (INSTAGRAM_SESSION_USERNAME등으로 세션 파일 로드).user+hashtag표기user만 구현.hashtag는 후속.external_id=shortcode__N,platform_metadata.carousel_index로 정리한다. 단일 이미지는 팀 규약에 맞춰__0또는 단일 shortcode 유지.