o2o-castad-backend/error_plan.md

5.8 KiB

ChatGPT API 에러 처리 개선 계획서

1. 현황 분석

1.1 generate_structured_output 사용처

파일 용도 DB 상태 업데이트 응답 상태 변수
app/lyric/worker/lyric_task.py 가사 생성 "failed" 저장 - (백그라운드)
app/home/api/routers/v1/home.py 크롤링 마케팅 분석 없음 없음

1.2 응답 스키마 상태 변수 현황

스키마 위치 상태 변수 조치
CrawlingResponse home_schema.py:158 없음 status 추가
GenerateLyricResponse lyric.py:72 success: bool False로 설정
LyricStatusResponse lyric.py:105 status: str "failed" 설정
LyricDetailResponse lyric.py:128 status: str "failed" 설정

2. 개선 목표

  1. DB 상태 업데이트: 에러 발생 시 DB에 status = "failed" 저장
  2. 클라이언트 응답: 기존 상태 변수가 있으면 "failed" 설정, 없으면 변수 추가 후 설정

3. 상세 작업 계획

3.1 lyric_task.py - ChatGPTResponseError 명시적 처리

파일: app/lyric/worker/lyric_task.py

현재 코드 (Line 138-141):

except Exception as e:
    elapsed = (time.perf_counter() - task_start) * 1000
    logger.error(f"[generate_lyric_background] EXCEPTION - task_id: {task_id}, error: {e} ({elapsed:.1f}ms)", exc_info=True)
    await _update_lyric_status(task_id, "failed", f"Error: {str(e)}")

변경 코드:

from app.utils.chatgpt_prompt import ChatgptService, ChatGPTResponseError

# ... 기존 코드 ...

except ChatGPTResponseError as e:
    elapsed = (time.perf_counter() - task_start) * 1000
    logger.error(
        f"[generate_lyric_background] ChatGPT ERROR - task_id: {task_id}, "
        f"status: {e.status}, code: {e.error_code} ({elapsed:.1f}ms)"
    )
    await _update_lyric_status(task_id, "failed", f"ChatGPT Error: {e.error_message}")

except SQLAlchemyError as e:
    # ... 기존 코드 유지 ...

except Exception as e:
    # ... 기존 코드 유지 ...

결과: DB lyric.status = "failed", lyric.lyric_result = 에러 메시지


3.2 home.py - CrawlingResponse에 status 추가

파일: app/home/schemas/home_schema.py

현재 코드 (Line 158-168):

class CrawlingResponse(BaseModel):
    """크롤링 응답 스키마"""
    image_list: Optional[list[str]] = Field(None, description="이미지 URL 목록")
    image_count: int = Field(..., description="이미지 개수")
    processed_info: Optional[ProcessedInfo] = Field(None, ...)
    marketing_analysis: Optional[MarketingAnalysis] = Field(None, ...)

변경 코드:

class CrawlingResponse(BaseModel):
    """크롤링 응답 스키마"""
    status: str = Field(
        default="completed",
        description="처리 상태 (completed, failed)"
    )
    image_list: Optional[list[str]] = Field(None, description="이미지 URL 목록")
    image_count: int = Field(..., description="이미지 개수")
    processed_info: Optional[ProcessedInfo] = Field(None, ...)
    marketing_analysis: Optional[MarketingAnalysis] = Field(None, ...)

3.3 home.py - 크롤링 엔드포인트 에러 처리

파일: app/home/api/routers/v1/home.py

현재 코드 (Line 296-303):

except Exception as e:
    step3_elapsed = (time.perf_counter() - step3_start) * 1000
    logger.error(...)
    marketing_analysis = None

변경 코드:

from app.utils.chatgpt_prompt import ChatgptService, ChatGPTResponseError

# ... 기존 코드 ...

except ChatGPTResponseError as e:
    step3_elapsed = (time.perf_counter() - step3_start) * 1000
    logger.error(
        f"[crawling] Step 3 FAILED - ChatGPT Error: {e.status}, {e.error_code} ({step3_elapsed:.1f}ms)"
    )
    marketing_analysis = None
    gpt_status = "failed"

except Exception as e:
    step3_elapsed = (time.perf_counter() - step3_start) * 1000
    logger.error(...)
    marketing_analysis = None
    gpt_status = "failed"

# 응답 반환 부분 수정
return {
    "status": gpt_status if 'gpt_status' in locals() else "completed",
    "image_list": scraper.image_link_list,
    "image_count": len(scraper.image_link_list) if scraper.image_link_list else 0,
    "processed_info": processed_info,
    "marketing_analysis": marketing_analysis,
}

4. 파일 변경 요약

파일 변경 내용
app/lyric/worker/lyric_task.py ChatGPTResponseError import 및 명시적 처리 추가
app/home/schemas/home_schema.py CrawlingResponsestatus 필드 추가
app/home/api/routers/v1/home.py ChatGPTResponseError 처리, 응답에 status 포함

5. 변경 후 동작

5.1 lyric_task.py (가사 생성)

상황 DB status DB lyric_result
성공 "completed" 생성된 가사
ChatGPT 에러 "failed" "ChatGPT Error: {message}"
DB 에러 "failed" "Database Error: {message}"
기타 에러 "failed" "Error: {message}"

5.2 home.py (크롤링)

상황 응답 status marketing_analysis
성공 "completed" 분석 결과
ChatGPT 에러 "failed" null
기타 에러 "failed" null

6. 구현 순서

  1. app/home/schemas/home_schema.py - CrawlingResponsestatus 필드 추가
  2. app/lyric/worker/lyric_task.py - ChatGPTResponseError 명시적 처리
  3. app/home/api/routers/v1/home.py - 에러 처리 및 응답 status 설정