Files
AI/ontology_platform/docs/semantic_page_classification_codex_spec.md
2026-05-22 20:16:28 +09:00

38 KiB

Semantic Page Classification Layer 설계 및 구현 지시서

0. 문서 목적

본 문서는 온톨로지 플랫폼의 page_classifier.py를 단순 URL/텍스트 기반 페이지 분류기에서 범용 Semantic Page Understanding Layer로 확장하기 위한 작업 지시서이다.

현재 시스템은 다음과 같은 제한적인 page type만 다룬다.

ProductPage
CategoryPage
SearchPage
BoardPage
NoticePage
BrandStoryPage
PromotionPage
UnknownPage

이 구조는 쇼핑몰 일부 페이지를 분류하는 데는 사용할 수 있으나, 범용 온톨로지 구축 플랫폼에는 부족하다.

범용 플랫폼은 인터넷에 존재하는 다양한 페이지를 다음 관점으로 분류할 수 있어야 한다.

Page Domain
Page Archetype
Semantic Page Type
Main Entity Type
Action Intent
Graph Role
Analyze Strategy
LLM Policy
Confidence
Evidence

즉, 목표는 단순히 ProductPage 같은 enum 하나를 맞히는 것이 아니라, 페이지의 의미적 역할을 여러 축으로 해석하고, 온톨로지 그래프 구축에 필요한 분석 전략까지 결정하는 것이다.


1. 현재 구조의 문제점

1.1 Page Type이 너무 적다

현재 분류 항목은 대부분 commerce 또는 게시판 중심이다.

ProductPage
CategoryPage
SearchPage
BoardPage
BrandStoryPage

하지만 인터넷에는 다음과 같은 페이지가 존재한다.

ArticlePage
NewsPage
BlogPostPage
FAQPage
QAPage
WikiPage
DocumentationPage
JobPostingPage
CoursePage
VideoPage
ProfilePage
LocalBusinessPage
RealEstateListingPage
PricingPage
CheckoutPage
LoginPage
TermsPage
PrivacyPolicyPage
APIReferencePage
DatasetPage
ResearchPaperPage

현 구조에서는 이들을 대부분 UnknownPage 또는 부정확한 기존 타입으로 분류하게 된다.


1.2 URL 휴리스틱 의존도가 높다

현재 방식은 대체로 다음과 같은 구조다.

if "/product/" in url:
    return "ProductPage"

if "/board/" in url:
    return "BoardPage"

이 방식은 다음 환경에서 쉽게 깨진다.

SPA
Headless Commerce
Dynamic Route
Query 기반 페이지
다국어 URL
짧은 URL
해시 라우팅
CMS 기반 자동 생성 페이지
AI 생성 페이지

예:

/p/12345
/x/abc
/node/987
/view?id=123
/ko/contents/123

이 URL만 보고는 페이지 의미를 알 수 없다.


1.3 CategoryPage, SearchPage, BoardPage를 너무 쉽게 skip한다

현재 구조는 보통 다음 흐름이다.

classify_page()
 -> should_analyze_page()
 -> analyze_page_types에 없으면 Extractor 실행 안 함

이 때문에 CategoryPage, SearchPage, BoardPage는 기본적으로 분석 대상에서 빠질 가능성이 높다.

그러나 범용 온톨로지 플랫폼에서는 이 페이지들이 중요하다.

CategoryPage       -> 카테고리 계층, 상품 목록, taxonomy 관계
SearchPage         -> 검색 의도, 결과 후보, query-result 관계
BoardPage          -> 게시글 목록, 질문/답변/토론 구조
ListingPage        -> entity collection, relation hub
ArchivePage        -> 시간 축 기반 콘텐츠 구조
TagPage            -> topic-entity 관계

따라서 “분석 여부”는 단순 boolean이 아니라, 페이지 타입별 분석 전략으로 분리해야 한다.


1.4 UnknownPage를 버리면 안 된다

현재는 분류 실패 시 UnknownPage로 두고 사실상 분석에서 제외될 가능성이 크다.

하지만 범용 플랫폼에서 UnknownPage는 새로운 페이지 패턴을 발견하는 출발점이다.

예:

UnknownPage Cluster A:
- 향수 노트 비교표가 있음
- 여러 상품을 향 계열별로 비교
- 일반 ProductPage도 CategoryPage도 아님

새 후보:
PerfumeNoteComparisonPage

따라서 Unknown은 폐기 대상이 아니라, clustering 및 taxonomy 확장 후보로 저장해야 한다.


2. 목표 아키텍처

기존 구조:

URL / title / text / html
 -> page_classifier.py
 -> page_type
 -> should_analyze_page()

개선 구조:

Raw Page Snapshot
 -> Signal Extraction
 -> Evidence Scoring
 -> Domain Classification
 -> Archetype Classification
 -> Entity Type Classification
 -> Action Intent Classification
 -> Graph Role Assignment
 -> Semantic Page Type Decision
 -> Analyze Strategy Decision
 -> LLM Policy Decision
 -> Unknown Pattern Storage / Clustering

3. 핵심 개념

3.1 Page Domain

페이지가 속한 큰 의미 영역이다.

Commerce
Editorial
Community
Knowledge
Corporate
Local
Education
Jobs
Media
Software
Finance
Government
Healthcare
Transaction
System
Unknown

