요약
Facebook 앱의 링크를 통해 iPhone으로 Discourse 사이트를 접속했을 때 CSS, JavaScript, 기능이 없는 단순한 HTML처럼 보인다면, 이는 Discourse의 크롤러 감지 기능이 Facebook의 인앱 브라우저를 봇으로 잘못 식별하고 있기 때문입니다.
이 문제는 Rails 콘솔을 통해 한 줄만 수정하면 해결됩니다.
증상
iPhone의 Facebook 앱에서 Discourse 사이트 링크를 클릭한 사용자는 스타일링이 적용되지 않은 단순한 HTML 페이지(크롤러/noscript 레이아웃)를 확인하게 됩니다. JavaScript가 실행되지 않아 이미지 그리드, 라이트박스, 미디어 플레이어와 같은 기능이 작동하지 않습니다. 동일한 링크는 Safari, Chrome, 그리고 Android 및 iPad의 Facebook 인앱 브라우저에서는 정상적으로 작동합니다.
원인
iPhone의 Facebook 인앱 브라우저는 facebook 단어를 포함하는 사용자 에이전트 문자열로 자신을 식별합니다. 예를 들어 다음과 같습니다:
Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15
(KHTML, like Gecko) Mobile/23D8133 Safari/604.1 MetaIAB Facebook
Discourse의 크롤러 감지(CrawlerDetection)는 사용자 에이전트를 crawler_user_agents 사이트 설정과 대조하여 확인합니다. 이 설정의 기본값에는 facebook이 포함되어 있습니다:
rss|bot|spider|crawler|facebook|archive|wayback|ping|...
이로 인해 Discourse는 실제 사용자가 사용하는 실제 브라우저임에도 불구하고, Facebook 인앱 브라우저에 전체 Ember 애플리케이션 대신 정적 크롤러 레이아웃을 제공합니다.
이것이 실제로 일어나고 있는지 확인하려면 nginx 액세스 로그에서 해당 브라우저의 요청을 확인하고, 응답 페이로드 크기가 정상적인 경우(전체 토픽 페이지의 경우 약 35KB)보다 현저히 작다는 것(보통 약 5KB)을 기록하면 됩니다.
해결 방법
MetaIAB를 crawler_check_bypass_agents 사이트 설정에 추가하세요. 이 설정은 크롤러 목록에 해당하더라도 크롤러 처리에서 제외할 사용자 에이전트를 지정하기 위해 특별히 설계되었습니다.
참고: crawler_check_bypass_agents는 숨겨진 사이트 설정이며 표준 관리자 UI에 표시되지 않습니다. 따라서 Rails 콘솔이 필요합니다.
Rails 콘솔을 통한 방법
SiteSetting.crawler_check_bypass_agents = "MetaIAB"
설정에 이미 값이 있는 경우(예: cubot), 파이프 구분자를 사용하여 추가하세요:
ruby
SiteSetting.crawler_check_bypass_agents = "cubot|MetaIAB"
변경 사항은 즉시 적용되며 재시작이 필요하지 않습니다.
왜 이것이 작동하는가
CrawlerDetection.crawler? 메서드는 세 가지 설정을 조합하여 사용합니다:
non_crawler_user_agents— UA가 이 목록과 일치하면 실제 브라우저일 수 있음crawler_user_agents— 이 목록에도 일치하면 크롤러로 처리됨crawler_check_bypass_agents— 이 목록과 일치하면 크롤러 처리에서 무조건 제외됨
Facebook 인앱 브라우저의 UA에는 non_crawler_user_agents와 일치하는 Safari가 포함되어 있습니다. 또한 crawler_user_agents와 일치하는 facebook도 포함되어 있습니다. Facebook 인앱 브라우저 UA에만 고유한 문자열인 MetaIAB를 crawler_check_bypass_agents에 추가하면 Discourse가 해당 브라우저에 전체 애플리케이션을 제공하도록 됩니다.
왜 Android와 iPad에는 영향이 없는가
- Android: Android의 Facebook 인앱 브라우저는
facebook을 포함하지 않는 다른 사용자 에이전트를 전송하므로 크롤러 감지를 문제없이 통과합니다. - iPad: iPad의 Facebook 인앱 브라우저도 크롤러 레이아웃을 트리거하지만, iPad는 넓은
window.innerWidth(약 1180px)를 보고하므로 Discourse가 데스크톱 레이아웃을 제공합니다. 이 레이아웃은 우연히도 적절하게 렌더링됩니다. 반면, iPhone의 좁은 뷰포트(약 414px)는 모바일 레이아웃을 트리거하며, 크롤러 모드에서는 완전히 기능이 작동하지 않습니다.
추가 참고: meta-webindexer 폭주
별개로, Facebook의 웹 인덱서(meta-webindexer/1.1)가 사이트로 매우 높은 볼륨의 요청(시간당 수천 건에 달할 수 있음)을 보낼 수 있으며, 이 요청들은 모두 홈페이지를 대상으로 합니다. meta-externalagent(OG 링크 미리보기 처리를 담당하므로 차단 해제 상태로 유지해야 함)와 달리, meta-webindexer는 대부분의 Discourse 설치 환경에서 유용한 목적을 수행하지 않는 것으로 보입니다.
로그에서 이 트래픽을 관찰한다면, 봇 차단 구성에 추가하여 nginx 수준에서 차단할 수 있습니다:
"~*meta-webindexer" 1;
meta-externalagent는 Facebook에서 링크가 공유될 때 OG 메타데이터를 수집하는 역할을 하므로 허용 상태로 유지해야 합니다.