GBT
한국외국어대학교Global Business & Technology
GenAI 특강 · 8-K 실시간 모니터링
목차 강의 홈 ↗
7H · 온라인 서비스 환경 구축

8-K 긴급 공시
실시간 모니터링

07_secrag(SEC 공시 RAG)의 심화편이다. 이 실습이 끝나면 로컬 PC를 꺼도 24시간 도는 모니터링 시스템이 생긴다 — HuggingFace Space가 10분마다 SEC RSS를 폴링해 새 8-K를 감지하고, Supabase에 영구 저장하고, LLM으로 자동 분석한 뒤 텔레그램으로 알림까지 보낸다.

HuggingFace SpaceSupabase PostgreSQLAPSchedulerGradio 대시보드텔레그램 봇
0
전체 구조 · 8-K · 준비

로컬 스크립트를 온라인 서비스로 바꾼다

지금까지의 실습은 내 PC에서 실행하는 순간에만 동작했다. 이번에는 클라우드에 상주하며 스스로 도는 시스템을 만든다.

아키텍처

전체 구조: SEC RSS → HF Space → Supabase → 대시보드

파이프라인의 몸통은 HuggingFace Space다. Space 안에서 스케줄러가 10분마다 SEC EDGAR RSS를 확인하고, 새 8-K를 감지하면 파싱해서 Supabase에 저장한다. Gradio 대시보드는 그 데이터를 실시간으로 보여준다.

SEC EDGAR RSS / API (공개 피드) 10분마다 폴링 HuggingFace Space 24시간 상시 실행 백그라운드 스케줄러 (APScheduler) 새 8-K 감지 → 내용 파싱 Supabase 저장 Supabase PostgreSQL filings 테이블 Gradio 모니터링 대시보드 실시간 감지 현황 · 최근 8-K 목록 클릭 → RAG 즉시 분석
그림 1. 전체 데이터 흐름. SEC EDGAR의 공개 RSS를 HuggingFace Space가 10분마다 폴링하고, 감지·파싱·저장은 Space 안의 스케줄러가 처리한다. Supabase의 filings 테이블(날짜, 제목, 내용, URL, 분석결과)이 영구 저장소이자 대시보드의 데이터 소스다.
HuggingFace SpaceGradio 앱을 무료로 24시간 호스팅. 로컬 PC와 독립적으로 상시 실행된다.
SupabasePostgreSQL을 무료로 제공. filings 테이블에 공시가 영구 저장된다.
SEC EDGAR미국 증권거래위원회의 공시 시스템. RSS 피드는 별도 인증 없이 공개.
배경 지식

8-K란 무엇인가

8-K는 미국 상장사가 중요한 사건이 발생했을 때 4영업일 내에 제출해야 하는 긴급 공시다. 분기마다 나오는 정기 보고서(10-Q, 10-K)와 달리, 시장을 움직일 만한 일이 생기면 즉시 나온다.

NVIDIA 기준으로 실적 발표, 임원 변경, 대규모 계약, 주식 환매 같은 사건이 8-K로 공시된다. 그래서 8-K를 실시간으로 감지하는 것은 투자 정보 시스템의 기본기다 — 07_secrag에서 만든 RAG 도구가 과거 공시를 "검색"했다면, 이번 시스템은 새 공시를 "감시"한다.

시작 전 준비

계정 두 개, 패키지 설치, 테이블 하나

준비물은 세 가지다. HuggingFace 계정(Space 배포용), Supabase 계정(DB용, 무료 플랜으로 충분), 그리고 로컬 개발용 패키지.

pip install gradio apscheduler supabase requests beautifulsoup4 -q

Supabase 테이블 생성

Supabase 프로젝트를 만든 뒤 SQL Editor에서 아래를 실행해 filings 테이블을 만든다.

create table filings (
  id           bigserial primary key,
  ticker       text default 'NVDA',
  filing_type  text,
  filed_at     date,
  title        text,
  content      text,
  sec_url      text unique,
  analysis     text,
  created_at   timestamptz default now()
);