3.2 Page Archetype

페이지의 구조적 역할이다.

Home
Landing
Detail
Listing
Collection
SearchResult
Profile
Article
Thread
Form
Transaction
Dashboard
Document
Media
Error
SystemResource
Unknown

3.3 Semantic Page Type

구체적인 페이지 타입이다.

예:

ProductDetailPage
CategoryListingPage
ArticlePage
ForumThreadPage
FAQPage
JobPostingPage
LocalBusinessPage
CheckoutPage
LoginPage
DocumentationPage

3.4 Main Entity Type

페이지가 중심으로 삼는 엔티티이다.

Product
Service
Article
NewsArticle
Person
Organization
Place
Event
JobPosting
Course
Question
Answer
Review
Dataset
SoftwareApplication
MediaObject
Recipe
RealEstateProperty
MedicalCondition
LegalDocument
FinancialProduct
UnknownEntity

3.5 Action Intent

페이지가 사용자를 유도하는 행동이다.

Read
Buy
Subscribe
Reserve
Book
Apply
Download
Watch
Listen
Search
Compare
Filter
Ask
Answer
Comment
Review
Login
Register
Pay
Contact
Navigate
Learn
Verify
Configure
Manage

3.6 Graph Role

온톨로지 그래프 안에서 이 페이지가 수행하는 역할이다.

EntityAnchor
RelationHub
NavigationHub
CollectionHub
SearchHub
TransactionOnly
PolicySource
ClaimSource
ProfileAnchor
MediaAnchor
ReferenceSource
SystemResource
NoisePage
UnknownPattern

3.7 Analyze Strategy

페이지를 어떻게 분석할지 결정하는 전략이다.

AnalyzeFull
AnalyzeStructureOnly
AnalyzeEntityOnly
AnalyzeRelationsOnly
AnalyzeMetadataOnly
AnalyzeDocumentOnly
AnalyzeDiscoveryOnly
SkipProtected
SkipNoise

3.8 LLM Policy

LLM 사용 여부 및 사용 범위다.

LLMFull
LLMLight
LLMForAmbiguityOnly
RuleOnly
NoLLM
Skip

4. Page Taxonomy v1

아래 taxonomy는 초기 버전이다. 구현 시 enum 또는 문자열 상수로 관리한다.


4.1 Site / Navigation 계열

HomePage
LandingPage
PortalPage
SectionHomePage
CategoryPage
SubcategoryPage
TagPage
TopicPage
CollectionPage
ArchivePage
SitemapPage
DirectoryPage
IndexPage
SearchPage
SearchResultsPage
FilteredResultsPage
PaginationPage
LocaleSelectorPage
LanguageRedirectPage
RedirectPage
NotFoundPage
ErrorPage
MaintenancePage
ComingSoonPage
RobotsBlockedPage

주요 신호

many internal links
breadcrumb
category tree
pagination
tag links
archive dates
search form
sitemap XML or sitemap-like links
locale links
error status text

온톨로지 역할

사이트 구조 파악
카테고리 계층 파악
내부 링크 그래프 구축
탐색 우선순위 결정

4.2 Commerce / Marketplace 계열

ProductDetailPage
ProductVariantPage
ProductBundlePage
ProductComparisonPage
ProductReviewPage
ProductQnAPage
ProductManualPage
ProductSpecPage
CategoryListingPage
ProductListingPage
BrandCatalogPage
SellerStorePage
MarketplaceListingPage
SearchProductResultsPage
DealPage
SalePage
CouponPage
PromotionPage
CampaignLandingPage
SubscriptionPlanPage
PricingPage
CartPage
CheckoutPage
PaymentPage
OrderPage
OrderConfirmationPage
OrderTrackingPage
WishlistPage
GiftCardPage
StoreLocatorPage
InventoryAvailabilityPage
AuctionPage
RentalProductPage
BookingProductPage
ServiceProductPage

주요 신호

schema.org Product
schema.org Offer
schema.org AggregateRating
price
currency
availability
add to cart
buy now
variant selector
quantity selector
SKU
brand
product image gallery
reviews
rating
shipping
return policy
repeated product cards
filters
sort control
pagination

온톨로지 역할

Product 엔티티 생성
Brand 관계 생성
Category 관계 생성
Offer / Price / Availability 추출
Review / Rating 관계 추출
RelatedProduct 관계 추출

4.3 Editorial / Article / Publishing 계열

ArticlePage
NewsArticlePage
BlogPostPage
OpinionPage
EditorialPage
InterviewPage
ReportPage
ColumnPage
PressArticlePage
MagazinePage
GuidePage
TutorialPage
HowToPage
RecipePage
CaseStudyPage
WhitePaperPage
ResearchSummaryPage
StoryPage
ChapterPage
SeriesPage
AuthorArticleListPage
PaywalledArticlePage
SponsoredContentPage

주요 신호

schema.org Article
schema.org NewsArticle
schema.org BlogPosting
headline
author
publisher
datePublished
dateModified
articleBody
byline
section
tags
hero image
related articles
paywall marker

온톨로지 역할

Article / Topic / Author / Publisher 엔티티 생성
about 관계 생성
citation / source 관계 생성
temporal coverage 추출
claim 후보 추출

4.4 Community / UGC 계열

