DOCS/troubleshooting/20251002_slack_bot_403_error.md
happybell80 bdd450945f 트러블슈팅: Slack 봇 메시지 403 에러 해결 방안 추가
- 문제: robeing 봇(U0935RJ60V6) 메시지 처리 시 403 에러 반복 발생
- 원인: 게이트웨이가 봇과 사용자를 구분하지 않고 UUID 매핑 요구
- 해결: 봇 메시지 필터링 로직 추가 제안

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-02 13:36:43 +09:00

3.5 KiB

Slack 봇 메시지 403 에러 처리

발생 일시

2025-10-02 13:29 ~ 13:31

현상

robeing-gateway 로그에서 지속적인 403 Forbidden 에러 발생

에러 로그

app.services.slack_proxy - WARNING - No UUID found for Slack user U0935RJ60V6
app.routers.slack - ERROR - User not registered: team_id=T0925SXPS4D, slack_user_id=U0935RJ60V6

패턴

  • 빈도: 1-2분마다 반복 발생
  • HTTP 응답: 403 Forbidden
  • 영향: 불필요한 에러 로그 생성, 리소스 낭비

원인 분석

문제의 핵심

U0935RJ60V6는 로빙(Robeing) 봇의 Slack User ID로, 봇이 메시지를 보낼 때마다 게이트웨이가 이를 일반 사용자 메시지로 처리하려고 시도

상세 분석

  1. 현재 로직

    • 모든 Slack 이벤트에 대해 UUID 매핑 요구
    • 봇 메시지도 사용자 등록 검증 시도
    • UUID가 없으면 403 반환
  2. 정상 동작 vs 비정상 동작

    • 정상: U0925SXQFDK(사용자) → UUID 변환 성공 → rb8001 전달 → 200 OK
    • 비정상: U0935RJ60V6(봇) → UUID 찾기 실패 → 403 Forbidden

해결 방안

1. 즉시 적용 가능한 수정

/home/admin/robeing-gateway/app/routers/slack.py 수정

방법 1: 하드코딩 (빠른 수정)

# Line 56-57 사이에 추가
team_id, slack_user_id = extract_team_and_user_from_event(body)

# Skip bot messages
if slack_user_id == "U0935RJ60V6":
    logger.info(f"Skipping bot message from {slack_user_id}")
    return JSONResponse({"ok": True}, status_code=200)

logger.info(f"Slack event from team: {team_id}, user: {slack_user_id}")

방법 2: 환경변수 활용 (권장)

  1. .env 파일에 추가:

    SLACK_BOT_USER_ID=U0935RJ60V6
    
  2. 코드 수정:

    import os
    
    SLACK_BOT_USER_ID = os.getenv("SLACK_BOT_USER_ID")
    
    # Line 56-57 사이에 추가
    if slack_user_id == SLACK_BOT_USER_ID:
        logger.info(f"Skipping bot message from {slack_user_id}")
        return JSONResponse({"ok": True}, status_code=200)
    

2. 장기적 개선 방안

Slack 이벤트 타입별 처리

# event 타입 확인
event_type = body.get("event", {}).get("type")
event_subtype = body.get("event", {}).get("subtype")

# bot_message 서브타입 필터링
if event_subtype == "bot_message":
    logger.debug(f"Skipping bot_message from {slack_user_id}")
    return JSONResponse({"ok": True}, status_code=200)

봇 ID 목록 관리

여러 봇을 사용하는 경우 환경변수에 쉼표로 구분:

SLACK_BOT_USER_IDS=U0935RJ60V6,U1234567890

적용 절차

  1. 로컬 개발 환경에서 코드 수정
  2. Git push → Gitea Actions 자동 배포
  3. 게이트웨이 재시작 확인
  4. 로그 모니터링으로 403 에러 해결 확인

검증 방법

# 403 에러 확인
docker logs robeing-gateway --tail 100 | grep "U0935RJ60V6"

# 수정 후 정상 동작 확인
docker logs robeing-gateway --tail 100 | grep "Skipping bot message"

교훈

  1. 봇과 사용자 구분 필수: Slack 이벤트 처리 시 봇 메시지는 별도 처리 필요
  2. 환경변수 활용: 봇 ID 등 변경 가능한 값은 환경변수로 관리
  3. 이벤트 타입 확인: Slack의 subtype 필드 활용으로 더 정확한 필터링 가능

관련 파일

  • /home/admin/robeing-gateway/app/routers/slack.py
  • /home/admin/robeing-gateway/.env

참고사항

  • Slack Bot User ID는 워크스페이스마다 다를 수 있음
  • 봇 메시지 필터링은 성능 향상과 로그 정리에 도움