본문 바로가기
개인프로젝트

(기록용)치지직 Top 20 분석 서비스를 만들면서 마케팅을 놓친 것들

by goodchuck 2026. 4. 7.

목차

     

     

    치지직 왓처(Chzzk Watcher)는 네이버 치지직의 시간별 Top 20 스트리머 순위를 자동 수집하고, 팔로우 추이·채팅 버스트·랭킹 히스토리를 분석하는 서비스다. Next.js 16 + NestJS + PostgreSQL 기반의 모노레포 구조로 운영 중이다.

    시작하게된 배경

    치지직이 빠르게 성장하면서 "지금 Top 20에 누가 있는지", "어제 1위가 누구였는지" 같은 정보를 찾을 수 있는 곳이 없었다. 트위치에는 비슷한 분석 서비스가 있는데 치지직은 아무것도 없다는 게 아쉬웠고, 그게 개발의 출발점이었다.

    결과적으로 서비스는 만들었는데, 돌아보니 "만드는 것"에만 집중하고 "알리는 것"과 "검색되는 것"은 거의 고민하지 않았다. 이 글은 그 부분에 대한 솔직한 회고다.


    실제로 만든 것들

    • 시간별 Top 20 스냅샷: 매 정각 자동 수집, 시청자 수·순위·채팅 저장
    • 스트리머 상세 페이지: 랭킹 히스토리, 명예의 순간, 팔로우 추이 차트
    • 소속사/그룹 카탈로그: 버튜버 소속사, 그룹 단위 정렬·집계
    • 채팅 버스트 감지: "ㅋㅋㅋ", "대박", "레전드" 등 반응 급증 감지
    • 명예의 전당: 역대 최고 순위, 이번 주 급상승, 단골 스트리머 섹션

    기능적으로는 꽤 촘촘하게 만들었다고 생각했다.


    SEO를 뒤늦게 들여다봤을 때

    서비스를 어느 정도 완성하고 나서 "검색하면 나올까?" 하고 처음으로 SEO를 점검했다. 결과는 복잡했다.

    잘 된 것들

    동적 메타데이터는 챙겼다. 스트리머 상세 페이지(/streamer/[channelId])에는 스트리머 이름, 프로필 이미지, 통계를 담은 OG 태그와 Twitter Card가 있다. 카카오톡이나 트위터에 링크를 공유하면 미리보기가 제대로 나온다.

    export async function generateMetadata({ params }) {
      const streamer = await fetchStreamer(params.channelId);
      return {
        title: `${streamer.channelName} — Chzzk Watcher`,
        openGraph: {
          images: [{ url: streamer.channelImageUrl }],
          type: 'profile',
        },
        twitter: { card: 'summary', ... }
      };
    }

    사이트맵도 동적으로 생성했다. /sitemap.ts에서 DB에 있는 스트리머·소속사·그룹 200개 이상의 페이지를 자동으로 포함시킨다. Google이 크롤링할 루트는 열어뒀다.

    robots.txt도 제대로 구성했다. 실시간 기능(/chat-monitor, /live-feed)처럼 색인될 필요 없는 페이지는 크롤링을 막았다.

    GA4는 초기에 붙였다. Vercel Analytics와 함께 기본 페이지뷰는 잡히고 있었다.

    놓친 것들

    찬찬히 보니 구멍이 꽤 있었다.

    1. JSON-LD 구조화 데이터가 없었다

    검색 결과에서 리치 스니펫이 나오려면 JSON-LD가 필요하다. 스트리머 상세 페이지에 Person 스키마를, 메인 페이지에 WebSite 스키마를 넣었다면 검색 결과 노출 품질이 달라졌을 거다.

    <!-- 넣었어야 했던 것 -->
    <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "Person",
      "name": "스트리머 이름",
      "url": "https://chzzk.naver.com/...",
      "image": "프로필 이미지 URL"
    }
    </script>

    2. 목록 페이지에 OG 이미지가 없었다

    스트리머 목록(/streamer), 차트(/chart), 소속사 목록(/companies)처럼 트래픽이 집중되는 페이지에 OG 이미지가 없었다. SNS에 공유하면 이미지 없이 링크만 나온다. 브랜드 이미지 하나만 넣어도 CTR이 다르다.

    3. 커스텀 이벤트 트래킹을 안 했다

    GA4가 붙어있어도 기본 페이지뷰만 수집됐다. "스트리머 클릭", "소속사 필터 사용", "채팅 버스트 카드 클릭" 같은 유저 행동 데이터가 없으니 어떤 기능이 실제로 쓰이는지 알 수 없었다.

    // 처음부터 했어야 했던 것
    trackEvent('streamer_click', { channelId, source: 'hall_of_fame' });
    trackEvent('filter_applied', { type: 'company', value: companyName });

    4. 기능을 만들었지만 노출 구조를 안 만들었다

    팔로우 추이 차트 기능을 개발하면서 "이 기능이 어떤 키워드로 검색되어야 하나?"를 한 번도 생각하지 않았다. "치지직 스트리머 팔로워", "치지직 구독자 추이" 같은 검색어가 있을 텐데, 그 키워드를 페이지 제목과 설명에 자연스럽게 넣는 작업을 하지 않았다.


    마케팅을 빠뜨린 이유

    돌아보면 이유가 명확하다.

     

    기능 완성도가 먼저였다. "이 기능이 작동하는가?"는 체크했지만 "이 기능을 유저가 발견할 수 있는가?"는 묻지 않았다. 스냅샷 수집 크론, 채팅 버스트 감지 알고리즘, WebSocket 연결 관리 같은 기술적 문제를 푸는 게 더 흥미롭기도 했다.

    "SEO는 나중에"가 생각보다 훨씬 늦어졌다. 페이지가 20개가 넘어가니 하나씩 뜯어고치는 게 처음부터 잘 짜는 것보다 훨씬 번거롭다.

    유저 행동 데이터가 없으니 개선 방향을 모른다. 어드민으로 DB를 직접 보거나 서버 로그를 뒤지는 방식으로 확인하다 보니 "유저가 어디서 이탈하는지" 같은 질문에 답을 못 했다.


    지금이라도 챙긴 것들

    최근에 다시 점검하면서 몇 가지를 챙겼다.

    팔로우 추이 기능을 만들면서 SEO를 같이 고민했다. GET /streamer/:channelId/follower-history 엔드포인트를 추가하면서 페이지 설명에 "팔로우 추이"라는 표현을 명시적으로 넣었다. 작은 차이지만 의식적으로 챙겼다는 게 다르다.

    추적 요청 기능에는 CTA 카피를 먼저 썼다. "아직 추적하지 않는 스트리머입니다"보다 "팔로우 성장 그래프를 보고 싶다면 추적을 요청해주세요"가 유저에게 더 명확하다. 버튼을 만들기 전에 문구를 먼저 결정했다.


    다음 프로젝트에서 바꿀 것들

    기능 스펙을 정할 때 "검색 키워드"도 함께 정한다. 팔로우 차트 기능을 기획할 때 "치지직 구독자 추이", "치지직 팔로워 변화" 같은 검색어를 함께 정리하고, 그 표현이 페이지 제목과 설명에 들어가도록 설계한다.

    커스텀 이벤트 트래킹은 기능 개발과 동시에 한다. 새 페이지나 기능을 배포할 때 GA4 이벤트 1~2개는 항상 같이 붙인다. 나중에 몰아서 하면 안 한다.

    OG 이미지는 정적 페이지에도 넣는다. Next.js의 opengraph-image 파일 컨벤션을 쓰면 목록 페이지도 쉽게 커버된다.

    JSON-LD는 상세 페이지 개발 때 기본으로 포함한다. 고유 URL이 있는 페이지는 구조화 데이터 없이 배포하지 않는다.


    마무리

    "SEO는 나중에"라고 미뤘을 때 실제로 잃은 건 유기적 유입 기회다. 광고 예산이 없는 사이드 프로젝트에서 SEO는 사실상 유일한 무료 마케팅 채널이다.

    기능을 잘 만드는 것과 그 기능이 발견되게 만드는 건 다른 일이다. 둘 다 챙겨야 한다.


    Chzzk Watcher는 현재도 운영 중이다. 치지직 스트리머의 랭킹 히스토리와 팔로우 추이가 궁금하면 둘러보자.

    https://chzzk.yangtinomad.com/chart