ForumHomePage
ForumBoardPage
ForumThreadPage
DiscussionPage
CommentThreadPage
QAPage
FAQPage
ReviewPage
UserReviewPage
CommunityPostPage
SocialPostPage
TimelinePage
FeedPage
UserProfilePage
CreatorProfilePage
GroupPage
CommunityPage
PollPage
PetitionPage
RankingPage
LeaderboardPage
ReputationPage
BadgePage

주요 신호

question
answer
accepted answer
comments
reply
thread
votes
likes
author profile
user avatar
posted date
edited date
review rating
FAQ accordion
Q&A structured data

온톨로지 역할

Question / Answer 엔티티 생성
User / Author 관계 생성
Thread 관계 생성
Claim / Opinion 분리
Reputation / Vote / AcceptedAnswer 추출

4.5 Knowledge / Reference / Documentation 계열

WikiPage
EncyclopediaPage
GlossaryPage
DefinitionPage
ReferencePage
DocumentationPage
DeveloperDocsPage
APIDocumentationPage
APIReferencePage
SDKDocumentationPage
ManualPage
SpecificationPage
StandardPage
ProtocolPage
ChangelogPage
ReleaseNotesPage
ErrorCodePage
TroubleshootingPage
KnowledgeBaseArticlePage
DatasetPage
DataCatalogPage
ResearchPaperPage
PatentPage
CitationPage
BibliographyPage

주요 신호

definition
table of contents
code block
API method
parameter table
version
endpoint
changelog
release notes
specification
standard
citation
references
dataset metadata

온톨로지 역할

Concept / Term / Definition 추출
API / Method / Parameter 관계 추출
Version 관계 추출
Dataset metadata 추출
Reference graph 생성

4.6 Corporate / Organization 계열

AboutPage
CompanyPage
BrandStoryPage
MissionPage
VisionPage
HistoryPage
TeamPage
FounderPage
LeadershipPage
ContactPage
LocationPage
BranchPage
InvestorRelationsPage
IRPage
FinancialReportPage
PressReleasePage
MediaKitPage
PartnershipPage
FranchisePage
CareersHomePage
JobPostingPage
RecruitPage
CulturePage
LegalPage
TermsPage
PrivacyPolicyPage
CookiePolicyPage
AccessibilityPage
CompliancePage
SecurityPage
TrustCenterPage

주요 신호

about us
company
mission
vision
history
team
founder
leadership
contact
address
investor relations
press release
careers
privacy policy
terms of service
cookie policy
security
compliance

온톨로지 역할

Organization 엔티티 생성
Founder / Location / Contact 관계 생성
Policy 문서 분류
법적/계약적 문장 추출
채용 정보 추출

4.7 Local / Place / Travel / Real Estate 계열

PlaceDetailPage
LocalBusinessPage
RestaurantPage
MenuPage
HotelPage
RoomPage
VacationRentalPage
TravelDestinationPage
AttractionPage
ItineraryPage
MapPage
MapSearchResultsPage
RealEstateListingPage
PropertyDetailPage
PropertySearchResultsPage
AgentProfilePage
OpenHousePage
ReservationPage
BookingPage
AvailabilityCalendarPage
TransportRoutePage
FlightPage
TrainPage
BusRoutePage

주요 신호

address
geo coordinates
map
opening hours
menu
reservation
booking
room availability
travel dates
property price
bedrooms
bathrooms
area
agent
route
schedule

온톨로지 역할

Place 엔티티 생성
Address / Geo / OpeningHours 추출
Reservation 가능성 판단
Nearby 관계 생성
Availability 추출

4.8 Education / Learning 계열

CourseDetailPage
CourseListPage
CurriculumPage
LessonPage
LecturePage
TutorialPage
AssignmentPage
QuizPage
ExamPage
FlashcardPage
EducationQAPage
MathSolverPage
SchoolPage
UniversityPage
ProgramPage
DegreePage
CertificationPage
InstructorProfilePage
LearningPathPage

주요 신호

course
lesson
curriculum
instructor
learning objective
assignment
quiz
exam
certificate
degree
program
tuition
syllabus

온톨로지 역할

Course / Lesson / Instructor 엔티티 생성
Prerequisite 관계 생성
LearningObjective 추출
Question / Answer / Solution 구조화

4.9 Jobs / Career 계열

JobPostingPage
JobSearchResultsPage
CompanyJobsPage
CareerCategoryPage
ApplicationFormPage
RecruitmentLandingPage
EmployerProfilePage
EmployerReviewPage
SalaryPage
InterviewReviewPage
BenefitsPage
InternshipPage
FreelanceGigPage

주요 신호

job title
employment type
salary
location
remote
apply
requirements
responsibilities
benefits
company
recruiter
deadline

온톨로지 역할

Job 엔티티 생성
Employer 관계 생성
Location / Salary / EmploymentType 추출
Skill requirement 추출

4.10 Media / Entertainment 계열

VideoPage
VideoWatchPage
LiveStreamPage
PodcastPage
EpisodePage
MusicTrackPage
AlbumPage
ArtistPage
MoviePage
TVSeriesPage
TVEpisodePage
GameDetailPage
GameGuidePage
ImagePage
ImageGalleryPage
PhotoStoryPage
MediaGalleryPage
DownloadMediaPage
StreamingChannelPage

주요 신호

