본문 바로가기
프로젝트/Chrome 확장

Chrome 확장 프로그램 #1 - Ticket Timer (티켓팅 타이머)

by 루까(Luka) 2026. 1. 28.
반응형

Chrome 확장 프로그램 — Ticket Timer

왜 만들었나

티켓팅을 해본 사람이면 안다. 오픈 시각에 0.1초가 늦으면 매진이다. 그런데 내 컴퓨터 시계가 정확한지 확인할 방법이 마땅치 않다.

기존에는 time.is 같은 사이트를 옆에 띄워놓고 비교했는데, 여러 공연을 동시에 준비할 때는 탭마다 다른 시간을 관리해야 해서 번거로웠다. 핸드폰 알람까지 세팅하면 정신없다.

표준시 API와 자동 동기화되는 탭별 타이머를 만들기로 했다.

Chrome Web Store: 티켓팅 타이머 설치하기


핵심 기능

1. 서버 시간 동기화

컴퓨터 시계를 믿지 않는다. Google과 Cloudflare의 HTTP 헤더에서 서버 시간을 가져와서 로컬 시간과의 오차를 계산한다.

async function syncServerTime() {
    const beforeFetch = Date.now();
    const response = await fetch('https://www.google.com', { method: 'HEAD' });
    const afterFetch = Date.now();

    const serverTime = new Date(response.headers.get('date')).getTime();
    const roundTripTime = afterFetch - beforeFetch;

    // 네트워크 지연의 절반만큼 보정
    serverTimeOffset = serverTime - beforeFetch + (roundTripTime / 2);
}

네트워크 왕복 시간(RTT)의 절반을 보정하는 게 핵심이다. 요청이 서버에 도착하는 데 걸리는 시간을 추정해서 빼준다. 이걸로 밀리초 단위의 정확도를 확보한다.

Google이 안 되면 Cloudflare의 CDN trace API로 폴백한다. 둘 다 안 되면 로컬 시간을 그대로 쓴다.

2. 탭별 독립 타이머

탭마다 다른 타이머를 설정할 수 있다.

// Chrome Storage에 tabId를 키로 저장
const { timers = {} } = await chrome.storage.local.get('timers');
timers[tab.id] = {
    concertName: '아이유 콘서트',
    openTime: '2026-02-01T14:00:00',
    autoRefresh: true,
    tabTitle: tab.title,
    tabUrl: tab.url
};
await chrome.storage.local.set({ timers });

인터파크에서 아이유 콘서트, 예스24에서 뮤지컬 — 이런 식으로 탭별로 독립적으로 관리된다. 탭을 닫으면 해당 타이머도 자동 삭제된다.

3. 알림 + 자동 새로고침

설정 시각이 되면:

  1. 브라우저 알림 (requireInteraction: true — 직접 닫을 때까지 유지)
  2. 해당 탭 자동 활성화 + 창 포커스
  3. 자동 새로고침 (옵션으로 ON/OFF)
function handleAlarmTrigger(tabId, timer) {
    chrome.notifications.create(`timer-${tabId}`, {
        type: 'basic',
        title: '🎫 티켓팅 시간입니다!',
        message: `${timer.concertName}\n지금 바로 티켓팅을 시작하세요!`,
        priority: 2,
        requireInteraction: true
    });

    chrome.tabs.update(tabId, { active: true });
    if (timer.autoRefresh) {
        chrome.tabs.reload(tabId);
    }
}

4. 실시간 카운트다운

확장 아이콘의 배지에 남은 시간이 표시된다. 3d2h45m30s 식으로 단위가 자동 전환된다. 팝업을 열면 초 단위 카운트다운을 볼 수 있다.


기술적 챌린지

Manifest V3의 Service Worker

V3에서는 백그라운드 페이지 대신 Service Worker를 사용한다. 차이점:

  • DOM 접근 불가 — document, window 사용 못함
  • 비활성 시 자동 종료 — 지속적으로 살아있지 않음
  • setTimeout은 되지만, 장시간 타이머는 보장 안됨

