Skip to content

host 조회 실패를 확정 실패로 내려 재시도를 태우지 않는다 - #43

Open
m-a-king wants to merge 1 commit into
mainfrom
fix/42-nxdomain-permanent-failure
Open

host 조회 실패를 확정 실패로 내려 재시도를 태우지 않는다#43
m-a-king wants to merge 1 commit into
mainfrom
fix/42-nxdomain-permanent-failure

Conversation

@m-a-king

Copy link
Copy Markdown
Collaborator

Situation

  • dev 에서 존재하지 않는 주소를 위시리스트에 담은 건이, 몇 번을 시도해도 결과가 같은 실패인데 "일시 오류"로 처리되고 있었다. 호스트를 IP 로 조회하는 단계에서 실패하는데 그 실패를 일시 code 로 내려, 호출자가 재시도 예산을 다 태운 뒤 "재시도 소진"으로 종결했다.
  • 그 결과 두 가지가 어긋났다.
어긋남 기록된 것 실제
운영 사유 외부가 불안정했다 (재시도 여력·대상 장애를 보라) 등록된 주소가 잘못됐다 (사용자 안내로 끝날 일)
비용 재시도로 회복 가능한 실패 재등록마다 호출 2회를 다시 태우는 확정 실패
  • 실측: 같은 주소가 2026-08-01 과 2026-08-15 두 번 등록됐고, 두 번 모두 시도 2회를 소진한 뒤 실패로 끝났다. 등록 사이에 바뀔 수 있는 것이 없는데도 같은 낭비가 반복됐다.

Task

  • 조회 실패를 확정 실패로 내려 재시도 축에서 빼낸다.
  • 그 과정에서 두 가지를 정해야 했다. 어떤 실패 code 로 내릴 것인가, 그리고 리졸버 자체가 잠깐 아플 때(진짜 없는 주소가 아닌 경우)를 어떻게 다룰 것인가.

Action

구현

  • 호스트 조회 실패를 확정 실패 팩토리로 번역한다. InternalHostGuardUnknownHostException 을 받으면 이제 PageFetchException.unresolvableHost 를 던지고, 그 팩토리가 code INVALID_URL 과 permanent=true 를 박는다.
  • 헤드리스 에스컬레이션 대상에서 뺀다(escalatable=false). 주소가 조회되지 않으면 실제 브라우저도 갈 곳이 없다. 이는 SSRF 차단에 이은 두 번째 예외이므로, 클래스 Javadoc 의 "SSRF 만 예외" 서술을 고치고 두 예외의 근거가 다르다는 점(보안 판단 vs 성립 불가 판단)을 갈라 적었다.
  • 로그는 그대로 둔다. 조회 실패는 계약상 정상 결과이므로 info 가 맞다.

결정: 어떤 code 로 내릴 것인가

비용 판단
기존 INVALID_URL 재사용 (채택) 계약 문서 한 줄 갱신 카탈로그에 이미 확정으로 있고 호출자 매핑도 맞아, 이 PR 만으로 동작이 완결된다. 호출자 입장에서 형식 위반과 결론("이 주소로는 갈 수 없다")이 같아 달리 행동할 여지도 없다
새 code 신설 infra, core, extractor 3 repo 순차 머지 얻는 것은 로그에서의 사유 구분뿐이다. 메트릭 라벨은 bucket 단위라 집계는 어느 쪽이든 같고, 호출자 매핑이 따라붙기 전까지는 internal_error 로 세어지는 창까지 생긴다

결정: 리졸버 일시 장애를 구분할 것인가

  • Java 는 없는 주소와 리졸버 일시 장애(응답 지연·서버 오류)를 같은 예외로 던져 구분할 수단을 주지 않는다. 구분 없이 전부 확정으로 두기로 했다.
  • 근거: 리졸버 장애는 이 박스 전역의 문제라 개별 추출의 재시도가 아니라 호스트 관측이 다룰 일이고, 그 창에서 확정된 건은 사용자 재등록이 새 시도를 만든다.
  • 버린 대안: 응답 코드까지 보고 정확히 가르려면 조회기를 교체해야 하는데, 그 조회기는 SSRF 가드가 검증한 IP 를 연결이 그대로 쓰도록 묶어 두는 계약을 함께 지고 있다. 보안 계약을 건드리는 변경이라 별건으로 뺐다.