video player
audio player
duration
episode
season
album
artist
track
movie
trailer
live
stream
gallery
image grid
download

온톨로지 역할

MediaObject 엔티티 생성
Creator / Performer / Publisher 관계 생성
Duration / Episode / Series 관계 추출
License / UsageInfo 추출

4.11 Software / SaaS / App 계열

SoftwareProductPage
SaaSProductPage
FeaturePage
PricingPage
IntegrationPage
PluginPage
ExtensionPage
AppStoreListingPage
PackagePage
RepositoryPage
ReleasePage
ChangelogPage
IssuePage
PullRequestPage
DocumentationPage
APIReferencePage
StatusPage
DashboardPage
SettingsPage
AdminPage
LoginPage
SignupPage
OnboardingPage
BillingPage
UsageReportPage

주요 신호

software
app
SaaS
feature
pricing
integration
plugin
extension
repository
release
changelog
issue
pull request
status
dashboard
settings
billing
API
SDK

온톨로지 역할

Software / Version / Feature 엔티티 생성
Dependency 관계 생성
Release 관계 생성
Issue / PR / Commit 관계 추출

BankProductPage
LoanPage
CreditCardPage
InsuranceProductPage
InvestmentProductPage
StockQuotePage
CryptoAssetPage
FinancialReportPage
TaxInfoPage
GovernmentServicePage
PublicNoticePage
RegulationPage
LawPage
CourtCasePage
LegalArticlePage
PolicyPage
FormPage
ApplicationPage
PermitPage
LicensePage
PublicDataPage
ProcurementPage
TenderPage

주요 신호

interest rate
APR
loan
credit card
insurance
investment
stock quote
financial statement
tax
government
regulation
law
court
policy
permit
license
tender
procurement

온톨로지 역할

Regulation / Policy / Law 엔티티 생성
Obligation / Prohibition / Permission 추출
Institution 관계 생성
Form requirement 추출

4.13 Healthcare / Medical 계열

MedicalArticlePage
ConditionPage
SymptomPage
TreatmentPage
DrugPage
SupplementPage
DoctorProfilePage
HospitalPage
ClinicPage
AppointmentPage
InsuranceCoveragePage
ClinicalTrialPage
MedicalFAQPage
HealthCalculatorPage
EmergencyInfoPage

주요 신호

condition
symptom
treatment
drug
dosage
side effect
doctor
hospital
clinic
appointment
clinical trial
insurance coverage
emergency

온톨로지 역할

Condition / Treatment / Drug 엔티티 생성
Symptom 관계 생성
Medical claim 추출
Source reliability 분리

4.14 Transaction / Account / Protected 계열

LoginPage
SignupPage
PasswordResetPage
AccountPage
ProfileSettingsPage
NotificationPage
MessageInboxPage
CartPage
CheckoutPage
PaymentPage
SubscriptionManagementPage
BillingPage
InvoicePage
OrderHistoryPage
UploadPage
DownloadPage
FormPage
SurveyPage
ConsentPage
AgeGatePage
CaptchaPage
PaywallPage
AccessDeniedPage
SessionExpiredPage

주요 신호

login form
password field
signup
reset password
account settings
payment fields
checkout
billing
invoice
consent
captcha
age gate
access denied
session expired

온톨로지 역할

대부분 분석 제외
개인정보 보호
크롤링 중단 또는 제한
거래 흐름만 메타 수준으로 기록

4.15 System / Technical / Machine-readable 계열

RSSFeedPage
AtomFeedPage
XMLSitemapPage
RobotsTxtPage
ManifestPage
OpenSearchDescriptionPage
JSONEndpointPage
APIEndpointPage
GraphQLEndpointPage
WebhookEndpointPage
FileDownloadPage
PDFDocumentPage
CSVDocumentPage
XMLDocumentPage
ImageAssetPage
VideoAssetPage
FontAssetPage
ScriptAssetPage
StylesheetAssetPage

주요 신호

content-type
xml
json
rss
atom
sitemap
robots.txt
manifest
API response
file extension
download headers

온톨로지 역할

크롤링 정책 파악
사이트 구조 파악
데이터 소스 발견
문서형 리소스 별도 파서로 전달

5. Signal Extraction 설계

page_classifier.py가 직접 모든 것을 처리하지 말고, signal extractor를 분리한다.

권장 파일 구조:

ontology_platform/
  classifier/
    page_classifier.py
    page_type_taxonomy.py
    page_signals.py
    page_signal_extractor.py
    page_type_scorer.py
    page_analysis_policy.py
    adaptive_page_classifier.py

기존 프로젝트 구조에 맞춰 경로는 조정해도 된다.


5.1 Raw Page Snapshot

분류 함수 입력은 다음 정보를 받을 수 있어야 한다.

@dataclass
class RawPageSnapshot:
    url: str
    final_url: str | None
    status_code: int | None
    content_type: str | None

    title: str | None
    text: str | None
    html: str | None
    rendered_html: str | None

    metadata: dict
    open_graph: dict
    twitter_card: dict
    json_ld: list[dict]
    microdata: list[dict]
    rdfa: list[dict]

    headings: list[str]
    links: list[dict]
    images: list[dict]
    forms: list[dict]
    buttons: list[str]
    inputs: list[dict]
    tables: list[dict]

    breadcrumbs: list[str]
    source_zones: list[str]
    screenshot_path: str | None

