Skip to content

fix: JCEF 스크래핑 브라우저를 오프스크린 렌더링으로 전환 (#9)#20

Merged
dj258255 merged 1 commit into
mainfrom
fix/jcef-offscreen-rendering
Jul 6, 2026
Merged

fix: JCEF 스크래핑 브라우저를 오프스크린 렌더링으로 전환 (#9)#20
dj258255 merged 1 commit into
mainfrom
fix/jcef-offscreen-rendering

Conversation

@dj258255

@dj258255 dj258255 commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Fixes #9

문제 (사용자 제보)

Linux에서 코드포스 문제를 가져오면 제목줄 없는 플로팅 창이 나타나고, 이를 Alt+F4로 닫으면 다음 오류 발생:

HTTP error fetching URL. Status=403, URL=[...]
JCEF fallback: JCEF internal timeout

원인

코드포스는 Cloudflare가 Jsoup(비브라우저 TLS 지문)을 403으로 차단하므로, 진짜 Chromium(JCEF)으로 페이지를 열어 HTML을 추출하는 폴백이 있음. 이 브라우저는 원래 보이면 안 되는 창인데, 숨기는 방식이 화면 밖 좌표였음:

frame = JFrame().apply {
    isUndecorated = true          // 제목줄 없음 → 닫기 버튼이 없던 이유
    setLocation(-3000, -3000)     // 화면 밖으로 숨기려는 의도
}

Wayland를 비롯한 일부 Linux WM은 앱의 창 위치 지정을 무시하고 화면 안에 배치하므로, 숨겨야 할 스크래핑 창이 그대로 노출됨. 사용자가 그 창을 닫으면 폴러가 응답을 못 받아 내부 타임아웃으로 이어짐.

변경

  • CodeforcesJcefFetcher·SweaJcefFetcher 모두 오프스크린 렌더링(OSR) 브라우저로 전환 — OS 창 자체가 생성되지 않아 어떤 플랫폼/WM에서도 노출 불가, 사용자가 실수로 닫을 수도 없음
  • OSR는 컴포넌트 크기를 뷰포트로 사용하므로 1024x768로 명시 지정
  • OSR 초기화가 실패하는 환경에서는 기존 숨김 프레임 방식으로 폴백

테스트

  • ./gradlew compileKotlin test 통과
  • 실제 코드포스 fetch(Cloudflare 챌린지 통과)는 runIde에서 확인 필요 — macOS에서 동작 확인 후, 제보자에게 Linux 확인 요청 권장

코드포스/SWEA 문제 가져오기 폴백이 사용하던 '화면 밖 좌표(-3000,-3000)
숨김 프레임' 방식은 Linux(Wayland 등)에서 WM이 창 위치 지정을 무시해
제목줄 없는 플로팅 창으로 노출됐고, 사용자가 이를 닫으면 폴러가 응답을
받지 못해 'JCEF internal timeout' 오류가 발생했음.

오프스크린 렌더링(OSR)으로 브라우저를 생성하면 OS 창 자체가 없어 어떤
플랫폼에서도 노출될 수 없음. OSR 초기화가 실패하는 환경에서는 기존 숨김
프레임 방식으로 폴백.
@dj258255 dj258255 merged commit d49bcec into main Jul 6, 2026
2 checks passed
@dj258255 dj258255 deleted the fix/jcef-offscreen-rendering branch July 6, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codeforces opens in a separate floating window and closing it results in a 403/JCEF timeout error

1 participant