이 때문에 chrome.alarms도 검토했지만, 1분 미만 간격을 지원하지 않아서 초 단위 정밀도가 필요한 이 프로젝트에서는 setTimeout + 재귀 호출 방식을 선택했다.

function updateBadgeForTab(tabId) {
    function update() {
        const diff = new Date(openTime) - getAccurateTime();
        if (diff <= 0) {
            chrome.action.setBadgeText({ text: '!', tabId });
            return;
        }
        const text = formatCountdown(diff);
        chrome.action.setBadgeText({ text, tabId });
        setTimeout(update, 1000);
    }
    update();
}

외부 fetch 권한

Manifest V3에서 외부 URL에 fetch를 보내려면 host_permissions에 명시해야 한다.

{
    "host_permissions": [
        "https://www.google.com/*",
        "https://cloudflare.com/*"
    ]
}

이걸 빠뜨리면 시간 동기화가 CORS 에러로 실패한다. permissions가 아니라 host_permissions에 넣어야 한다.

브라우저 재시작 대응

Service Worker는 재시작 시 메모리가 초기화된다. 기존 타이머를 잃지 않으려면 chrome.storage.local에서 복원해야 한다.

chrome.runtime.onStartup.addListener(async () => {
    await syncServerTime();
    await loadExistingTimers();  // storage에서 타이머 복원
});

미래 시각의 타이머만 다시 활성화하고, 이미 지난 타이머는 건드리지 않는다.


Chrome Web Store 배포

비용

항목 비용
개발 $0
개발자 등록 $5 (1회)
호스팅 (개인정보처리방침) $0 (GitHub Pages)
합계 $5

배포에 필요한 것

생각보다 준비물이 많다:

  • 확장 프로그램 zip 파일
  • 스크린샷 5장 (1280×800)
  • 아이콘 3종 (16, 48, 128px)
  • 개인정보처리방침 URL — 의외로 필수
  • 각 권한별 사용 이유 설명

개인정보처리방침은 GitHub Pages에 privacy-policy.html을 올려서 해결했다. 무료다.

심사 정책

Google이 중요하게 보는 것:

  1. 단일 목적 원칙 — 확장이 하나의 명확한 기능만 해야 함
  2. 최소 권한 원칙 — 필요한 권한만 요청
  3. 원격 코드 실행 금지 — 외부 JS 로드 불가
  4. 사용자 데이터 수집 여부 — 수집 안 하면 "아니요"

각 권한마다 "왜 이 권한이 필요한지"를 한 줄씩 써야 한다. 대충 쓰면 리젝당한다.


개발 타임라인

날짜 작업 시간
Day 1 아이디어 + 기획 2h
Day 2 핵심 기능 (시간 동기화, 타이머) 4h
Day 3 UI/UX 구현 3h
Day 4 테스트 + 버그 수정 2h
Day 5 배포 자료 준비 3h
Day 6 Web Store 등록 2h
합계   ~16h

배포 자료 준비가 3시간이나 걸렸다. 스크린샷 찍고, 설명 쓰고, 개인정보처리방침 만들고, 권한 사유 작성하는 데 생각보다 시간이 든다. 개발보다 배포 준비가 귀찮았다.


마무리

$5로 Chrome Web Store에 확장 프로그램을 올렸고, 심사를 통과해서 현재 누구나 설치할 수 있다. 개발 자체보다 배포 프로세스를 한 번 경험하는 게 가장 큰 수확이었다. 심사 정책, 권한 설명, 개인정보처리방침 — 이런 것들은 직접 해봐야 감이 잡힌다.

다음 Chrome 확장은 QA 업무에서 쓸 보안 스캐너를 만들 예정이다.


기술 스택: Vanilla JavaScript, Chrome Extension APIs (Manifest V3), Service Worker
소스 코드: GitHub
Chrome Web Store: 티켓팅 타이머

반응형