초기 구현에서는 모든 필드가 없어도 된다.
없는 값은 None 또는 빈 리스트로 처리한다.


5.2 Page Signals

추출 결과는 다음 형태로 관리한다.

@dataclass
class PageSignals:
    # structured data
    schema_types: set[str]
    og_type: str | None
    twitter_card_type: str | None

    # commerce
    has_price: bool
    has_currency: bool
    has_cart_button: bool
    has_buy_button: bool
    has_variant_selector: bool
    has_sku: bool
    has_rating: bool
    has_review_section: bool
    has_product_gallery: bool

    # listing
    has_repeated_cards: bool
    repeated_card_count: int
    has_filter_panel: bool
    has_sort_control: bool
    has_pagination: bool

    # editorial
    has_author: bool
    has_published_date: bool
    has_modified_date: bool
    has_article_body: bool
    has_tags: bool

    # community
    has_question: bool
    has_answer: bool
    has_comments: bool
    has_votes: bool
    has_thread_structure: bool
    has_faq_structure: bool

    # knowledge/docs
    has_code_blocks: bool
    has_toc: bool
    has_api_endpoint: bool
    has_parameter_table: bool
    has_version_info: bool

    # corporate/legal
    has_contact_info: bool
    has_address: bool
    has_policy_terms: bool
    has_privacy_terms: bool
    has_career_terms: bool

    # transaction/protected
    has_login_form: bool
    has_password_field: bool
    has_payment_fields: bool
    has_captcha: bool
    has_access_denied: bool

    # graph
    internal_link_count: int
    external_link_count: int
    product_link_count: int
    category_link_count: int
    profile_link_count: int
    article_link_count: int

    # text/layout
    dominant_language: str | None
    keyword_hits: dict[str, int]

6. Scoring 방식

단일 if-else가 아니라 evidence scoring으로 분류한다.

예:

scores = {
    "ProductDetailPage": 0.0,
    "CategoryListingPage": 0.0,
    "ArticlePage": 0.0,
    "QAPage": 0.0,
    "LoginPage": 0.0,
}

6.1 ProductDetailPage scoring 예시

schema.org Product             +0.40
schema.org Offer               +0.15
price detected                 +0.15
cart button                    +0.20
variant selector               +0.15
SKU                            +0.10
product image gallery          +0.10
review section                 +0.05
URL product hint               +0.05

6.2 CategoryListingPage scoring 예시

repeated product cards          +0.35
filter panel                    +0.20
sort control                    +0.15
pagination                      +0.10
many product links              +0.20
breadcrumb category             +0.10
URL category/list hint          +0.05

6.3 ArticlePage scoring 예시

schema.org Article              +0.35
schema.org NewsArticle          +0.35
author                          +0.15
published date                  +0.15
article body                    +0.20
headline                        +0.10
tags                            +0.05
URL blog/news/article hint       +0.05

6.4 QAPage scoring 예시

schema.org QAPage               +0.35
question block                  +0.20
answer block                    +0.20
accepted answer                 +0.15
votes                           +0.10
comments                        +0.05
URL question/qna hint            +0.05

6.5 LoginPage scoring 예시

password input                  +0.40
login keyword                   +0.20
email/user id input             +0.15
submit button                   +0.10
signup/reset password links      +0.10

7. Classification Result 모델

분류 결과는 단일 문자열이 아니라 아래 구조로 반환한다.

@dataclass
class EvidenceItem:
    key: str
    value: str | int | float | bool | None
    weight: float
    source: str
    message: str


@dataclass
class PageClassificationResult:
    url: str

    primary_page_type: str
    secondary_page_types: list[str]

    domain: str
    archetype: str
    main_entity_type: str | None

    action_intents: list[str]
    graph_roles: list[str]

    confidence: float
    alternatives: list[tuple[str, float]]
    evidence: list[EvidenceItem]

    should_analyze: bool
    analyze_strategy: str
    llm_policy: str

    is_protected: bool
    is_noise: bool

예:

{
  "primary_page_type": "CategoryListingPage",
  "secondary_page_types": ["FilteredResultsPage"],
  "domain": "Commerce",
  "archetype": "Listing",
  "main_entity_type": "Product",
  "action_intents": ["Filter", "Compare", "Navigate"],
  "graph_roles": ["CollectionHub", "RelationHub"],
  "confidence": 0.88,
  "should_analyze": true,
  "analyze_strategy": "AnalyzeRelationsOnly",
  "llm_policy": "RuleOnly",
  "is_protected": false,
  "is_noise": false
}

8. Analyze Strategy 정책

기존 should_analyze_page(page_type, analyze_page_types)는 유지하되, 내부를 확장한다.

기존 방식:

ProductPage -> analyze
CategoryPage -> skip
SearchPage -> skip
BoardPage -> skip

개선 방식:

