임베디드 브라우저 네이버 차단문제 해결
개요
심화반 학생 중 한명이 임베디드 웹브라우저 (Embedded Web Browser) 를 활용해 앱을 만들다 질문을 합니다.
"앱을 완성하고 구글에서 검색한 페이지는 이동이 되는데 네이버는 안돼요.?"
살펴보니 페이지 이동시 아래와 같은 경고가 발생합니다.
Failed to execute 'postMessage' on 'DOMWindow':
The target origin
provided ('https://recoshopping.naver.com')
does not match the
recipient window's origin ('https://www.naver.com')
이 글은,
임베디드 브라우저가 무엇인지?
Python, PyQt5로 브라우저를 만드는 방법,
왜 네이버에서만 문제가 발생했는지?
어떻게 해결했는지?
전 과정에 대해 설명합니다.
임베디드 웹브라우저?
일반 Chrome, Edge처럼 외부 브라우저를 띄우는 것이 아니라,
"애플리케이션 내부에 웹 브라우저 엔진을 내장해서
웹페이지를 직접
렌더링하는 방식"
을 말합니다.
대표적으로 다음 기술들이 임베디드
브라우저입니다
- Android WebView
- iOS WKWebView
- Electron (Chromium Embedded)
- CEF (Chromium Embedded Framework)
- Qt WebEngine (Chromium 기반)
PyQt6의 QWebEngineView도 Chromium 기반 엔진을 품고 있어 데스크탑 앱
안에서 웹을 띄우는 데 매우 적합하고 학원 게시물에서도 소개한 적이 있습니다.
PyQt6 웹브라우저 만들기
아래 코드를 실행하면 간단한 임베디드 브라우저가 만들어집니다.
|
| [PyQt6 WebEngineView 기반 브라우저] |
from PyQt6.QtWidgets import QApplication, QWidget, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWebEngineCore import QWebEngineProfile, QWebEnginePage
from PyQt6.QtCore import QUrl
import sys
class Form(QWidget):
def __init__(self):
super().__init__()
self.home = QUrl('https://google.com')
hbox = QHBoxLayout()
self.btn_go = QPushButton('Move')
self.le_url = QLineEdit(self.home.toString())
hbox.addWidget(self.le_url)
hbox.addWidget(self.btn_go)
hbox.setStretchFactor(self.le_url, 10)
self.webview = QWebEngineView()
self.webview.load(self.home)
vbox = QVBoxLayout(self)
vbox.addLayout(hbox)
vbox.addWidget(self.webview)
self.setWindowTitle('Ocean Coding School')
self.setLayout(vbox)
# signal
self.webview.urlChanged.connect(self.onUrlChanged)
self.btn_go.clicked.connect(self.onMove)
self.le_url.returnPressed.connect(self.onMove)
def onUrlChanged(self, url):
self.le_url.setText(url.toString())
self.le_url.home(True)
def onMove(self):
txt = self.le_url.text()
if txt.find('http')==-1 and txt.find('https')==-1:
txt = f'http://{txt}'
self.le_url.setText(txt)
url = QUrl(txt)
self.webview.load(url)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Form()
w.show()
sys.exit(app.exec())
네이버검색 링크는 왜 안 열릴까?
만든 임베디드 브라우저로 구글 검색 결과 링크는 정상적으로 열립니다.
하지만 네이버 검색 링크를 누르면 아무 반응이 없으면서 다음 오류가 뜹니다:
Failed to execute 'postMessage' on 'DOMWindow':
The target origin
provided ('https://recoshopping.naver.com')
does not match the
recipient window's origin ('https://www.naver.com')
이 오류는 CORS(도메인 간 통신) 보안 문제로 보이지만, 사실 더
중요한 핵심이 있습니다.
원인 1. 네이버는 임베디드 브라우저를 차단
네이버는 자체적으로 WebView / WebEngine / Embedded Browser 차단 정책이
있습니다.
아마도 보안·광고·추천 엔진 보호 때문이고,
- 로그인
- 쇼핑(recoshopping)
- 추천상품 영역
- 광고 기반 링크
이런 페이지들은 WebView에서 열리지 않도록 설계되어 있습니다.
즉, 코드 문제가 아니라 네이버의 정책적인 차단입니다.
원인 2. 네이버는 window.open() 기반 링크가 많다
네이버 검색 결과의 상당수는 직접 <a> 태그가 아니라,
window.open("https://recoshopping.naver.com/....")
형태로 열립니다.
하지만 QtWebEngine 기본 설정은
[새 창 요청 → 무시 → 이동 안 됨] 이라서 링크가 먹지
않습니다.
해결방법
1. User-Agent를 실제 브라우저처럼 설정하기
profile.setHttpUserAgent(
"Mozilla/5.0 (Windows NT 10.0;
Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko)
"
"Chrome/120.0.0.0 Safari/537.36"
)
네이버는 WebView의 User-Agent를 감지하여 제한을 걸기 때문에
Chrome UA로 바꾸면 차단이 많이 풀립니다.
(테스트 해보니 쇼핑, 일부링크는 완벽하진 않습니다.)
2. window.open() 요청을 현재 창에서 열기
네이버 검색 결과는 100%, window.open() 사용 (새창 열기)
그런데 QtWebEngine 기본 설정은 [새 창 요청 → 무시 → 이동 안 됨] 이므로,
아래와 같이 QWebEngineView의 상속클래스에서 createWindow() 를 overriding 해서 처리.
class CustomWebView(QWebEngineView):
def createWindow(self,
_type):
return self
(이 방법 역시
완전한 우회가 불가능합니다)
해결책이 적용된 코드
from PyQt6.QtWidgets import QApplication, QWidget, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWebEngineCore import QWebEngineProfile, QWebEnginePage
from PyQt6.QtCore import QUrl
import sys
class CustomWebView(QWebEngineView):
def createWindow(self, _type):
return self
class Form(QWidget):
def __init__(self):
super().__init__()
self.home = QUrl('https://google.com')
hbox = QHBoxLayout()
self.btn_go = QPushButton('Move')
self.le_url = QLineEdit(self.home.toString())
hbox.addWidget(self.le_url)
hbox.addWidget(self.btn_go)
hbox.setStretchFactor(self.le_url, 10)
self.profile = QWebEngineProfile(self)
self.profile.setHttpUserAgent(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36"
)
self.page = QWebEnginePage(self.profile, self)
self.webview = CustomWebView()
self.webview.setPage(self.page)
self.webview.load(self.home)
vbox = QVBoxLayout(self)
vbox.addLayout(hbox)
vbox.addWidget(self.webview)
self.setWindowTitle('Ocean Coding School')
self.setLayout(vbox)
# signal
self.webview.urlChanged.connect(self.onUrlChanged)
self.btn_go.clicked.connect(self.onMove)
self.le_url.returnPressed.connect(self.onMove)
def onUrlChanged(self, url):
self.le_url.setText(url.toString())
self.le_url.home(True)
def onMove(self):
txt = self.le_url.text()
if txt.find('http')==-1 and txt.find('https')==-1:
txt = f'http://{txt}'
self.le_url.setText(txt)
url = QUrl(txt)
self.webview.load(url)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Form()
w.show()
sys.exit(app.exec())
정리하면
PyQt WebEngine은 편리한 임베디드 브라우저 엔진이다. 😀
하지만 네이버는 보안/광고/추천 엔진 이유로 임베디드 브라우저 일부 기능을
차단한다. 😥
특히 일부 내부 추천 도메인은 WebEngine에서 정상
동작하지 않는다. 😫
하지만 User-Agent 변경 + createWindow()
오버라이드로 대부분의 네이버 기능은 동작하게 만들 수 있다. 😄
만약 완전한 동작을 원하면 특정 링크만 외부 브라우저(크롬, 엣지, 사파리 등) 로 열기 전략을 사용한다.
결론적으로 완벽하진 않지만, 보안을 위한 네이버의 차단정책을 이해, 존중할 필요가 있다고 생각합니다.
생각하고 공부할 주제를 던져준 학원생 HJ 군에게 감사합니다.

댓글
댓글 쓰기