# Gap-Timer (갭타이머) - 상세 기술 아키텍처 및 API 명세 ## 1. 서비스 개요 Gap-Timer(https://gap-timer.aiasaas.com)는 모바일 및 데스크톱 웹에서 간단히 간격(초), 수신번호, 머리말, 최대 실행 시간(분)을 설정하고 Start 버튼을 누르면 서버(Node.js + Express + SQLite WAL + Solapi SDK)에서 독립적으로 SMS를 주기 발송하는 시스템입니다. ## 2. 기술 스택 및 아키텍처 - **Runtime & Web**: Node.js, Express - **Database**: SQLite (`better-sqlite3`, WAL 모드) — `jobs`, `logs` 테이블 영속화 - **SMS Gateway**: Solapi 공식 SDK (`solapi`) + 해외 VPS IP 차단 대비 한국 프록시(`SOLAPI_PROXY_URL`) 라우팅 지원 - **Process Manager & Reverse Proxy**: PM2 + Nginx + Let's Encrypt (Certbot HTTPS) ## 3. 정밀 타이머 알고리즘 1. Start 요청 시 `started_at = Date.now()` 기록 후 즉시 1회차 발송(`seq = 1`). 2. 다음 회차(`seq = n + 1`)의 목표 시각을 `target = started_at + n * interval_sec * 1000`으로 계산하여 `setTimeout(tick, Math.max(0, target - Date.now()))` 등록. 3. 서버 재시작 시 `status = 'running'` Job을 조회하여 `n = Math.ceil((now - started_at) / (interval_sec * 1000))`로 다음 정시 회차를 산출, 과거 밀린 회차를 한꺼번에 발송하지 않고 다음 정시부터 정확히 재개. ## 4. REST API 엔드포인트 - `POST /api/login`: 관리자 비밀번호(`ADMIN_PASSWORD`) 인증 및 HttpOnly 세션 쿠키 발급 (IP당 로그인 시도 제한 적용) - `POST /api/logout`: 세션 로그아웃 - `GET /api/status`: 현재 실행 상태, 경과 시간, 다음 발송 남은 초, 예상 비용, 최근 발송 기록 20건 조회 - `POST /api/start`: 주기 발송 Job 시작 (간격 30~3600초, 수신번호, 머리말, 최대 실행 시간) - `POST /api/stop`: 실행 중인 Job 즉시 중지 및 예약 타이머 취소 - `POST /api/test-sms`: 현재 설정으로 테스트 문자 1통 즉시 발송 ## 5. 자주 묻는 질문 (FAQ) - **Q. 브라우저를 닫아도 계속 문자가 발송되나요?** A. 네, 발송 타이머는 브라우저가 아닌 VPS 서버 프로세스(PM2)와 SQLite DB에서 동작하므로 브라우저를 닫거나 휴대폰 전원을 꺼도 설정한 종료 시점까지 계속 동작합니다. - **Q. LMS(장문)로 요금이 더 나올 위험은 없나요?** A. 모든 메시지는 발송 전 EUC-KR 기준 바이트 길이를 계산하여 90바이트 이내로 자동 절삭·검증하므로 단문(SMS) 요금만 부과됩니다. - **Q. 해외 서버 IP라서 솔라피 발송이 차단되면 어떻게 하나요?** A. 솔라피 콘솔(개발자 설정 > API Key 관리)에서 서버 IP(104.237.11.24)를 허용 IP에 추가하거나, `.env`의 `SOLAPI_PROXY_URL`에 한국 IP 프록시를 설정하면 즉시 우회 가능합니다. 최근 상태 동기화 시각: 2026-10-16 20:49:02 (Asia/Seoul)