정부지원사업 공고 수집 데몬(gov-scraper) 추가

- government/ Node 데몬: Open API 우선 + HTML 보조 + 디스커버리 전략
- Strategy 패턴 소스 어댑터: KStartupApiSource(공공데이터 Open API), GenericHtmlSource(config 기반)
- sundol 3단계 폴백 크롤러(cheerio→Jina→Playwright CDP) Node 재구현, sundol-chrome(9222) 재사용
- Oracle thick 모드(Instant Client + sso 지갑) 접속, gov_source/gov_opportunity 적재(중복제거)
- K-Startup 29,017건 + 중기부(mss) 30건 적재 검증, PM2 gov-daemon 등록(60분 주기)
- 기업마당(bizinfo)은 자체 crtfcKey 발급 대기

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-10 04:36:50 +00:00
parent 5700449bfd
commit cbc5ba5663
23 changed files with 1639 additions and 0 deletions

43
government/src/config.js Normal file
View File

@@ -0,0 +1,43 @@
// 환경설정 로더. 프로젝트 루트(.env)를 읽어 데몬 전역 설정으로 노출한다.
import dotenv from 'dotenv';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, '..', '..'); // /home/opc/sundol
dotenv.config({ path: path.join(ROOT, '.env') });
function required(name) {
const v = process.env[name];
if (v === undefined || v === null || v === '') {
throw new Error(`필수 환경변수 누락: ${name}`);
}
return v;
}
export const config = {
root: ROOT,
oracle: {
user: required('ORACLE_USERNAME'),
password: required('ORACLE_PASSWORD'),
connectString: required('ORACLE_TNS_NAME'),
walletPath: required('ORACLE_WALLET_PATH'),
// thick 모드: Instant Client 라이브러리 + sso 지갑을 읽을 net 설정 디렉터리
icLibDir: process.env.ORACLE_IC_LIB_DIR || '/home/opc/oracle-ic/instantclient_23_26',
netConfigDir:
process.env.ORACLE_NET_CONFIG_DIR ||
path.join(ROOT, 'government', 'oracle-net'),
},
dataGoKr: {
apiKey: process.env.DATA_GO_KR_API_KEY || '',
},
bizinfo: {
crtfcKey: process.env.BIZINFO_CRTFC_KEY || '',
},
jina: {
apiKey: process.env.JINA_READER_API_KEY || '',
},
cdpUrl: process.env.GOV_CDP_URL || 'http://127.0.0.1:9222',
pollIntervalMinutes: Number(process.env.GOV_POLL_INTERVAL_MINUTES || 60),
};