일일 생성 한도를 3회에서 6회로 올렸다. 채널당 하루 3개는 너무 짜다는 판단.
// jobs.service.ts
const DAILY_LIMIT = 6;
한 줄짜리 변경인데, 이 뒤로 대시보드 썸네일 표시 쪽에서 한나절 미세조정이 이어졌다.
영상 상태는 네 가지다. 정상, 실패, 삭제(유튜브에서 지워짐), 비공개. 근데 지금까지는 실패와 삭제를 구분 안 하고 똑같이 "삭제"라고만 보여주고 있었다.
<div className={`w-full h-full flex items-center justify-center ${
job.status === 'FAILED'
? job.failReason === '유튜브에서 영상이 삭제되었습니다.'
? 'bg-white/5'
: 'bg-red-500/10'
: 'bg-white/5'
}`}>
{job.status === 'FAILED' ? (
<span className={...}>
{job.failReason === '유튜브에서 영상이 삭제되었습니다.' ? '삭제' : '실패'}
</span>
) : (
<Video className="w-4 h-4 text-white/30" />
)}
</div>
failReason 문자열로 분기해서 삭제는 회색, 실패는 빨간 톤으로 구분했다.
비공개는 또 다른 케이스다. 처음엔 상세 페이지에서 blur 오버레이를 씌우고 15초마다 썸네일 재시도 로직을 돌렸는데, 비공개 영상은 애초에 썸네일이 안 뜨니까 이 retry가 무한 반복이었다.
- const rawThumb = job.status !== 'FAILED' ? effectiveThumbUrl(...) : null;
+ const rawThumb = (job.status !== 'FAILED' && job.privacyStatus !== 'private') ? effectiveThumbUrl(...) : null;
- // YouTube CDN 썸네일 미처리(404) 시 15초 후 자동 재시도
+ // YouTube CDN 썸네일 미처리(404) 시 15초 후 자동 재시도 (비공개 영상은 항상 404이므로 스킵)
useEffect(() => {
- if (!thumbnailError || !job?.youtubeVideoId) return;
+ if (!thumbnailError || !job?.youtubeVideoId || job?.privacyStatus === 'private') return;
blur+backdrop 오버레이도 걷어내고 그냥 "비공개" 플레이스홀더로 바로 처리하게 바꿨다. 어차피 썸네일이 없으니 오버레이를 씌울 대상 자체가 없다.
scriptContent가 null일 때 스크립트 패널의 hook, 썸네일 텍스트, 해시태그 영역이 통째로 사라지면서 패널 높이가 들쭉날쭉했다. 조건부 렌더링을 각 필드 단위로 쪼개서, 값이 없으면 dim 처리된 빈 블록을 채우도록 바꿨다.
<div>
<p className="text-xs text-white/40 mb-1.5">후크 문구</p>
{sc?.hook
? <p className="text-sm font-medium text-white italic">“{sc.hook}”</p>
: <div className="h-4 rounded bg-white/5 w-4/5" />
}
</div>
삭제 플레이스홀더 배경이 bg-black/60이었는데 너무 어두워서 bg-black/40으로 낮췄다. 조회수 뱃지 배경도 같이 맞췄다. 이런 명도 조정은 코드로는 한 줄이지만 실제로 화면 보면서 몇 번을 왔다갔다 했다.