Skip to content

허가 없는 대상에는 헤드리스를 열지 않는다 - #31

Merged
m-a-king merged 1 commit into
mainfrom
feat/honest-extraction
Aug 12, 2026
Merged

허가 없는 대상에는 헤드리스를 열지 않는다#31
m-a-king merged 1 commit into
mainfrom
feat/honest-extraction

Conversation

@m-a-king

@m-a-king m-a-king commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Situation

  • Extractor 는 정적 fetch(plain)로 못 끝내는 경우 헤드리스 브라우저로 넘어간다 - 직행(headlessFirst)·차단 승격·불완전 승격 세 경로다. 지금까지 이 경로는 "비싸고 느리니 필요할 때만" 이라는 최적화로만 게이트됐고, "이 대상에 브라우저를 써도 되는가" 라는 허가는 없었다.
  • 방향 전환: 헤드리스는 허가받은 대상에만 쓴다. 허가 여부의 주인은 호출자(core DB·백오피스)이고, 무상태인 Extractor 는 요청 플래그로만 받는다.

Task

  • 어떻게 허가를 요청으로 받되 무상태를 지키나. 허가 원장을 Extractor 에 두면 안 된다(설계 경고 신호). 요청 필드 하나로만 받는다.
  • 배포 순서에 뚫리지 않게. 이 필드를 모르는 구버전 core 의 요청이 헤드리스를 열어버리면 허가 계약이 조용히 새므로, 누락은 안전한 쪽으로 떨어져야 한다.
  • 세 경로를 한 자리에서 닫나. 직행·차단 승격·불완전 승격이 제각기 게이트되면 하나를 빠뜨린다.

Action

  • 요청에 headlessAllowed 를 받는다. false 면 헤드리스 진입 3경로를 한 가드로 전부 닫고 plain 만 돈다.
  • 게이트는 product.extract.headless.enabled 스위치와 AND 로 묶는다. 둘의 역할이 다르다:
조건 무엇 주인
product.extract.headless.enabled 이 서비스의 운영 비상 차단 Extractor (호출자 정책이 앞설 수 없음)
headlessAllowed 이 대상에 브라우저를 써도 되는지의 허가 호출자 (core DB·백오피스)
  • fail-safe 정규화 - 누락·null 은 false(허가 없음)로 떨어진다(LinkExtractionRequest). 이 필드를 모르는 구버전 호출자의 요청은 헤드리스를 열지 않아, 배포 순서와 무관하게 안전한 쪽으로만 어긋난다.
  • 허가가 라우팅보다 앞선다 - headlessFirst(직행 힌트)도 headlessAllowed 가 false 면 함께 무시된다.
  • 계약 반영 - docs/api-contract.md(계약의 단일 진실)에 headlessAllowed 항목과 §0 원칙을 더하고, 컨트롤러 원장 로그에 값을 남긴다(허가 없는 대상이 브라우저로 갔는지 사후에 되짚는 근거).

Result

  • 허가는 성능 최적화가 아니라 계약이다. headlessAllowed=false 면 어떤 실패 분류로도 헤드리스를 타지 않는다.
  • 커버리지 영향 - core 가 허가를 실어 주기 전까지 이 대상들은 plain 만 돌아 실패로 떨어진다(허가받은 도메인이 화이트리스트에 오르면 회복). 이는 회피 중단의 의도된 결과다.
  • 검증(비자명한 것만) - enabled 는 켜졌지만 headlessAllowed=false 인 요청이 헤드리스 세 경로 어디로도 안 가고 plain 만 타는지를 각 경로별로 단언했다(가드를 임시로 풀면 FAIL 하는 negative control).
  • 후속 - core 쪽 허가 원장(별도 PR)이 함께 배포돼야 실제로 허가받은 대상만 헤드리스를 탄다.

연관 이슈

Summary by CodeRabbit

  • 새 기능
    • 링크 추출 요청에 헤드리스 사용 허가 옵션을 추가했습니다.
    • 허가가 있을 때만 헤드리스 우선 처리 및 대체 경로가 적용됩니다.
  • 변경 사항
    • 허가값이 누락되거나 null이면 기본적으로 헤드리스 처리가 비활성화됩니다.
    • 허가되지 않은 요청은 일반 추출 경로만 사용합니다.
    • 관련 API 계약과 오류 처리 동작을 업데이트했습니다.
  • 테스트
    • 허가 옵션의 기본값, 명시적 설정 및 일반 추출 동작을 검증했습니다.

