Skip to content

[REFACTOR] URL 분석 공통 콘텐츠 탐지 정확도 개선#31

Merged
minsoo0506 merged 7 commits into
devfrom
refactor/#29-improve-accuracy
May 24, 2026
Merged

[REFACTOR] URL 분석 공통 콘텐츠 탐지 정확도 개선#31
minsoo0506 merged 7 commits into
devfrom
refactor/#29-improve-accuracy

Conversation

@minsoo0506

@minsoo0506 minsoo0506 commented May 22, 2026

Copy link
Copy Markdown
Contributor

요약

URL 콘텐츠 분석 정확도를 높이기 위해 공통 content_analyzer 계층을 보강했습니다.

기존에는 정적 HTML에서 title, password input, 이미지 alt, meta refresh, 외부 링크 비율 등을 중심으로 판단했습니다.
이번 변경에서는 이미 가져온 HTML에서 더 많은 고신호 정보를 추출하고, 정적 HTML만으로 부족한 SPA/동적 페이지는 조건부로 렌더링 분석까지 수행합니다.

주요 변경 내용은 다음과 같습니다.

  • HTML 정적 추출 피처 확장

    • 본문 주요 텍스트
    • form/input/label/placeholder/name/type 정보
    • 버튼, submit, CTA 문구
    • APK, IPA, EXE 등 위험 확장자 다운로드 링크
    • 주민등록번호, 휴대폰, 카드, 계좌, OTP, 인증번호 관련 입력 필드 후보
    • 지원금, 환급금, 택배, 부고, 청첩장, 과태료, 건강보험, 카카오톡 등 한국형 루어 키워드
    • 국민건강보험, 정부24, 국세청 등 공공기관 사칭 후보 키워드
  • 로컬 룰 점수화 보강

    • PII 수집형 폼 탐지
    • 주민등록번호/OTP 등 민감 식별 정보 입력 필드 탐지
    • 카드/CVC/계좌 등 금융정보 입력 필드 탐지
    • APK 등 위험 다운로드 유도 탐지
    • 공공기관 사칭 문구와 한국형 루어 문구 탐지
    • 단순 문구만으로 점수가 과하게 오르지 않도록 실제 입력 폼/다운로드 링크와 결합될 때 주로 가산
  • OpenAI 프롬프트 컨텍스트 개선

    • HTML 원문 대신 구조화된 고신호 요약을 전달
    • 도메인/리다이렉트/threat DB 선행 신호와 콘텐츠 피처를 함께 제공
    • OpenAI 호출 횟수는 기존처럼 기본 1회 유지
  • 조건부 렌더링 정밀 분석 추가

    • SPA shell 또는 정적 분석 점수가 애매한 경우에만 Playwright 렌더링 DOM을 추가 분석
    • 렌더링 후 실제 DOM에서 드러나는 폼, 버튼, 다운로드 링크, 민감 필드를 재추출
    • Playwright 미설치/실패 시 기존 정적 분석 결과로 degrade
    • 응답에 precision_analysis_used, precision_analysis_error, RENDERED_DOM_ANALYZED를 노출
  • 탐지 성능 평가 메트릭 추가

    • accuracy, precision, recall, F1, false positive rate 계산 유틸 추가
    • 이후 평가셋을 확장해 90% 목표를 수치로 검증할 수 있는 기반 마련

성능 저하를 줄이기 위해 렌더링 분석은 모든 URL에 적용하지 않고, 정적 분석만으로 부족하거나 의심 신호가 있는 경우에만 실행됩니다.
(실제 렌더링 분석을 사용하려면 배포 환경에서 Chromium 설치가 필요)

playwright install chromium

연관 이슈 및 Close 할 이슈

close #29

Pull Request 체크리스트

TODO

  • 최종 결과물을 확인했는가?
  • 의미 있는 커밋 메시지를 작성했는가?

테스트

  • ruff check ...
    • 통과
  • pytest tests/services/content_analyzer tests/services/test_pipeline.py tests/services/test_db_independent_pipeline.py tests/services/test_evaluation_metrics.py tests/
    api/test_stages.py -q
    • 180 passed

