Skip to main content

JunkBox apps/message-api 가이드

1. 애플리케이션 역할

  • apps/message-api는 홈서버 애플리케이션과 셸 스크립트의 메시지 발송 공통 진입점임.
  • 외부 요청, 웹 즉시 발송, 예약 발송, 정기 발송, 수동 재발송은 하나의 메시지 발송 서비스 계층을 사용함.
  • 메시지 요청을 SQLite 이력에 먼저 저장하고 Apprise API 호출 결과를 같은 이력에 반영함.
  • Apprise API는 실제 채널 전달 엔진이며 Telegram, Discord 등의 채널 연결 정보는 Message 앱이 소유하지 않음.
  • Message 앱은 셸 스크립트 실행, crontab 관리, 대형 메시지 브로커, 직접 Telegram/Discord 연동을 소유하지 않음.

2. 런타임 구성

  • FastAPI 엔트리포인트는 junkbox_message_api.main:app임.
  • 기본 루트 //messages로 리다이렉트됨.
  • 상태 확인 경로는 /health임.
  • apps/message-ui/dist/message-ui 경로로 직접 마운트함.
  • libs/shared-ui 산출 자산은 /shared-ui 경로로 직접 마운트함.
  • 웹 화면은 shared-ui base.html을 상속한 message.html 앱 셸 위에 React SPA를 마운트함.
  • 템플릿은 shared_ui_asset()으로 공통 CSS/JS에 파일 수정 시각 기반 버전 쿼리를 붙이고, stylesheet 매크로로 hub-ui-base.css + hub-ui-mobile.css 조합을 로드함.
  • 페이지 전용 CSS, inline <style>, inline style은 사용하지 않음.