sec_url에 걸린 unique 제약이 이 시스템의 중복 방지 장치다. 같은 공시를 다시 저장하려 하면 DB가 거부하므로, 폴링을 아무리 반복해도 데이터가 두 번 쌓이지 않는다.

확인할 값

  • Project URL — 설정 → API에서 확인
  • anon key — 설정 → API에서 확인

이 두 값은 Step 1의 코드와 Step 3의 Space Secrets에서 사용한다.

1
Step 1 · monitor_core.py

8-K 감지 & Supabase 저장

RSS를 파싱해 새 공시를 찾고 DB에 넣는 핵심 모듈을 만든다. 이 함수 하나가 시스템 전체의 심장이 된다.

🔵 Step 1

check_and_store() — 감지에서 저장까지 한 함수로

SEC EDGAR는 회사별 공시를 RSS(atom) 피드로 공개한다. 새 공시가 나오면 피드에 항목이 추가되므로, 주기적으로 확인해서 새 항목만 Supabase에 저장하면 된다. 중복은 sec_url unique 제약이 자동으로 막아 준다.

NVIDIA 8-K 전용 RSS 주소는 다음과 같다 (CIK 0001045810이 NVIDIA다).

https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=0001045810&type=8-K&dateb=&owner=include&count=10&output=atom
SEC EDGAR RSS 피드로 NVIDIA 8-K 공시를 감지해 Supabase에 저장하는 모듈을 만들어줘.
- RSS URL: (위 atom URL)
- requests + xml.etree.ElementTree로 RSS 파싱 (beautifulsoup4 금지)
- 각 항목에서 추출: title, filed_at, sec_url, 본문 텍스트(링크 따라가서 파싱)
- Supabase 저장: SUPABASE_URL/KEY, 테이블 filings, sec_url 중복 시 skip (upsert)
- 함수 check_and_store() 하나로 캡슐화
- 실행 시 "신규 X건 저장, Y건 중복 스킵" 출력
파일명: monitor_core.py

확인 포인트

  • monitor_core.py를 실행하면 "신규 X건 저장, Y건 중복 스킵"이 출력된다
  • Supabase Table Editor → filings 테이블에 행이 쌓여 있다
  • 한 번 더 실행하면 전부 "중복 스킵"으로 처리된다 (unique 제약 동작 확인)
생각해보기

filings에 행이 쌓이는 것을 확인했다면 감지·저장 로직은 완성이다. 그런데 이 스크립트는 내가 실행하는 순간에만 동작한다. 새 공시가 새벽에 나오면? 수동 실행은 의미가 없다. 다음 단계에서 자동 주기 실행으로 넘어가는 이유다.

2
Step 2 · app.py

백그라운드 스케줄러 + Gradio 대시보드

APScheduler가 10분마다 check_and_store()를 자동 호출하고, Gradio 화면에서 감지 현황을 실시간으로 본다.

🟡 Step 2

앱이 떠 있는 동안, 10분마다 스스로 돈다

APScheduler의 BackgroundScheduler는 Gradio 앱이 실행 중인 동안 별도 스레드에서 지정한 주기로 함수를 호출한다. 앱을 띄워 두기만 하면 check_and_store()가 10분마다 자동으로 실행되는 구조다.

monitor_core.py를 import해서 Gradio 모니터링 대시보드를 만들어줘.
- APScheduler BackgroundScheduler로 10분마다 check_and_store() 실행
- UI: 상단 "마지막 체크: [시각]" + [지금 체크] 버튼 / 중간 filings 최근 20건 gr.Dataframe(날짜, 제목, 공시유형, URL) / 하단 행 선택 시 본문 gr.Textbox
- [지금 체크] 클릭 시 즉시 실행 후 테이블 갱신, 앱 시작 시 스케줄러 자동 시작
- SUPABASE_URL, SUPABASE_KEY는 환경변수(os.environ)에서 로드
파일명: app.py