@minsoo0506 minsoo0506 changed the title [REFACTOR] RL 분석 공통 콘텐츠 탐지 정확도 개선 [REFACTOR] URL 분석 공통 콘텐츠 탐지 정확도 개선 May 23, 2026
@sunm2n sunm2n added the refactor 코드 리팩토링 label May 23, 2026
Comment thread pyproject.toml
"lxml>=5.3.0",
"cachetools>=5.5.0",
"openai>=1.60.0",
"playwright>=1.45.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

playwright가 필수 의존성으로 추가 문제

render.py에서는 ImportError를 잡아 graceful degradation하는데, 정작 설치를 강제하고 있는 것으로 보입니다.
Playwright는 Chromium 바이너리까지 포함하므로 이미지 크기가 수백 MB 늘어납니다.
optional-dependencies로 이동하는 게 어떨까 제안 드립니다.

  [project.optional-dependencies]
  render = ["playwright>=1.45.0"]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 확인했습니다! render.py가 Playwright 미설치 시 playwright_unavailable로 graceful degradation하도록 되어 있어서, playwright를 기본 dependencies에서 제거하고 [project.optional-dependencies].render로 이동했습니다.

렌더링 분석이 필요한 환경에서는 .[render]로 설치하는 방식으로 분리했습니다.

_MAX_CTA_TEXTS = 40
_MAX_DOWNLOAD_LINKS = 40
_RISKY_DOWNLOAD_EXTENSIONS: frozenset[str] = frozenset(
{".apk", ".ipa", ".exe", ".msi", ".dmg", ".scr", ".bat", ".cmd", ".js", ".vbs"}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.js 위험 확장자 오탐 문제

.js는 정상 웹사이트 모든 <script src="..."> 로드에서 나타난다고 합니다.
<a href="/bundle.js"> 형태로 링크된 경우 RISKY_DOWNLOAD_LINK 시그널이 발생합니다.
실제 위협 벡터인 APK/EXE/BAT류와 성격이 다르다고 합니다.
js를 목록에서 제거하거나, <a> 태그의 download 속성이 있는 경우에만 적용하는 조건을 추가하는 게 어떨까 합니다.
다만 저도 이 부분에 대해서는 잘 알지 못하기 때문에 리뷰가 타당한다고 생각하시면 반영하면 좋을 거 같습니다!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 맞습니다! 일반 .js 링크는 정상 사이트의 번들 파일에서도 흔하게 노출될 수 있어서 RISKY_DOWNLOAD_LINK 대상에서 제외했습니다.

대신 <a download href="...js">처럼 명시적인 다운로드 의도가 있는 .js 링크만 위험 다운로드 후보로 유지했고, 해당 케이스에 대한 테스트도 추가했습니다.

_render_semaphore: asyncio.Semaphore | None = None


def _get_render_semaphore() -> asyncio.Semaphore:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전역 세마포어가 이벤트 루프에 묶임 문제

asyncio.Semaphore는 생성 시점의 이벤트 루프에 묶입니다.
pytest-asyncio는 테스트마다 새 루프를 만들기 때문에 모듈 재로드 없이 두 번째 테스트부터 "Future
attached to a different loop" 오류가 발생할 수 있습니다.
asyncio.Semaphore를 anyio.Semaphore로 교체하거나,
함수 진입 시 루프를 비교해 무효 시 재생성하는 방어 로직을 넣으면 어떨까 제안 드립니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asyncio.Semaphore를 전역으로 재사용하지 않고, 현재 running loop를 저장한 뒤 루프가 바뀌면 semaphore를 재생성하도록 수정했습니다.

pytest처럼 테스트마다 이벤트 루프가 바뀌는 환경에서도 기존 loop에 묶인 semaphore를 재사용하지 않도록 회귀 테스트를 추가했습니다.

@sunm2n sunm2n left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다!

@minsoo0506 minsoo0506 merged commit 09bfe07 into dev May 24, 2026
@minsoo0506 minsoo0506 deleted the refactor/#29-improve-accuracy branch May 24, 2026 14:54
@minsoo0506 minsoo0506 restored the refactor/#29-improve-accuracy branch May 24, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REFACTOR] URL 분석 공통 콘텐츠 탐지 정확도 개선

2 participants