콘텐츠 자동화 파이프라인에 Groq 모델 지원 종료 알림 추가 및 gpt‑oss‑120b로의 마이그레이션
요약
Groq 모델 지원 종료로 인한 콘텐츠 자동화 파이프라인의 SyntaxError를 해결하고, gpt-oss-120b로의 마이그레이션을 수행했습니다. 모델 지원 종료 시 이메일 알림을 발송하는 기능을 추가하여 모델 수명 주기에 대한 가시성을 확보했습니다.
핵심 포인트
- Groq 모델 지원 종료 시 발생하는 HTML 에러 응답에 대한 예외 처리
- 모델 지원 종료 감지 및 이메일 기반 알림 시스템 구현
- gpt-oss-120b 엔드포인트로의 성공적인 마이그레이션
- 모델 수명 주기 관리를 통한 파이프라인 안정성 강화
콘텐츠 자동화 파이프라인에 Groq 모델 지원 종료 알림 추가 및 gpt‑oss‑120b로의 마이그레이션
요약 (TL;DR): Groq 모델이 지원 종료(deprecation)될 때 발송되는 이메일 기반 알림을 추가하였고, 여전히 사용 가능한 모델 목록을 나열했으며, 새로운 gpt‑oss‑120b 엔드포인트를 사용하도록 생성기를 업데이트했습니다. 이 변경 사항은 콘텐츠 자동화 실행을 중단시켰던 “SyntaxError: Unexpected token ‘<’” 오류를 해결하고, 팀이 모델 수명 주기(lifecycle)를 파악할 수 있도록 가시성을 제공합니다.
문제 상황
우리의 야간 content‑automation 작업이 다음과 같은 오류와 함께 실패하기 시작했습니다:
SyntaxError: Unexpected token '<' in src/content_generator.py line 142
스택 트레이스(stack trace)는 API 응답에서 Groq 모델 목록을 파싱하는 _list_available_models 헬퍼 함수를 가리켰습니다. Groq는 gpt‑oss‑20b 모델의 지원 종료를 발표했지만, 우리 코드는 여전히 해당 모델을 요청하려고 시도했고, 그 결과 JSON 대신 HTML 에러 페이지(<html>…)를 받게 되었습니다. JSON 파서가 < 토큰 오류를 발생시키면서 전체 파이프라인이 중단되었고, 당일 Medium, Substack, Dev.to 포스트 생성이 불가능해졌습니다.
즉각적인 충돌 외에도, 모델이 은퇴(retired)될 때 이를 확인할 수 있는 가시성이 없었기 때문에, CI 작업이 실패한 후에야 문제를 발견할 수밖에 없었습니다.
처음 시도했던 방법
저의 첫 번째 본능은 JSON 파싱 예외(exception)를 포착하여 이전 모델로 폴백(fallback)하는 것이었습니다:
def _list_available_models(self) -> list[str]:
try:
resp = httpx.get(self.MODEL_ENDPOINT)
...
이 방식은 파이프라인을 계속 유지시켜 주었지만, 지원이 종료된 모델을 조용히 계속 사용하게 만들어 매 실행마다 동일한 HTML 응답을 받게 했습니다. 알림은 전혀 발생하지 않았고, 우리는 더 이상 존재하지 않는 모델로 콘텐츠를 계속 생성하게 되어 출력 품질이 저하되는 결과를 초래했습니다.
또한 설정 파일(config file)에서 엔드포인트 URL을 패치하려고 시도했으나, 설정 파일은 여러 환경에서 공유되므로 하드코딩된 변경은 여전히 이전 모델을 사용하는 다른 브랜치들을 망가뜨릴 수 있었습니다.
구현 내용
1. 지원 종료 감지 및 알림 전송
해결책의 핵심은 src/content_generator.py에 구현되어 있습니다. 저는 _list_available_models를 확장하여 모델 목록과 함께 이전에 사용하던 모델 중 누락된 것이 있는지 나타내는 플래그를 반환하도록 했습니다. 그런 다음, 여전히 사용 가능한 모델 목록과 저장소의 GitHub Secrets 페이지 링크를 포함한 이메일을 작성하는 _send_deprecation_alert를 도입했습니다 (이를 통해 팀이 모델 이름을 저장하는 Secret을 업데이트할 수 있습니다).
# src/content_generator.py
import smtplib
from email.message import EmailMessage
...
주요 변경 사항:
- 이제 함수가 튜플(tuple)을 반환하여, 호출자가 작업을 계속 진행할지 아니면 중단할지를 결정할 수 있습니다.
- 지원 종료(Deprecation) 감지는 간단한 집합 차집합(set subtraction) 연산을 사용합니다. 우리가 예상하는 모델(
DEPRECATED_MODELS) 중 하나라도 누락되었다면, 이를 지원 종료된 것으로 간주합니다. - 알림에는 GitHub Secrets 페이지로 연결되는 직접 링크가 포함되어 있어, 누구나 쉽게 Secret을 교체(rotate)할 수 있습니다.
2. gpt‑oss‑120b로의 마이그레이션 (Migrating)
이전 모델이 사라졌음을 확인하면, 더 새롭고 더 큰 모델로 전환해야 합니다. 저는 여전히 사용 가능한 모델 중 가장 용량이 큰 모델을 선택하는 작은 헬퍼 함수인 _pick_preferred_model을 추가했습니다.
def _pick_preferred_model(self, models: list[str]) -> str:
# 선호 순서: 120b > 70b > 40b > 20b
preference = ["gpt-oss-120b", "gpt-oss-70b", "gpt-oss-40b", "gpt-oss-20b"]
...
ContentGenerator의 초기화 과정에서 이제 감지 흐름(detection flow)을 실행합니다:
class ContentGenerator:
def __init__(self):
self.available_models, self.has_deprecated = self._list_available_models()
...
지원 종료된 모델이 없으면 알림이 발송되고, 생성기(generator)는 자동으로 gpt‑oss‑120b를 선택합니다. 이를 통해 수동으로 설정을 변경할 필요가 없어지며, 우리가 접근 가능한 가장 유능한 모델을 항상 사용하도록 보장합니다.
3. CI 파이프라인 업데이트
CI 작업 (.github/workflows/content.yml)은 이제 경고 이메일에 필요한 환경 변수 (environment variables)를 설정합니다. 작업이 실행되기 전에 시크릿 (secret) ALERT_SENDER가 존재하는지 확인하는 단계를 추가하여, 문제가 있을 경우 명확한 메시지와 함께 즉시 실패(fail fast)하도록 했습니다:
- name: Verify alert secrets
run: |
if [ -z "${{ secrets.ALERT_SENDER }}" ]; then
...
4. 문서화 (Documentation)
새로운 모델 테이블을 반영하기 위해 docs/CLAUDE.md 및 docs/CLAUDE_CODE_CONTEXT.md를 업데이트하였으며 (content/2026/08/03/VS/changelog.md 참조), "모델 지원 종료 처리 (Model deprecation handling)" 섹션을 추가했습니다. 변경 로그 (changelog) 항목은 다음과 같이 작성되었습니다:
## 2026‑08‑03 VS
### Changed
- `src/content_generator.py` – 지원 종료 경고 이메일 및 gpt‑oss‑120b로의 자동 마이그레이션 (auto‑migration) 추가.
...
핵심 요약 (Key Takeaway)
외부 API의 계약 (contract)이 불변할 것이라고 절대 가정하지 마세요. 모델 가용성을 동적인 설정 (dynamic configuration)으로 취급하고 이를 자동화된 경고와 결합함으로써, 조용히 발생하는 중단 변경 (breaking change)을 가시적이고 실행 가능한 이벤트로 전환할 수 있습니다. 이 패턴—가져오기(fetch)‑검증(validate)‑경고(alert)‑폴백(fallback)—은 리소스를 지원 종료할 수 있는 모든 제3자 서비스 (third‑party service)에 재사용될 수 있습니다.
향후 계획 (What’s Next)
- 재시도 로직 (Retry logic): 일시적인 네트워크 장애를 처리하기 위해 모델 목록 요청에 지수 백오프 (exponential back‑off)를 추가합니다.
- 기능 플래그 (Feature flag): 팀이 코드 변경 없이 실험적 모델을 선택할 수 있도록 선호 모델 목록을 환경 변수를 통해 노출합니다.
- 대시보드 (Dashboard): 지원 종료 경고를 Slack 채널로 전송하고, 이력 분석을 위해 작은 SQLite 로그에 저장합니다.
태그: #vibecoding #buildinpublic #python #automation #ai #email #groq #gpt-oss
Roberto Luna Osorio – 풀스택 개발자 (Full Stack Developer) 및 프로젝트 리드 (Project Lead)
나의 Build in Public 시리즈의 일부 — 멕시코 플레이아 델 카르멘에서 SaaS 프로젝트를 구축하는 실제 과정을 공유합니다.
Repo: zaerohell/content-automation · 2026-08-04
#playadev #buildinpublic
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기