확인 포인트

  • 앱 시작과 동시에 스케줄러가 자동으로 시작된다
  • [지금 체크] 버튼을 누르면 즉시 실행되고 테이블이 갱신된다
  • 최근 20건이 Dataframe에 표시되고, 행을 선택하면 본문이 보인다
생각해보기

Supabase URL과 Key를 코드에 직접 쓰지 않고 환경변수에서 읽게 한 이유가 있다. 다음 단계에서 이 코드를 HuggingFace에 그대로 업로드하는데, 코드에 키가 박혀 있으면 공개 저장소에 비밀값이 노출된다. 환경변수 방식이면 Space Secrets에 등록하는 것만으로 안전하게 배포된다.

3
Step 3 · 배포

HuggingFace Space 배포

로컬에서만 돌던 앱을 클라우드에 올린다. 이 단계가 끝나면 내 PC를 꺼도 시스템이 돈다.

🟢 Step 3

무료로 24시간 호스팅되는 Gradio 앱

HuggingFace Spaces는 Gradio 앱을 무료로 24시간 호스팅한다. 로컬 PC를 꺼도 Space 위의 앱과 스케줄러는 계속 실행된다. Supabase URL/Key는 코드가 아니라 Space Secrets에 등록해 노출을 막는다.

업로드할 파일 구성

my-8k-monitor/
├── app.py
├── monitor_core.py
└── requirements.txt   (gradio, apscheduler, supabase, requests, beautifulsoup4)

배포 절차

  1. HuggingFace에서 New Space 생성 (SDK: Gradio)
  2. Settings → Secrets에 SUPABASE_URL, SUPABASE_KEY 등록
  3. Files 탭에 위 3개 파일 업로드
  4. 자동 빌드가 끝나면 Space URL이 생성된다
주의 · 슬립 모드

무료 플랜의 Space는 일정 시간 사용(방문)이 없으면 슬립 모드로 들어가 스케줄러도 함께 멈춘다. 정기적으로 방문하거나, 끊김 없는 상시 실행이 필요하면 유료 플랜을 쓴다.

확인 포인트

  • Space URL로 접속하면 대시보드가 뜬다
  • 로컬 PC를 꺼도 Supabase에 데이터가 계속 쌓이면 성공
4
Step 4 · 자동 분석

신규 8-K 즉시 RAG 분석 연결

새 공시를 저장만 하지 않고, 감지 즉시 LLM이 분석해서 결과를 함께 저장한다. 대시보드에서 바로 확인한다.

🟣 Step 4

감지 → 자동 LLM 분석 → analysis 컬럼 저장

새 8-K가 감지되면 HF Inference API로 즉시 분석을 돌리고, 결과를 filings 테이블의 analysis 컬럼에 저장한다. 대시보드는 분석 완료 여부를 표시하고, 행을 선택하면 원문과 AI 분석을 나란히 보여준다.

07_secrag에서 만든 SEC RAG 도구의 벡터 DB는 히스토리 검색용이고, 신규 8-K 분석은 여기서 별도 처리한다는 점을 구분해 두자.

요청 1 — monitor_core.py 수정

check_and_store()에 자동 RAG 분석 기능을 추가해줘.
- 새 8-K 저장 직후 HF Inference API(Qwen/Qwen3-8B, HF_TOKEN 환경변수) 분석
- 분석 프롬프트: "다음 NVIDIA 8-K 공시를 분석하시오. 1. 공시 핵심 내용 (2~3줄) 2. 투자자 관점에서 중요한 이유 3. 긍정/부정/중립 중 시장 영향 예상. 한국어로 답변. [공시 내용]: {content}"
- 결과를 analysis 컬럼에 업데이트, 실패 시 "분석 실패" 저장 후 계속 진행

요청 2 — app.py 수정

