GamerLinks 구축: 게임 크리에이터를 위한 자동 콘텐츠 스케줄링이 포함된 링크인바이오 플랫폼

발행: (2025년 12월 5일 오후 07:32 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

문제

게임 크리에이터(스트리머, 유튜버 등)는 단순한 링크 목록만으로는 부족합니다. 그들은 다음이 필요합니다:

  • 스트리밍 일정 표시
  • 수익화 옵션 강조
  • 커뮤니티 구축
  • 의미 있는 분석 추적

일반적인 링크‑인‑바이오 도구는 이러한 문제를 해결하지 못하므로, 나는 이를 해결할 무언가를 만들었습니다.

기술 스택

프론트엔드

  • React 19.2.0 (Create React App)
  • React Router v6
  • Tailwind CSS + 커스텀 게임 테마
  • @dnd-kit (드래그‑앤‑드롭)
  • date-fns (날짜/시간 처리)

백엔드

  • Firebase Firestore (NoSQL 데이터베이스)
  • Firebase Authentication
  • Firebase Storage (이미지 저장)
  • Firebase Cloud Functions (서버리스)

주요 라이브러리

  • react-image-crop (아바타 편집)
  • qrcode.react (QR 코드 생성)
  • react-icons (아이콘)

핵심 기능: 자동 콘텐츠 스케줄링

도전 과제

게임 크리에이터는 반복적인 일정(예: 매주 월·수·금 오후 7시 스트리밍)을 가지고 있습니다. 매 이벤트를 수동으로 만들고 싶지 않죠. 시스템은 다음을 수행해야 합니다:

  • 미래 발생을 자동으로 생성
  • 시간대 변환 처리
  • 이벤트 상태 업데이트(예정 → 진행 중 → 완료)
  • 프로필에 동적으로 일정 표시

해결책

나는 다음 3개월 동안 발생을 생성하는 반복 이벤트 시스템을 구축했습니다.

// Simplified version of the logic
function processRecurringEvents(events) {
  const processed = [];

  events.forEach(event => {
    if (event.isRecurring && event.recurrenceType === 'weekly') {
      // Generate occurrences for next 3 months
      const occurrences = generateWeeklyOccurrences(
        event.scheduleStart,
        event.weeklyDays, // [1, 3, 5] for Mon, Wed, Fri
        event.durationHours
      );
      processed.push(...occurrences);
    } else {
      processed.push(event);
    }
  });

  return processed;
}

시스템은 자동으로:

  • 패턴에 따라 이벤트 생성
  • 시간대 변환 수행
  • 현재 시간에 따라 상태 업데이트
  • 과거 이벤트 삭제
  • 미래 발생 생성

이벤트 상태 관리

function updateEventStatuses(events) {
  const now = new Date();

  return events.map(event => {
    const start = new Date(event.scheduleStart);
    const end = new Date(start.getTime() + event.durationHours * 3600000);

    if (now >= start && now  end) {
      return { ...event, status: 'completed' };
    } else {
      return { ...event, status: 'scheduled' };
    }
  });
}

Firestore 실시간 업데이트

useEffect(() => {
  const unsubscribe = subscribeProfileByUsername(username, profile => {
    setProfile(profile);
    // Profile updates automatically when data changes
  });

  return () => unsubscribe();
}, [username]);

크리에이터가 일정을 업데이트하면 모든 시청자가 즉시 변화를 확인합니다.

게임화 시스템

레벨 및 배지 시스템은 다음을 추적합니다:

  • 프로필 조회수
  • 링크 클릭수
  • 획득한 팔로워 수
  • 예약된 콘텐츠 수
  • 기타…

레벨은 Rookie → Bronze → Silver → Gold → Platinum 순으로 상승하며, 배지는 클라우드 함수에서 자동으로 부여해 클라이언트 측 조작을 방지합니다.

보호된 분석

스팸을 방지하기 위해 레이트 리밋, 검증, 배치 처리 큐를 추가했습니다.

// Simplified analytics protection
function trackLinkClick(username, linkUrl) {
  const key = createRateLimitKey(username, 'linkClick');

  if (!checkRateLimit(key, 10, 60000)) { // 10 per minute
    return; // Rate limited
  }

  // Queue for batch processing
  analyticsQueue.push({
    type: 'linkClick',
    username,
    linkUrl,
    timestamp: Date.now()
  });
}

팔로우 시스템

Firestore 서브컬렉션에 팔로워/팔로잉 관계를 저장합니다:

profiles/{profileId}
  └── followers/{followerId}
  └── following/{followingId}

실시간 구독으로 팔로워 수를 최신 상태로 유지합니다:

subscribeToFollowerCount(userId, count => {
  setFollowerCount(count);
});

모바일 퍼스트 디자인

플랫폼은 완전 반응형이며, 인스타그램 스타일 사이드바를 제공합니다:

  • 모바일에서는 왼쪽에서 슬라이드 인
  • 백드롭으로 콘텐츠 오버레이
  • 외부 클릭 시 닫힘
  • 열릴 때 본문 스크롤 방지

직면한 도전 과제

  • 시간대 처리 – 다양한 시간대를 지원하려 date-fns-tz를 사용했습니다.
  • 실시간 성능 – Firestore 리스너가 과도하면 성능 저하가 발생하므로 구독을 배치하고 메모이제이션을 적용했습니다.
  • 이미지 최적화 – 아바타 업로드 시 크롭, 압축, 최적화가 필요했으며 react-image-crop와 Firebase Storage로 해결했습니다.
  • 분석 스팸 – 클라우드 함수에서 서버 측 검증으로 가짜 클릭/조회수를 차단했습니다.

배운 점

  • 단순하게 시작 – 초기 과잉 설계는 불필요한 복잡성을 초래합니다.
  • 실시간의 힘 – Firestore 구독 덕분에 앱이 즉각적으로 반응합니다.
  • 모바일 우선 – 대부분의 크리에이터가 모바일을 사용하므로 모바일 퍼스트 디자인이 필수입니다.
  • 게임화 효과 – 레벨과 배지는 사용자를 지속적으로 참여시킵니다.

현재 상황

GamerLinks는 한 달 전에 출시되었으며 다음 기능을 완전하게 제공하고 있습니다:

  • 자동 콘텐츠 스케줄링
  • 팔로우 시스템
  • 분석
  • 게임화
  • 수익화 기능

현재 사용자 수는 0명이며, 모든 제품은 작은 시작에서 출발합니다.

사용해 보기

게임 크리에이터이거나 알고 있다면 gamerlinks.org 를 확인해 보세요. 시작은 무료이며, 피드백을 환영합니다.

향후 계획

  • 더 많은 플랫폼 연동
  • 향상된 분석
  • 모바일 앱(Capacitor 사용)
  • 팀/협업 기능

질문이 있나요?

기술 스택, 구현 방식, 기능 등에 대해 언제든지 물어보세요. 추가 코드 스니펫을 공유하거나 결정 이유를 설명해 드릴 수 있습니다.

기술 스택 요약

  • React + Firebase
  • 실시간 Firestore 구독
  • 서버‑사이드 로직을 위한 Cloud Functions
  • 모바일 퍼스트 반응형 디자인
  • 자동 콘텐츠 스케줄링 시스템

링크

Back to Blog

관련 글

더 보기 »

JavaScript 첫 걸음: 간단한 정리

JavaScript에서 변수 let: 나중에 값이 변경될 수 있는 경우에 사용합니다. 예시: ```javascript let age = 20; age = 21; ``` const: 값이 절대로 변경되지 않아야 할 때 사용합니다.