- 요청에 headlessAllowed 를 받아, false 면 헤드리스 진입 3경로(직행·차단 승격·불완전 승격)를 한 가드로 전부 닫고 plain 만 돈다. product.extract.headless.enabled 스위치와 AND - 둘 다 서야 헤드리스가 열린다.
- 누락·null 은 false(허가 없음)로 정규화하는 fail-safe. 이 필드를 모르는 구버전 호출자의 요청은 헤드리스를 열지 않아, 배포 순서와 무관하게 안전한 쪽으로만 어긋난다.
- headlessFirst 도 headlessAllowed 가 false 면 함께 무시된다(허가가 라우팅보다 앞선다).
- 계약 문서(api-contract.md)와 컨트롤러 원장 로그에 headlessAllowed 를 반영. 허가는 성능 최적화가 아니라 계약이다.
@m-a-king m-a-king added the feat 외부 가시적 새 기능 label Aug 12, 2026
@m-a-king m-a-king self-assigned this Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 48214988-1aae-4231-9cf6-9448b0f9cfe8

📥 Commits

Reviewing files that changed from the base of the PR and between 819edf9 and ffc8953.

📒 Files selected for processing (8)
  • docs/api-contract.md
  • src/main/java/com/depromeet/piki/extractor/api/ExtractionController.java
  • src/main/java/com/depromeet/piki/extractor/api/LinkExtractionRequest.java
  • src/main/java/com/depromeet/piki/extractor/extraction/FallbackProductLinkExtractor.java
  • src/main/java/com/depromeet/piki/extractor/extraction/ProductLinkExtractor.java
  • src/test/java/com/depromeet/piki/extractor/api/ExtractionLinkIntegrationTest.java
  • src/test/java/com/depromeet/piki/extractor/api/LinkExtractionRequestTest.java
  • src/test/java/com/depromeet/piki/extractor/extraction/FallbackProductLinkExtractorTest.java

📝 Walkthrough

Walkthrough

headlessAllowed 요청 필드를 추가했다. 누락 또는 nullfalse로 정규화한다. 허가가 없으면 headless 직행과 모든 승격 경로를 차단하고 plain 추출만 실행한다. 관련 계약, 호출부, fallback 로직 및 테스트를 갱신했다.

Changes

Headless 사용 허가

Layer / File(s) Summary
요청 계약과 호출 연결
docs/api-contract.md, src/main/java/com/depromeet/piki/extractor/api/LinkExtractionRequest.java, src/main/java/com/depromeet/piki/extractor/api/ExtractionController.java, src/main/java/com/depromeet/piki/extractor/extraction/ProductLinkExtractor.java
headlessAllowed 요청 필드를 추가했다. 누락 또는 nullfalse로 정규화한다. 컨트롤러는 해당 값을 extractor에 전달한다.
Fallback headless 경로 차단
src/main/java/com/depromeet/piki/extractor/extraction/FallbackProductLinkExtractor.java
운영 설정과 요청 허가가 모두 활성화된 경우에만 headless 직행과 승격을 실행한다.
허가 동작 검증
src/test/java/com/depromeet/piki/extractor/api/LinkExtractionRequestTest.java, src/test/java/com/depromeet/piki/extractor/api/ExtractionLinkIntegrationTest.java, src/test/java/com/depromeet/piki/extractor/extraction/FallbackProductLinkExtractorTest.java
기본값 정규화와 허가 여부에 따른 plain 추출, headless 실행, 실패 승격 동작을 검증한다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ExtractionController
  participant LinkExtractionRequest
  participant ProductLinkExtractor
  participant FallbackProductLinkExtractor
  participant PlainExtractor
  participant HeadlessExtractor

  ExtractionController->>LinkExtractionRequest: headlessAllowed 요청값 전달
  LinkExtractionRequest-->>ExtractionController: null 또는 누락값을 false로 정규화
  ExtractionController->>ProductLinkExtractor: 정규화된 허가값 전달
  ProductLinkExtractor->>FallbackProductLinkExtractor: headlessFirst와 headlessAllowed 전달
  alt 운영 설정과 요청 허가가 모두 활성화됨
    FallbackProductLinkExtractor->>HeadlessExtractor: headless 직행 또는 승격 추출
  else 허가가 없거나 운영 설정이 비활성화됨
    FallbackProductLinkExtractor->>PlainExtractor: plain 추출만 실행
  end
Loading

Possibly related PRs

  • TeamPiKi/extractor#22: EMPTY_SHELL headless 승격 동작을 도입했으며, 이 변경은 해당 경로에 요청별 허가 조건을 추가한다.
  • TeamPiKi/extractor#24: 불완전 스냅샷의 headless 승격을 변경했으며, 이 변경은 해당 승격을 headlessAllowed로 제한한다.
  • TeamPiKi/extractor#23: LinkExtractionRequestExtractionController의 요청 처리를 확장했으며, 이 변경도 같은 호출 경로를 수정한다.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 허가되지 않은 요청에서 헤드리스 사용을 차단하는 PR의 핵심 변경을 정확하고 간결하게 설명합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@m-a-king
m-a-king merged commit bf15076 into main Aug 12, 2026
1 of 2 checks passed
@m-a-king
m-a-king deleted the feat/honest-extraction branch August 12, 2026 07:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 외부 가시적 새 기능

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant