홈 화면이 뜨고 나서 Jobs 목록이 한 박자 늦게 채워지는 게 계속 거슬렸다. 오늘은 그거랑 겹쳐 있던 문제들을 같이 정리했다.
page.tsx(서버 컴포넌트)에서 channels만 조회하고 Jobs는 클라이언트에서 useQuery로 다시 불러오고 있었다. 서버에서 첫 채널의 Jobs까지 미리 가져와서 넘겨주도록 바꿨다.
const firstChannelId = channels[0]?.id ?? '';
const initialJobs = firstChannelId
? await apiGet<Job[]>(`/jobs?channelId=${firstChannelId}`, userHeaders).catch(() => [])
: [];
return <HomeClient channels={channels} userId={userId} firstChannelId={firstChannelId} initialJobs={initialJobs} />;
useQuery는 activeChannelId가 firstChannelId랑 같을 때만 initialData를 쓴다. 다른 채널로 넘어가면 그냥 클라이언트에서 fetch한다.
initialData: activeChannelId === firstChannelId ? initialJobs : undefined,
썸네일을 render-worker가 FFmpeg -vframes 1로 첫 프레임을 뽑아서 S3에 올리고 있었는데, upload-worker가 YouTube 업로드 완료 시 youtubeVideoId를 저장하기 시작하면서 i.ytimg.com CDN을 그냥 쓰면 되는 상태가 됐다. 같은 정보를 두 번 만드는 셈이라 S3 경로를 통째로 뺐다.
-const thumbnailPath = join(tmpDir, `${jobId}-thumbnail.jpg`);
-concatClipsWithAudio(clipPaths, audioPath, srtPath, outputPath, ..., thumbnailPath);
+concatClipsWithAudio(clipPaths, audioPath, srtPath, outputPath, ...);
FFmpeg 커맨드 자체도 렌더러에서 걷어냈다.
-if (thumbnailPath) {
- try {
- execSync(`"${ffmpegPath}" -y -i "${concatPath}" -vf "${headerFilter},${footerFilter}" -vframes 1 -q:v 2 "${thumbnailPath}"`, { stdio: 'pipe' });
- } catch { /* 썸네일 생성 실패 시 무시 */ }
-}
프론트에서는 youtubeVideoId 유무로 어떤 썸네일을 쓸지 고르는 헬퍼 하나로 통합했다.
export function effectiveThumbUrl(youtubeVideoId: string | null | undefined, thumbnailUrl: string | null | undefined): string | null {
if (youtubeVideoId) return `https://i.ytimg.com/vi/${youtubeVideoId}/hqdefault.jpg`;
return toProxyThumbUrl(thumbnailUrl);
}
syncChannel이 YouTube Data API로 채널 전체 누적 조회수를 정확히 저장하는데, 바로 뒤에서 syncVideos가 앱에서 업로드한 영상들의 viewCount만 합산해서 같은 필드를 또 덮어쓰고 있었다. 당연히 YouTube Studio 수치랑 어긋난다.
-const totalVideoViews = viewCountUpdates.reduce((sum, v) => sum + v.viewCount, 0);
-await this.repo.updateTotalViews(channelId, totalVideoViews);
updateTotalViews 메서드 자체를 지웠다. 이제 totalViews는 syncChannel 한 곳에서만 쓴다.
같이 syncChannel에서 채널명도 갱신하도록 살짝 얹었다. channels.list에 snippet part를 추가하면 되는 간단한 거였다.
const channelRes = await yt.channels.list({ part: ['statistics', 'snippet'], id: [channelRow.youtubeId] });