Skip to content

Latest commit

 

History

History
125 lines (94 loc) · 4.96 KB

File metadata and controls

125 lines (94 loc) · 4.96 KB

AGENTS.md

프로젝트 개요

실시간 재난/안전 데이터 소스들을 주기적으로 수집하여, 공통 형태의 "이벤트"로 정형화해서 Postgres에 저장하고, HTTP API 및 SSE로 최신 이벤트 목록을 제공한다.

  • 단일 백엔드 앱이 모든 역할 수행(수집 잡 실행, API, SSE)
  • 백엔드 앱은 여러 인스턴스로 실행될 수 있음(Scale-out)

작업 흐름

코딩시 아래 단계를 충실히 따릅니다.

  1. 요청 사항 및 AGENTS.md, SPEC.md 검토
  2. 테스트를 포함하여 요청에 맞는 코드 작성/수정
  3. 타입/린트 오류 검사 및 수정 (npx tsc --noEmit, npm run lint:fix)
  4. 필요한 경우 AGENTS.md, SPEC.md 업데이트
  5. 상세한 결과 보고

범위

이번 단계에서 하는 것

  • 소스별 폴링(잡) 실행 및 이벤트 저장(append-only)
  • 이벤트 목록 조회 API
  • SSE 스트림(다중 인스턴스에서도 동작)
  • 소스별 장애가 전체를 멈추지 않게 실패 격리
  • 지오코딩/좌표 처리

이번 단계에서 하지 않는 것

  • 사건 병합/클러스터링(중복 통합)
  • 진행/종료 같은 상태 전이

핵심 원칙

  • DB(Postgres)가 단일 진실 공급원(SoT)
  • SSE는 실시간 UX용. 놓친 이벤트는 DB 기반 catch-up으로 커버
  • 소스 추가는 "파일 추가 + 등록" 정도로 끝나야 함
  • 소스별 구현은 클래스(또는 객체) 하나가 fetch+정형화를 함께 수행한다(collector/normalizer 분리 없음)

이벤트 모델

  • id: UUID v7
  • source: 숫자 enum (앱에서 관리; DB에는 enum 제약 없음)
  • kind: 숫자 enum (앱에서 관리; DB에는 enum 제약 없음)
  • title: 한 줄
  • body: 본문(선택)
  • fetched_at: timestamptz (필수)
  • 선택: occurred_at, region_text, geo(위도/경도), region_codes(10자리 행정구역 코드 배열), payload(jsonb)
  • level: 숫자 enum (필수)

다중 인스턴스 SSE

  • 이벤트 insert 성공 후 Redis Pub/Sub 채널로 eventId publish
  • 모든 인스턴스가 채널을 subscribe
  • 메시지를 받으면 DB에서 이벤트를 읽어와 그 인스턴스에 붙어있는 SSE 클라이언트에 전송
  • SSE 재연결 시 DB에서 누락분을 보내고 live로 전환

개발/실행

  • npm 사용
  • docker-compose로 Postgres + Redis 제공
  • DB 스키마는 마이그레이션 대신 init-sql.db(= init SQL 파일)에 최신 전체 스키마를 유지한다

Coding conventions

  • 보기 좋은 코드를 작성합니다.
  • Type Safe를 준수합니다. any 사용을 금지하며 꼭 필요하다면 unknown을 사용합니다. Zod 스키마를 적극 활용합니다.
  • Biome을 사용하여 코드 스타일을 강제합니다.
  • forEach 대신 for 문을 사용합니다.
  • then 대신 async/await를 사용합니다.
  • 주석은 남용하지 말고 코드만 봐서 이해하기 어려운 부분에만 한국어로 작성합니다.
  • Code smells를 피합니다. (예: 중복 코드, 긴 함수, 긴 매개변수 목록 등)
  • Kysely 쿼리는 raw SQL을 최소화하고, 가능한 Kysely 메서드를 사용합니다. 예: foo as a 대신 foo().as('a')
  • 타입에는 PascalCase, 변수/함수/메서드에는 camelCase, 상수에는 UPPER_SNAKE_CASE를 사용합니다.
  • enum 이름은 복수형으로 작성합니다.
  • Zod 스키마 변수는 schemaXXX 형태의 camelCase로 작성합니다.
  • logger를 사용하여 적절한 수준의 로그를 남깁니다. (debug/info/warn/error)
  • 필요한 경우가 아니라면 일반 함수는 function 키워드로 작성합니다. (화살표 함수는 주로 콜백용)
  • as unknown 같이 타입 안전성을 해치는 변환을 사용하지 않습니다.

Git commit style

  • 영어로 작성.
  • Conventional Commits 규칙을 따릅니다.
  • 서로 다른 변경을 한 커밋에 묶지 않습니다.
  • 버그 수정은 fix를 사용합니다.
  • refactor는 큰 동작 변화 없는 코드 구조 개선에 사용합니다.

Tech stack

  • Runtime/Language: Node.js, TypeScript
  • Web Framework: Hono
  • ORM/Database: Kysely, PostgreSQL
  • Queue/Worker: BullMQ
  • Pub/Sub: Redis
  • DI/Architecture: Inversify
  • Environment Variables: dotenv
  • API Documentation: Swagger UI, zod-openapi
  • Logging: pino
  • Testing: Vitest
  • Build/Dev Tools: tsup, tsx, Vite
  • Code Quality/Formatter: Biome, lint-staged, Husky

Architecture

This project follows a layered architecture at both the top-level and within each module:

  • Top-level layers:

    • core: Core logic and shared dependencies
    • infra: External infrastructure (e.g., database)
    • view: HTTP API routes and middleware
    • modules: Feature modules, each with its own layers
  • Module structure:

    • app: Business logic such as services
    • infra: External infrastructure (e.g., DB repositories)
    • view: HTTP API route definitions
    • domain: Shared dependencies, DTOs, entities, interfaces, etc. (referenced by other modules)

MCP and Skills

  • use context7 for the latest information