ProductDetailPage      -> AnalyzeFull
ArticlePage            -> AnalyzeFull
BrandStoryPage         -> AnalyzeFull
CategoryListingPage    -> AnalyzeRelationsOnly
SearchResultsPage      -> AnalyzeDiscoveryOnly
ForumThreadPage        -> AnalyzeFull
ForumBoardPage         -> AnalyzeRelationsOnly
FAQPage                -> AnalyzeFull
QAPage                 -> AnalyzeFull
TermsPage              -> AnalyzeDocumentOnly
PrivacyPolicyPage      -> AnalyzeDocumentOnly
SitemapPage            -> AnalyzeDiscoveryOnly
RobotsTxtPage          -> AnalyzeMetadataOnly
LoginPage              -> SkipProtected
CheckoutPage           -> SkipProtected
PaymentPage            -> SkipProtected
ErrorPage              -> SkipNoise
NotFoundPage           -> SkipNoise

9. LLM Policy 정책

LLM은 모든 페이지에 쓰지 않는다.

LLMFull
- ArticlePage
- ProductDetailPage
- BrandStoryPage
- ResearchPaperPage
- LegalArticlePage

LLMLight
- FAQPage
- QAPage
- DocumentationPage
- TutorialPage

LLMForAmbiguityOnly
- CategoryListingPage
- SearchResultsPage
- ForumBoardPage
- ArchivePage
- TagPage

RuleOnly
- SitemapPage
- RSSFeedPage
- RobotsTxtPage
- LoginPage
- CheckoutPage
- PaymentPage

Skip
- ErrorPage
- NotFoundPage
- AccessDeniedPage
- CaptchaPage

10. UnknownPage 처리

UnknownPage는 버리지 않는다.

분류 confidence가 낮은 경우:

primary_page_type = "UnknownPage"
graph_roles = ["UnknownPattern"]
analyze_strategy = "AnalyzeMetadataOnly"
llm_policy = "LLMForAmbiguityOnly" 또는 "NoLLM"

저장해야 할 정보:

url
title
text sample
html fingerprint
dom fingerprint
schema types
link pattern
button labels
forms
top keywords
embedding
classification alternatives

향후 clustering 대상:

UnknownPatternCluster

새 page type 후보 생성 예:

Unknown cluster 12
 -> repeated comparison tables
 -> product attributes
 -> no cart button
 -> many product links
 => ProductComparisonPage 후보

11. 구현 단계

Phase 1. Taxonomy와 Result 모델 추가

작업

  1. page_type_taxonomy.py 추가
  2. PageDomain enum 추가
  3. PageArchetype enum 추가
  4. PageType enum 또는 문자열 상수 추가
  5. EntityType enum 추가
  6. ActionIntent enum 추가
  7. GraphRole enum 추가
  8. AnalyzeStrategy enum 추가
  9. LLMPolicy enum 추가
  10. PageClassificationResult, EvidenceItem dataclass 추가

완료 기준

  • 기존 ProductPage, CategoryPage 등과 호환되어야 한다.
  • 기존 코드에서 string page_type만 기대하는 부분은 깨지지 않도록 compatibility helper를 제공한다.

예:

def get_legacy_page_type(result: PageClassificationResult) -> str:
    return result.primary_page_type

Phase 2. Signal Extractor 추가

작업

  1. page_signals.py 추가
  2. page_signal_extractor.py 추가
  3. HTML에서 JSON-LD 추출
  4. OpenGraph 추출
  5. Twitter Card 추출
  6. meta 태그 추출
  7. button text 추출
  8. form/input 추출
  9. link pattern 추출
  10. 반복 카드 후보 탐지
  11. breadcrumb 후보 탐지
  12. price/currency 후보 탐지
  13. article author/date 후보 탐지
  14. login/password/payment/captcha 후보 탐지

완료 기준

  • 입력 HTML이 일부 깨져도 예외 없이 동작해야 한다.
  • BeautifulSoup 또는 현재 프로젝트에서 사용하는 parser에 맞춰 구현한다.
  • 없는 값은 빈 리스트/빈 dict/False로 처리한다.

Phase 3. Scoring 기반 Page Type 분류

작업

  1. page_type_scorer.py 추가
  2. 주요 page type별 scoring function 작성
  3. score normalize
  4. top score와 alternatives 산출
  5. confidence 계산
  6. evidence 기록

최소 구현 대상:

ProductDetailPage
CategoryListingPage
SearchResultsPage
ArticlePage
BlogPostPage
QAPage
FAQPage
ForumBoardPage
ForumThreadPage
BrandStoryPage
AboutPage
ContactPage
DocumentationPage
APIReferencePage
JobPostingPage
PricingPage
LoginPage
CheckoutPage
TermsPage
PrivacyPolicyPage
SitemapPage
RSSFeedPage
ErrorPage
UnknownPage

완료 기준

  • 단일 if-else return 금지
  • 반드시 evidence list를 남긴다
  • confidence가 낮으면 UnknownPage로 보낼 수 있어야 한다

Phase 4. Analyze Strategy / LLM Policy 분리

작업

  1. page_analysis_policy.py 추가
  2. PageType -> AnalyzeStrategy mapping 작성
  3. PageType -> LLMPolicy mapping 작성
  4. 기존 should_analyze_page()를 compatibility 형태로 유지
  5. 신규 함수 추가

예:

def decide_analyze_strategy(result: PageClassificationResult) -> AnalyzeStrategy:
    ...

def decide_llm_policy(result: PageClassificationResult) -> LLMPolicy:
    ...

def should_analyze_page(result_or_page_type, analyze_page_types=None) -> bool:
    ...

