문제
입찰 공고를 찾으려면 나라장터를 사람이 매일 반복해서 검색해야 했고, 놓치는 공고가 생겼다.
해결
조달청 공공데이터 API 8개 엔드포인트(입찰공고·사전규격·개찰·낙찰·계약)를 주기적으로 수집해 DB에 쌓고, 사업 분야 키워드로 자동 분류한 뒤 새 공고를 텔레그램으로 알린다.
주요 기능
- 대시보드: 통계 카드, 최근 공고
- 입찰공고 / 결과공고 / 사전규격: 카테고리 탭, 검색, 기간 필터, 상세와 첨부 규격서
- 사업분석: 공고와 낙찰·계약 정보를 연결해 낙찰업체와 점수, 실제 낙찰자를 추적
- 설정: 카테고리별 포함/제외 키워드, 자동 동기화 주기, 알림 봇, 동기화 진행 상황
설계 포인트
- 앱 내장 스케줄러: Next.js
instrumentation훅에서 cron을 띄운다. 매 분 DB의 동기화 설정을 읽고, 실행 중 플래그로 중복 실행을 막는다. - 멱등 동기화: 모든 수집은 upsert로 처리하고, 실행 결과는 동기화 로그에 남긴다. 몇 번을 다시 돌려도 데이터가 중복되지 않는다.
- API 클라이언트: 요청 간격 제한, 재시도, 전체 페이지 순회. 과거 수년치 데이터는 별도 스크립트로 일괄 적재했다.
- 키워드 분류기: 공백과 대소문자를 정규화한 뒤 포함/제외 목록으로 매칭한다. 키워드가 바뀌면 기존 데이터 전체를 다시 분류한다.
- 보안: API 경로는 내부망 IP 허용목록으로 제한한다. 정렬 컬럼은 화이트리스트로 받고, 페이지 범위에 상한을 둔다. 외부 호출 대상은 공공데이터 도메인으로 고정해 SSRF를 막는다.
스택
Next.js 16 (App Router) · React 19 · TypeScript · Tailwind CSS v4 · TanStack Query · Prisma · PostgreSQL · node-cron · nginx · systemd