대시보드에 분석 결과 표시 기능을 추가해줘.
- Dataframe에 analysis 컬럼 (있으면 ✅, 없으면 ⏳)
- 행 선택 시 왼쪽 8-K 원문 / 오른쪽 AI 분석(gr.Markdown)
- 분석 없는 항목 선택 시 [지금 분석] 버튼 → 즉시 분석

확인 포인트

  • 새 공시가 저장되면 analysis 컬럼에 분석 결과가 함께 채워진다
  • 대시보드 Dataframe에 분석 완료 ✅ / 대기 ⏳ 표시가 보인다
  • 행 선택 시 왼쪽 원문, 오른쪽 AI 분석이 나란히 표시된다
  • 분석이 없는 항목은 [지금 분석] 버튼으로 즉시 분석된다
생각해보기

분석 실패 시 예외를 던지지 않고 "분석 실패"를 저장한 뒤 계속 진행하게 한 이유를 생각해 보자. 이 시스템의 1순위 임무는 감지·저장이고, 분석은 부가 기능이다. LLM API가 잠시 죽었다고 모니터링 전체가 멈추면 안 된다 — 자동화 시스템 설계에서 "부가 기능의 실패가 핵심 기능을 막지 않게" 하는 것이 기본 원칙이다.

5
Step 5 · 알림

텔레그램 알림 연결

대시보드를 열어 보지 않아도 새 8-K가 나오면 폰으로 즉시 알림이 온다. 그룹 채팅에 연결하면 팀 공유도 된다.

🏆 Step 5

새 8-K 감지 → 텔레그램 즉시 발송

텔레그램 봇 API는 토큰과 chat_id만 있으면 HTTP POST 한 번으로 메시지를 보낼 수 있다. check_and_store()가 신규 공시를 저장한 직후 알림을 발송하게 연결한다.

발송할 메시지 구성: "📡 NVIDIA 새 8-K 공시 / 제목 / 날짜 / 분석(AI 요약 2~3줄) / 원문 URL"

봇 만들기 (1회)

@BotFather에서 /newbot → 봇 이름·계정명(…bot) 입력 → 토큰 발급 → 봇에게 /start를 보낸 뒤 https://api.telegram.org/bot[토큰]/getUpdates에서 message.chat.id를 확인한다. 그룹에 연결하려면 봇을 그룹에 초대한 뒤 같은 방법으로 확인하며, 그룹의 chat.id는 음수다. (막히면 아래 해설의 상세 가이드를 펼쳐서 따라 한다.)

monitor_core.py에 텔레그램 알림 기능을 추가해줘.
- 환경변수 TELEGRAM_TOKEN, TELEGRAM_CHAT_ID
- 함수 send_telegram(title, filed_at, analysis, sec_url)
- API: POST https://api.telegram.org/bot{token}/sendMessage (parse_mode: Markdown)
- 메시지: "📡 *NVIDIA 새 8-K 공시* / *제목:* / *날짜:* / *분석:* [앞 300자] / *원문:*"
- check_and_store()에서 신규 저장 후 호출, 발송 실패 시 print만 하고 계속, TOKEN 없으면 알림 없이 정상 동작

완성되면 Space의 Settings → Secrets에 TELEGRAM_TOKEN, TELEGRAM_CHAT_ID를 추가한다.

확인 포인트

  • 로컬 실행 → 봇 채팅방에 메시지가 수신된다
  • 신규 공시가 없어 테스트가 안 되면: Supabase에서 행 하나를 지우고 재실행 (신규로 재감지된다)
  • Space Secrets에 TELEGRAM_TOKEN, TELEGRAM_CHAT_ID가 등록되어 있다
부록 · 텔레그램 봇 등록 상세 가이드

1단계 — BotFather 찾기. 텔레그램에서 BotFather를 검색한다. 파란 체크 뱃지가 붙은 공식 계정인지 확인할 것 — 사칭 계정이 있으니 주의한다.