2.1 로컬 개발 및 운영 포트

  • 로컬 비컨테이너 기본 포트는 API 18004, Vite 15004임.
  • 운영 컨테이너 포트는 8004이며 Docker Compose 서비스명은 junkbox-message임.
  • 개발·운영 Compose는 junkbox-hub 이후에 시작하며 /sorc001/junkbox/db/app/db로 마운트함.
  • 운영 환경은 /sorc001/junkbox/env/.env.shared, /sorc001/junkbox/env/.env.prod를 사용하고 컨테이너 내부 ENV_FILE=/app/env/.env.prod 기준으로 로드함.
  • 운영 로그는 /logs001/junkbox/message-api를 컨테이너 /app/logs에 마운트하며 공통 앱 로그 경로는 /app/logs/app.log임.
  • Dockerfile은 shared-ui 자산과 message-ui Vite 산출물을 빌드한 뒤 런타임 이미지에 포함함.
  • GitHub Actions 배포 감지는 apps/message-api/**, apps/message-ui/**, libs/shared-core/**, libs/shared-ui/**, docker-compose.prod.ymljunkbox-message 이미지 빌드·배포 대상으로 연결함.

3. 설정 계약

  • MESSAGE_DATABASE_URL은 Message SQLite DSN임.
  • 로컬 기본 DSN은 sqlite+aiosqlite:////sorc001/junkbox/db/message.sqlite3임.
  • Docker 기준 DSN은 sqlite+aiosqlite:////app/db/message.sqlite3임.
  • Apprise 연동은 settings.modules.message 설정을 사용함.
  • Apprise 기본 주소, 기본 설정 키, 연결 제한시간은 Message 모듈 환경설정으로 관리함.
  • 요청별 config_key가 있으면 기본 설정 키보다 우선함.
  • 현재 Apprise 요청은 POST /notify/{config_key} 형식이며 JSON 본문 title, body, type을 전달함.
  • 메시지 유형은 info, success, warning, failure만 허용함.

4. 데이터 저장소와 스케줄러

  • SQLite 파일은 /sorc001/junkbox/db/message.sqlite3이며 Message 앱이 단일 writer임.
  • tb_message_log_n은 모든 발송 요청과 발송 시도를 저장함.
    • 출처, 제목, 본문, 메시지 유형, 설정 키, 요청 방식, 요청·예정·시도·완료 시각, 처리 상태, Apprise 응답·오류, 원본 메시지 식별자, 외부 요청 식별자, JSON 메타데이터를 보존함.
    • 정기 실행 이력은 recurrence_id + recurrence_scheduled_at 유니크 제약으로 같은 실행 시각의 중복 이력을 방지함.
  • tb_message_schedule_n은 단일 예약 정의와 연결된 발송 이력을 분리해 저장함.
  • tb_message_recurrence_n은 정기 일정 정의를 저장하며 실제 실행마다 새 tb_message_log_n 행을 생성함.
  • 메시지 상태는 PENDING, PROCESSING, SUCCESS, FAILED, CANCELED, EXPIRED를 사용함.
  • 요청 방식은 발송 진입 경로를 구분하는 이력 필드로 저장함.
  • 앱 lifespan에서 스키마를 보장하고 MessageScheduler를 시작함.
  • 스케줄러는 SQLite의 상태 전이와 선점 갱신으로 due 예약과 정기 실행을 처리하며, 처리 중 또는 완료 이력을 덮어쓰지 않음.
  • Apprise 네트워크 오류, 시간 초과, HTTP 오류, 비정상 응답은 메시지 이력의 실패 상태와 오류 내용으로 남김.

5. 웹 라우트

  • GET /messages: 즉시 발송 화면임.
  • GET /message-history: 발송 이력 화면임.
  • GET /message-schedules, GET /message-schedules/new: 예약 메시지 목록 및 등록 화면임.
  • GET /message-recurrences, GET /message-recurrences/new: 정기 메시지 목록 및 등록 화면임.
  • 모든 웹 라우트는 같은 Message 앱 셸을 반환하며 실제 본문은 Message React Router가 선택함.
  • 앱 셸 메뉴는 즉시 발송, 발송 이력, 예약 메시지, 정기 메시지로 구성함.

6. HTTP API

  • 모든 업무 API의 접두사는 /api/message임.
  • POST /messages: 즉시 메시지 발송 요청을 저장하고 Apprise로 전달함.
  • GET /messages: 페이지, 크기, 출처, 상태, 메시지 유형, 요청 방식, 검색어 기준 이력을 조회함.
  • GET /messages/{message_id}: 메시지 상세와 발송 결과를 조회함.
  • POST /messages/{message_id}/resend: 원본 이력을 보존한 새 발송 이력을 생성해 재발송함.
  • POST /schedules, GET /schedules, PUT /schedules/{schedule_id}, DELETE /schedules/{schedule_id}: 예약 메시지를 관리함.
  • POST /recurrences, GET /recurrences, PUT /recurrences/{recurrence_id}, POST /recurrences/{recurrence_id}/active, DELETE /recurrences/{recurrence_id}: 정기 메시지를 관리함.
  • 정기 메시지 반복 유형은 DAILY, WEEKLY, MONTHLY, CRON임.
  • CRON 반복 설정은 저장 전에 유효성을 검증함.

7. 인증과 입력 경계

  • 현재 Message 웹 라우트와 발송 API는 자체 JWT 인증·allowed_modules 권한 검증을 적용하지 않음.
  • 외부 발송 API에는 현재 별도 인증 헤더를 요구하지 않음.
  • 인증 추가 시 웹 관리자와 외부 발송 API의 의존성을 분리하고 shared-core JWT/Cookie/Header 계약 및 Hub 권한 구조를 사용함.
  • 요청 모델은 출처, 제목, 본문, 설정 키, 외부 요청 식별자, 메타데이터의 길이와 메시지 유형을 검증함.
  • Apprise 주소와 설정 키는 API 응답이나 화면에 노출하지 않음.

8. 공통 UI 및 문구 규칙

  • 앱 셸, 브랜드 헤더, 모바일 메뉴, 드로어, 카드, 입력창, 바텀 액션바, 바텀시트는 shared-ui 자산을 사용함.
  • 화면 폰트는 PretendardVariable.woff2를 공급하는 shared-ui 중앙 폰트 선언만 사용함.
  • 일반 UI 문구와 사용자 메시지는 DB 메시지 마스터로 관리하지 않고 소스의 한국어 문구로 작성함.
  • 문장형 사용자 노출 메시지는 하십시오체와 마침표를 사용함.
  • 공통코드나 메타의 데이터값은 기존 Hub 마스터데이터 계약을 사용하며 화면 문구 목적으로 신규 키를 만들지 않음.