완료 기준

  • 기존 호출부가 바로 깨지지 않아야 한다.
  • CategoryListingPage는 기본 skip이 아니라 AnalyzeRelationsOnly가 되어야 한다.
  • SearchResultsPage는 AnalyzeDiscoveryOnly가 되어야 한다.
  • Login/Checkout/Payment는 SkipProtected가 되어야 한다.

Phase 5. 기존 Extractor 연결 수정

작업

기존 흐름:

classify_page(...)
 -> page_type
 -> should_analyze_page(page_type, analyze_page_types)
 -> Extractor 실행
 -> HybridExtractor 내부에서 LLM skip 판단

개선 흐름:

classify_page(...)
 -> PageClassificationResult
 -> decide_analyze_strategy(result)
 -> decide_llm_policy(result)
 -> strategy에 따라 Extractor 또는 relation/link extractor 실행

전략별 처리

AnalyzeFull
 -> 기존 Extractor + HybridExtractor + LLM policy 적용

AnalyzeRelationsOnly
 -> 링크, breadcrumb, category, repeated card 중심 추출
 -> full LLM 금지

AnalyzeDiscoveryOnly
 -> crawl candidate, result link, pagination만 추출
 -> content claim 추출 금지

AnalyzeMetadataOnly
 -> title, metadata, schema, canonical, link relation만 저장

AnalyzeDocumentOnly
 -> 법률/정책/문서 구조 추출
 -> 필요 시 LLM 사용

SkipProtected
 -> 개인정보/계정/결제 페이지 분석 금지

SkipNoise
 -> 저장 최소화 또는 제외

Phase 6. Unknown Pattern 저장 기반 추가

작업

  1. UnknownPage 또는 confidence 낮은 페이지를 별도 저장
  2. DOM fingerprint 생성
  3. text fingerprint 생성
  4. link pattern summary 생성
  5. 향후 clustering을 위한 embedding hook 추가

초기에는 clustering까지 구현하지 않아도 된다.
다만 데이터 구조는 남겨야 한다.


Phase 7. 테스트 추가

단위 테스트 대상

ProductDetailPage
CategoryListingPage
SearchResultsPage
ArticlePage
QAPage
FAQPage
ForumThreadPage
DocumentationPage
JobPostingPage
LoginPage
CheckoutPage
TermsPage
SitemapPage
UnknownPage

테스트 샘플

각 page type에 대해 최소 HTML fixture를 만든다.

예:

tests/fixtures/pages/product_detail.html
tests/fixtures/pages/category_listing.html
tests/fixtures/pages/article.html
tests/fixtures/pages/qapage.html
tests/fixtures/pages/login.html

테스트 기준

primary_page_type이 기대값과 일치
confidence가 최소 기준 이상
evidence가 비어 있지 않음
analyze_strategy가 기대값과 일치
llm_policy가 기대값과 일치
protected page가 분석되지 않음
UnknownPage가 예외 없이 처리됨

12. 분류 예시

12.1 ProductDetailPage

입력 신호:

JSON-LD @type Product
price
add to cart
variant selector
product images
reviews

결과:

{
  "primary_page_type": "ProductDetailPage",
  "domain": "Commerce",
  "archetype": "Detail",
  "main_entity_type": "Product",
  "action_intents": ["Buy", "Review"],
  "graph_roles": ["EntityAnchor"],
  "confidence": 0.93,
  "analyze_strategy": "AnalyzeFull",
  "llm_policy": "LLMLight"
}

12.2 CategoryListingPage

입력 신호:

repeated product cards
filter panel
sort control
pagination
many product links
breadcrumb

결과:

{
  "primary_page_type": "CategoryListingPage",
  "domain": "Commerce",
  "archetype": "Listing",
  "main_entity_type": "Product",
  "action_intents": ["Filter", "Navigate", "Compare"],
  "graph_roles": ["CollectionHub", "RelationHub"],
  "confidence": 0.88,
  "analyze_strategy": "AnalyzeRelationsOnly",
  "llm_policy": "RuleOnly"
}

12.3 ArticlePage

입력 신호:

schema.org Article
headline
author
published date
article body
tags

결과:

{
  "primary_page_type": "ArticlePage",
  "domain": "Editorial",
  "archetype": "Article",
  "main_entity_type": "Article",
  "action_intents": ["Read"],
  "graph_roles": ["ClaimSource", "EntityAnchor"],
  "confidence": 0.91,
  "analyze_strategy": "AnalyzeFull",
  "llm_policy": "LLMFull"
}

12.4 LoginPage

입력 신호:

password input
email input
login button
reset password link

결과:

{
  "primary_page_type": "LoginPage",
  "domain": "Transaction",
  "archetype": "Form",
  "main_entity_type": null,
  "action_intents": ["Login"],
  "graph_roles": ["TransactionOnly"],
  "confidence": 0.96,
  "analyze_strategy": "SkipProtected",
  "llm_policy": "Skip"
}

13. 하위 호환성 요구

기존 코드가 아래처럼 page_type 문자열을 기대할 수 있다.

page_type = classify_page(...)
should_analyze_page(page_type, analyze_page_types)

따라서 처음부터 모든 호출부를 바꾸지 말고, compatibility layer를 둔다.

권장:

def classify_page_legacy(*args, **kwargs) -> str:
    result = classify_page(*args, **kwargs)
    return result.primary_page_type