2단계 — 봇 생성과 토큰 발급. BotFather에게 /newbot을 보내고, 봇 이름(예: NVIDIA 공시 알림)과 계정명(예: nvda_filing_alert_bot)을 입력하면 토큰이 발급된다. 토큰은 비밀번호처럼 보관한다 — 코드에 적지 말고 Secrets/.env에만 둔다.

3단계 — 봇에게 /start. 방금 만든 봇과의 채팅방에서 /start를 보낸다. 이것이 chat 기록을 생성해 다음 단계에서 chat.id를 읽을 수 있게 한다.

4단계 — chat.id 확인. 브라우저에서 https://api.telegram.org/bot[토큰]/getUpdates를 열어 message.chat.id 값을 확인한다. result가 []로 비어 있다면 3단계의 /start를 보내지 않은 것이다.

5단계 — 연결 테스트. sendMessage URL로 테스트 메시지를 보내 봇 채팅방에 도착하는지 확인한다.

6단계 — Space Secrets 등록. TELEGRAM_TOKEN과 TELEGRAM_CHAT_ID를 Space Secrets에 등록하고 재배포한다.

그룹 채팅에 연결하려면. 그룹 생성 → 봇 초대 → 그룹에 메시지 전송 → getUpdates에서 음수 chat.id 확인 → 그 값을 그대로 TELEGRAM_CHAT_ID로 등록하면 된다.

6
완성 시스템 · 비용 · 확장

완성 시스템 정리

로컬 PC와 무관하게 24시간 도는 공시 모니터링 시스템이 완성됐다. 각 구성 요소의 역할과 비용, 다음 확장 방향을 정리한다.

시스템 요약

세 구성 요소의 역할

구성 요소역할
HuggingFace Space대시보드 24시간 호스팅 · 10분마다 SEC RSS 폴링 · 신규 8-K 자동 분석
Supabasefilings 테이블 영구 저장 · sec_url unique 중복 방지 · 대시보드 데이터 소스
SEC EDGAR공개 RSS 피드 제공 · 별도 인증 불필요

비용

항목비용비고
HF Spaces무료 (CPU)슬립 모드 있음 · 유료 $9/월이면 슬립 없음
Supabase무료500MB DB · 50만 API 호출 — 이 용도에 충분
HF Inference API무료 할당량초과 시 skip 처리로 시스템은 계속 동작

확장 아이디어

  • 다른 종목 모니터링 — ticker와 CIK만 바꾸면 어떤 미국 상장사든 같은 구조로 감시할 수 있다.
  • Slack·이메일 알림 — 텔레그램 자리에 webhook을 추가하면 채널을 늘릴 수 있다.
  • 감성 분석 차트 — 축적된 analysis의 긍정/부정/중립을 시계열 차트로 시각화한다.
  • 벡터 DB 추가 인덱싱 — 신규 8-K를 07_secrag의 기존 벡터 DB에 추가해 히스토리 검색까지 통합한다.
핵심 정리

하나. 로컬 스크립트와 온라인 서비스의 차이는 코드가 아니라 실행 환경이다. 같은 check_and_store()가 HF Space에 올라가는 순간 24시간 서비스가 된다.

둘. 자동화 시스템의 데이터 무결성은 코드가 아니라 DB 제약으로 지킨다. sec_url unique 하나가 모든 중복 문제를 해결했다.

셋. 비밀값(URL, Key, 토큰)은 코드가 아니라 환경변수·Secrets에 둔다. 부가 기능(분석·알림)의 실패는 핵심 기능(감지·저장)을 멈추지 않게 설계한다.

출처 원본 노션 실습 자료: 8-K 긴급 공시 실시간 모니터링 (HuggingFace + Supabase)

한국외국어대학교 Global Business & Technology · GenAI 특강 · [8H] Prompt, Context 기반 AI 도구 실무 활용 · 7H 온라인 서비스 환경 구축.
이 자료는 단일 HTML 파일로 배포되는 실습 가이드다. "AI에게 이렇게 요청" 블록의 프롬프트는 복사 버튼으로 그대로 복사해 사용한다.