Reddit ICP 모니터
사용자가 해결하는 문제를 겪고 있는 사람을 서브레딧에서 찾습니다. 관련성을 점수화하고, 각 매칭에 대해 도움 되는 답변을 초안합니다.
중요 규칙: 게시물의 URL, 제목, 내용을 절대 임의로 생성하지 마십시오. 모든 출력 게시물은 Reddit 검색 결과에서 나와야 합니다. 결과가 없는 섹션은 "일치하는 항목이 없습니다."라고 표시하십시오. 검색에서 반환되지 않은 게시물에 대해 답변을 초안하지 마십시오.
스팸 방지 규칙: 게시물에서 도구 추천을 명시적으로 요청하지 않는 한, 초안 답변에 제품이나 회사 이름을 언급하지 마십시오. 마케터처럼 말하지 말고 실무자처럼 말하십시오.
1단계: 설정 확인
echo "GEMINI_API_KEY: ${GEMINI_API_KEY:+set}"
echo "REDDIT_CLIENT_ID: ${REDDIT_CLIENT_ID:-설정되지 않음, 공개 엔드포인트 사용 (10 RPM)}"
GEMINI_API_KEY가 없는 경우: 중단하세요. 사용자에게 알리세요: "GEMINI_API_KEY가 필요합니다. aistudio.google.com에서 받으세요. .env 파일에 추가하세요."
Reddit 자격 증명이 없는 경우: 계속 진행하세요. Reddit의 공개 JSON 엔드포인트를 사용하세요 (인증 불필요, 10 RPM 제한). 3~6개의 서브레딧을 모니터링하는 대부분의 세션에서 이 정도면 충분합니다.
REDDIT_CLIENT_ID가 설정된 경우: OAuth를 사용하여 60 RPM을 확보하세요. 먼저 토큰을 가져오세요:
TOKEN=$(curl -s -X POST \
-d "grant_type=password&username=$REDDIT_USERNAME&password=$REDDIT_PASSWORD" \
--user "$REDDIT_CLIENT_ID:$REDDIT_CLIENT_SECRET" \
-H "User-Agent: varnan-skills/1.0" \
https://www.reddit.com/api/v1/access_token \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
이후 모든 요청에 Authorization: Bearer $TOKEN 헤더와 https://oauth.reddit.com 기본 URL을 사용하세요.
2단계: ICP 로드
기존 ICP 파일 확인:
ls docs/icp.md 2>/dev/null && echo "ICP 찾음" || echo "ICP 없음"
docs/icp.md가 존재하는 경우: 읽으세요. 다음을 추출하세요:
product: 한 문장 제품 설명pain_points: 고통점 구문 목록 (정확한 구매자 언어)anti_keywords: 게시물을 제외하는 구문subreddits: 검색할 서브레딧 목록
docs/icp.md가 존재하지 않는 경우: 다음 3가지 질문을 하세요. 모든 답변이 완료될 때까지 진행하지 마십시오:
- 당신의 제품은 무엇을 하나요? (한 문장)
- ICP는 어떤 서브레딧에 게시물을 올리나요? (쉼표로 구분, 예: devops, startups, SaaS)
- 어떤 고통점 구문이 매칭을 트리거해야 하나요? (구매자의 언어로 3-5개 구문, 예: "온보딩에 너무 오래 걸려요", "사용자가 이탈하는 이유를 알 수 없어요")
답변을 수집한 후, references/icp-format.md의 표준 형식으로 docs/icp.md에 저장하세요. 확인: "ICP가 docs/icp.md에 저장되었습니다. 다음 실행부터 자동으로 사용됩니다."
표준 형식과 좋은/나쁜 고통점 구문 예시를 보려면 references/icp-format.md를 읽으세요.
3단계: Reddit 검색
각 서브레딧과 고통점 구문 조합에 대해 하나의 검색을 실행하세요. OAuth 자격 증명이 설정되지 않은 경우 공개 엔드포인트를 사용하세요.
OAuth 없음 (공개 엔드포인트):
curl -s \
-H "User-Agent: varnan-skills/1.0" \
"https://www.reddit.com/r/{SUBREDDIT}/search.json?q={PHRASE}&sort=new&t=week&limit=25&restrict_sr=true" \
| python3 -c "
import sys, json
d = json.load(sys.stdin)
posts = d.get('data', {}).get('children', [])
for p in posts:
data = p['data']
print(json.dumps({
'id': data['id'],
'title': data['title'],
'body': data.get('selftext', '')[:600],
'url': 'https://reddit.com' + data['permalink'],
'score': data['score'],
'comments': data['num_comments'],
'subreddit': data['subreddit'],
'created_utc': data['created_utc']
}))
"
OAuth 사용:
https://www.reddit.com을 https://oauth.reddit.com으로 바꾸고 -H "Authorization: Bearer $TOKEN"을 추가하세요.
구문을 URL 인코딩한 후 쿼리 문자열에 삽입하세요:
ENCODED=$(python3 -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1]))" "{PHRASE}")
시간 창 기본값:
- 기본값:
t=week(최근 7일) - 사용자가 "오늘" 또는 "지난 24시간"을 말하면:
t=day - 사용자가 "이번 달"을 말하면:
t=month
모든 검색 후:
- 모든 게시물을 하나의 목록으로 수집
- 게시물 ID로 중복 제거. 동일한 게시물이 여러 구문과 일치하면 한 번만 유지하고 모든 일치 구문을 기록
- 검색 결과가 0개면: 기록하고 계속 진행. 중단하지 마십시오.
점수화 전 총 후보 수를 명시: "Y개의 서브레딧에서 X개의 후보 게시물을 찾았습니다."
4단계: Gemini로 관련성 점수화
모든 후보 게시물과 ICP 컨텍스트를 임시 파일에 기록한 후 점수화:
cat > /tmp/reddit-score-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "당신은 특정 제품이 해결하는 정확한 고통점을 누군가가 겪고 있는 Reddit 게시물을 식별하는 GTM 분석가입니다. 제공된 각 게시물에 대해 다음 필드를 가진 JSON 객체를 출력하세요: id (게시물 ID), score (정수 1-5), reason (점수를 설명하는 한 문장). 점수 기준: 5 = 사람이 명확히 문제를 가지고 있으며 적극적으로 도움을 구하거나 불만을 토로함; 4 = 강한 신호, 문제는 있지만 덜 명시적임; 3 = 가능한 일치, 불확실; 2 = 관련성은 있지만 핵심 고통은 아님; 1 = 관련 없음. 점수 객체의 JSON 배열만 출력하세요. 배열 앞뒤에 설명을 추가하지 마세요."
}]
},
"contents": [{
"parts": [{
"text": "POSTS_AND_ICP_CONTEXT_HERE"
}]
}],
"generationConfig": {
"temperature": 0.2,
"maxOutputTokens": 2048
}
}
ENDJSON
curl -s -X POST \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/reddit-score-request.json \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
POSTS_AND_ICP_CONTEXT_HERE를 다음으로 바꾸세요:
- 2단계의 제품 설명 및 고통점 구문
- 각 후보 게시물: id, 제목, 본문 일부
- ICP의 안티 키워드 (Gemini가 이 키워드가 포함된 게시물은 낮은 점수 부여)
답변 초안 작성을 위해 점수 >= 4인 게시물만 유지하세요.
명시: "X개의 게시물이 4점 또는 5점을 받았습니다. 답변 초안 작성 중입니다."
점수 >= 4인 게시물이 0개면: 7단계의 결과 없음 메시지를 출력하고 중단하세요. 빈 답변을 초안하지 마십시오.
5단계: Gemini로 답변 초안 작성
초안 작성 전 references/reply-rules.md를 읽으세요. 각 고점수 게시물의 게시물 유형(모드 1, 2 또는 3)을 결정하고 모드를 Gemini에 전달하세요.
점수 >= 4인 각 게시물에 대해 답변 초안을 작성하세요 (세션당 최대 5개 답변):
cat > /tmp/reddit-reply-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "당신은 이 Reddit 게시물에 설명된 정확한 문제를 직접 해결한 실무자입니다. 도움 되는 답변을 작성하세요: (1) 게시물에서 질문하거나 불만을 토로한 내용에 직접 답변, (2) 실제 경험에서 얻은 구체적이고 유용한 인사이트 공유, (3) 게시물에서 도구 추천을 명시적으로 요청하지 않는 한 어떤 제품, 도구, 회사 이름도 언급 금지, (4) 2-5문장으로 작성, 헤더나 글머리 기호 목록 없이 평이한 대화체로 작성, (5) 선택적으로 대화를 이어갈 수 있는 부담 없는 초대 문구로 마무리. 마케팅 언어를 사용하지 마십시오. 다음 단어를 사용하지 마십시오: game-changer, best-in-class, streamline, transform, revolutionize, leverage, seamless, robust, innovative. 실제 사람처럼 말하세요."
}]
},
"contents": [{
"parts": [{
"text": "POST_CONTENT_AND_MODE_HERE"
}]
}],
"generationConfig": {
"temperature": 0.7,
"maxOutputTokens": 512
}
}
ENDJSON
curl -s -X POST \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/reddit-reply-request.json \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
POST_CONTENT_AND_MODE_HERE를 다음으로 바꾸세요:
- 전체 게시물 제목 및 본문
- 답변 모드 (모드 1: 불만/좌절, 모드 2: X를 어떻게 처리하나요?, 모드 3: 도구 추천)
- 제품 설명 (모드 1/2에서 Gemini가 이름을 피하도록 함)
- 모드 3인 경우: Gemini가 제품 이름을 언급할 수 있으며 반드시 하나의 대안도 언급해야 함
6단계: 자체 QA
제시하기 전에 모든 검사를 실행하고 위반 사항을 수정하세요:
- 모드 1 또는 모드 2 답변에 제품 이름 없음
- 모든 답변에 금지 단어 없음: "game-changer", "best-in-class", "streamline", "transform", "revolutionize", "leverage", "seamless", "robust", "innovative"
- 모든 답변 2-5문장 (문장 수를 세고 명시)
- 각 답변이 게시물의 특정 질문이나 불만에 직접 답변
- 출력의 모든 URL이 검색 결과에서 나온 실제 Reddit URL (임의로 생성하거나 추측하지 않음)
- 총 초안 답변 5개 이하
- 모드 3 답변은 최소 하나의 대안 언급 (제품만 언급하지 않음)
- 어떤 서브레딧이 모든 키워드 검색에서 결과 0개를 반환한 경우 출력에 표시
제시하기 전에 위반 사항을 수정하세요.
7단계: 출력 및 저장
전체 보고서 제시:
## Reddit ICP 모니터 — [YYYY-MM-DD]
**모니터링한 서브레딧:** r/[서브레딧1], r/[서브레딧2]
**시간 창:** 최근 7일
**검색 키워드:** [구문1], [구문2], [구문3]
**발견된 후보:** X개 게시물
**고신호 매칭 (점수 4-5):** Y개 게시물
---
### 매칭 1 — 점수 [N]/5
**게시물:** [제목](URL)
**서브레딧:** r/[서브레딧] | [N]개의 추천 | [N]개의 댓글
**신호 인용:** "[게시물 본문에서 관련 발췌]"
**일치 키워드:** [구문]
**게시물 유형:** 모드 [1/2/3]
**초안 답변:**
[답변 텍스트]
**답변 단어 수:** N단어
---
[각 매칭에 대해 반복]
---
**결과가 0개인 서브레딧:** [결과가 없는 목록]
점수 >= 4인 게시물이 0개인 경우: "최근 7일 동안 [서브레딧]에서 고신호 매칭을 찾지 못했습니다. 검색 키워드: [목록]. 시간 창을 넓히거나 ('지난 달'이라고 다시 실행) docs/icp.md에서 고통점 구문을 확장해 보세요."
파일로 저장:
mkdir -p docs/reddit-intel
OUTFILE="docs/reddit-intel/$(date +%Y-%m-%d).md"
cat > "$OUTFILE" << 'EOF'
REPORT_CONTENT_HERE
EOF
echo "$OUTFILE에 저장되었습니다"