또는:

def normalize_page_type(page_type_or_result) -> str:
    if isinstance(page_type_or_result, PageClassificationResult):
        return page_type_or_result.primary_page_type
    return str(page_type_or_result)

14. 기존 page type과 신규 page type 매핑

ProductPage      -> ProductDetailPage
CategoryPage     -> CategoryListingPage 또는 CategoryPage
SearchPage       -> SearchResultsPage
BoardPage        -> ForumBoardPage
NoticePage       -> PublicNoticePage 또는 NoticePage
BrandStoryPage   -> BrandStoryPage
PromotionPage    -> PromotionPage 또는 CampaignLandingPage
UnknownPage      -> UnknownPage
ReviewPage       -> ReviewPage 또는 ProductReviewPage

기존 이름은 당분간 alias로 유지한다.


15. 코딩 원칙

  1. 단일 if-return 방식으로 확장하지 말 것
  2. evidence를 반드시 남길 것
  3. confidence를 반드시 계산할 것
  4. PageType 하나만 반환하지 말 것
  5. Category/Search/Board 계열을 무조건 skip하지 말 것
  6. Login/Checkout/Payment는 보호 페이지로 처리할 것
  7. UnknownPage는 폐기하지 말고 저장 가능한 구조로 만들 것
  8. JSON-LD, OpenGraph, meta, DOM, link graph를 모두 signal로 사용할 것
  9. 다국어 키워드 확장을 고려할 것
  10. 기존 호출부가 깨지지 않도록 compatibility helper를 제공할 것

16. 최소 완료 기준

이번 작업의 최소 완료 기준은 다음과 같다.

1. PageClassificationResult dataclass 추가
2. PageDomain / PageArchetype / PageType / EntityType / ActionIntent / GraphRole / AnalyzeStrategy / LLMPolicy 정의
3. JSON-LD / OpenGraph / URL / DOM / text 기반 signal 추출
4. 최소 20개 page type scoring 구현
5. CategoryListingPage가 AnalyzeRelationsOnly로 처리됨
6. SearchResultsPage가 AnalyzeDiscoveryOnly로 처리됨
7. LoginPage / CheckoutPage / PaymentPage가 SkipProtected로 처리됨
8. ProductDetailPage / ArticlePage / FAQPage / QAPage는 AnalyzeFull 가능
9. UnknownPage가 evidence와 함께 반환됨
10. 기존 should_analyze_page 호환성 유지
11. 테스트 fixture 10개 이상 추가
12. pytest 통과

17. 최종 목표

이 작업의 최종 목표는 page_classifier.py를 다음 수준으로 확장하는 것이다.

기존:

URL/text 기반 page type 분류기

개선:

Semantic Page Understanding Layer

최종 파이프라인:

Raw Page
 -> Signal Extraction
 -> Evidence Scoring
 -> Domain Classification
 -> Archetype Classification
 -> Main Entity Classification
 -> Action Intent Classification
 -> Graph Role Assignment
 -> Analyze Strategy Decision
 -> LLM Policy Decision
 -> Unknown Pattern Storage

이렇게 해야 온톨로지 플랫폼이 특정 쇼핑몰이나 특정 사이트에 종속되지 않고, 인터넷 전체의 다양한 페이지를 의미 단위로 해석할 수 있다.


18. Codex 작업 요청 요약

Codex는 이 문서를 기준으로 다음 작업을 수행한다.

1. 현재 page_classifier.py를 확인한다.
2. 기존 호출부와 테스트를 확인한다.
3. taxonomy / signal / scoring / policy 레이어를 분리한다.
4. 기존 단순 page_type 문자열 반환 구조를 PageClassificationResult 중심으로 확장한다.
5. 기존 코드가 깨지지 않도록 legacy compatibility를 유지한다.
6. Category/Search/Board를 단순 skip하지 않고 strategy 기반으로 처리한다.
7. protected/transaction page는 안전하게 skip한다.
8. UnknownPage는 evidence와 함께 저장 가능하게 만든다.
9. 최소 fixture 테스트를 추가한다.
10. pytest로 회귀 테스트를 확인한다.

19. 주의 사항

  • 기존 엔진을 대규모로 폐기하지 말 것.
  • 현재 parser, crawler, extractor 흐름을 먼저 파악한 뒤 최소 침습 방식으로 확장할 것.
  • page type enum 확장은 허용하되, extractor 전체를 한 번에 갈아엎지 말 것.
  • LLM 사용량이 늘어나지 않도록 LLMPolicy를 반드시 적용할 것.
  • protected page에서 개인정보나 계정 정보를 추출하지 말 것.
  • 분류가 애매할 경우 억지로 하나의 타입에 넣지 말고 alternatives와 confidence를 남길 것.
  • Evidence 기반 디버깅이 가능해야 한다.

20. 향후 확장 방향

이번 작업 이후 다음 단계로 확장할 수 있다.

1. UnknownPage clustering
2. DOM fingerprint 기반 template detection
3. site-specific learned page archetype
4. screenshot 기반 visual block classification
5. multilingual keyword dictionary
6. schema.org type mapping 강화
7. page type별 extraction schema 자동 선택
8. crawl priority와 page type 연동
9. graph relation confidence와 page evidence 연동
10. admin UI에서 page classification 결과 검토