검증

  • 단위: 조회에 실패하는 stub 을 주입해, 가드가 확정·비에스컬레이션·INVALID_URL 세 속성을 모두 세운 예외를 던지는지 본다. 원인 예외가 그대로 실려 오는지도 함께 확인한다(디버깅 단서 유실 방지).
  • 계약 대조: 새 팩토리를 카탈로그 대조 표에 등록했다. 표에 없는 팩토리는 분류가 무보증으로 남고, 그 자체를 실패로 보는 테스트라 등록이 곧 커버리지다.
  • 통합: 조회 실패가 응답 계약에서 422 와 해당 code 로 나가는지 확인한다. 형식 위반의 422 케이스와 나란히 둬, 두 경로가 같은 결론에 닿는 것이 의도임을 테스트로 드러낸다.

Result

  • 이 주소로는 첫 시도에서 바로 실패가 확정되므로, 호출자의 재시도와 재등록마다 반복되던 추출 호출이 사라진다.
  • 운영 사유가 "재시도 소진"이 아니라 "상품 아님" 계열로 기록돼, 지표에서 외부 장애와 잘못된 입력이 섞이지 않는다.
  • 머지 순서: 계약 문서 갱신(TeamPiKi/infra) 이 먼저다. 소비 repo 의 CI 가 그 카탈로그를 받아 대조하므로, 순서가 뒤바뀌면 문서와 코드가 어긋난 창이 생긴다. 카탈로그 값 자체는 바뀌지 않아 대조 결과에는 영향이 없다.
  • 남는 것: 리졸버 일시 장애의 오확정 가능성. 빈도가 관측되면 응답 코드 기반 구분을 별건으로 다룬다.

연관 이슈

- InternalHostGuard 가 UnknownHostException 을 upstreamError(UPSTREAM_ERROR, 일시)로 번역해, 호출자가 재시도 2회를 소진한 뒤 reason=retry_exhausted 로 종결하던 것을 unresolvableHost(INVALID_URL, 확정)로 바꾼다
- 두 가지가 어긋나 있었다. 운영 사유가 "외부 불안정"으로 기록돼 실제 사유(등록된 주소가 잘못됨)를 가렸고, 확정적으로 실패할 주소에 재등록마다 호출 2회를 다시 태웠다. dev 에서 같은 https://df 가 2회 등록돼 두 번 다 attempt=2 를 소진한 것이 실측이다
- code 는 새로 만들지 않고 INVALID_URL 을 재사용한다. 형식 위반과 결론이 같고 카탈로그에 이미 permanent 로 있어 호출자 매핑이 그대로 맞는다
- escalatable=false — resolve 되지 않는 host 는 헤드리스 브라우저도 도달하지 못한다. blockedHost 에 이어 "무조건 폴백"의 두 번째 예외이며, 근거가 보안이 아니라 성립 불가라는 점을 클래스 Javadoc 에 갈라 적었다
- UnknownHostException 이 NXDOMAIN 과 리졸버 일시 장애를 구분하지 않는 한계는 확정 처리 쪽으로 감수한다. 리졸버 장애는 박스 전역 문제라 호스트 관측이 다룰 일이고, 그 창의 건은 재등록이 새 시도를 만든다. RCODE 로 가르려면 SSRF 가드·IP pin 계약까지 바꿔야 해 별건이다

Closes #42
@m-a-king m-a-king added the fix 외부 가시적 결함 수정 label Aug 16, 2026
@m-a-king m-a-king self-assigned this Aug 16, 2026
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 80a8b3f3-68fb-4c9c-af67-c3549a174e07


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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix 외부 가시적 결함 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NXDOMAIN(호스트 조회 실패)을 확정 실패로 내려 재시도를 태우지 않는다

1 participant