문제 설명
최근 포럼에서 이미지 표시에 문제가 발생하고 있으며, 구체적으로 다음과 같습니다:
- 이미지 섬네일(미리보기)이 올바르게 표시되지 않습니다.
- 이미지를 클릭하면 전체 크기 이미지가 올바르게 표시됩니다.
- 브라우저의 개발자 도구에서 잘못된 이미지 URL이 표시됩니다.
조사 결과, 문제의 근본 원인은 이미지 URL의 잘못된 도메인 이름임이 밝혀졌습니다:
- 올바른 URL:
https://store.starorigin.cc/optimized/1X/[imageID].jpeg - 잘못된 URL:
https://info.7a4081a2d83d3f43fe6b1be1c926fd1c.r2.cloudflarestorage.com/optimized/1X/[imageID].jpeg
시스템이 설정된 CDN 도메인 대신 원본 R2 버킷의 잘못된 도메인을 사용하고 있습니다.
기술 분석
이것은 Cloudflare R2에 저장된 이미지를 처리할 때 Discourse에서 발생하는 알려진 문제입니다. s3_cdn_url이 설정되어 있는 경우에도, Discourse는 최적화된 이미지(예: 섬네일)를 생성할 때 CDN URL 대신 원본 저장소 URL을 사용할 수 있습니다.
이것은 다음과 같은 요소와 관련이 있을 수 있습니다:
- Discourse 버전
- S3 호환 저장소의 구성
OptimizedImage테이블에 URL이 저장되는 방식
해결책
가장 간단하고 효과적인 해결책은 클라이언트 측 수리를 위해 Discourse 테마 컴포넌트를 사용하는 것입니다. 이것은 데이터베이스 작업이나 서버 구성 변경을 필요로 하지 않습니다. 브라우저에서 잘못된 URL을 올바른 URL로 자동으로 대체하는 짧은 JavaScript 코드 스니펫을 추가하는 것만 포함됩니다.
테마 컴포넌트 코드
import { apiInitializer } from "discourse/lib/api";
export default apiInitializer("0.11.1", (api) => {
// Fix already loaded images
function fixImageUrls() {
const badDomain = "info.7a4081a2d83d3f43fe6b1be1c926fd1c.r2.cloudflarestorage.com";
const goodDomain = "store.starorigin.cc";
// Fix regular images
document.querySelectorAll(`img[src*="${badDomain}"]`).forEach(img => {
img.src = img.src.replace(badDomain, goodDomain);
});
// Fix lazy-loaded images
document.querySelectorAll(`img[data-src*="${badDomain}"]`).forEach(img => {
img.setAttribute('data-src', img.getAttribute('data-src').replace(badDomain, goodDomain));
});
// Fix background images
document.querySelectorAll('[style*="background"]').forEach(el => {
if (el.style.backgroundImage && el.style.backgroundImage.includes(badDomain)) {
el.style.backgroundImage = el.style.backgroundImage.replace(badDomain, goodDomain);
}
});
// Fix various other potential attributes
['srcset', 'data-large-src', 'data-small-src', 'data-download-href'].forEach(attr => {
document.querySelectorAll(`[${attr}*="${badDomain}"]`).forEach(el => {
el.setAttribute(attr, el.getAttribute(attr).replace(badDomain, goodDomain));
});
});
}
// Fix images in the editor
api.decorateCooked($elem => {
fixImageUrls();
}, { id: 'fix-r2-image-urls' });
// Fix after initial load
api.onPageChange(() => {
fixImageUrls();
});
// Handle dynamically loaded content
const observer = new MutationObserver(mutations => {
fixImageUrls();
});
// Start observing after the DOM is loaded
if (document.readyState === "loading") {
document.addEventListener('DOMContentLoaded', () => {
fixImageUrls();
startObserver();
});
} else {
fixImageUrls();
startObserver();
}
function startObserver() {
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['src', 'data-src', 'srcset', 'style']
});
}
});
코드 작동 원리
이 코드는 다음 작업을 수행합니다:
- 포괄적 감지: 잘못된 도메인을 포함하는 모든 이미지 URL을 찾습니다.
- 다양한 요소 처리: 다양한 이미지 요소와 속성(img 태그, 지연 로드 이미지, 배경 이미지 등)을 처리합니다.
- 동적 모니터링:
MutationObserver를 사용하여 페이지 변경 사항을 모니터링함으로써 동적으로 로드된 콘텐츠도 수정되도록 보장합니다. - Discourse 통합: 다양한 특수 시나리오를 처리하기 위해 Discourse API와 통합됩니다.
설치 단계
- Discourse 관리자 계정에 로그인합니다.
- 관리자 > 사용자 정의 > 테마 컴포넌트로 이동합니다.
- 새로 만들기 버튼을 클릭합니다.
- 새 컴포넌트 만들기 옵션을 선택합니다.
- 이름을 “Fix R2 Image URLs”(또는 원하는 이름)으로 지정합니다.
- “Javascript” 탭에서 위의 코드를 붙여넣습니다.
- 생성 버튼을 클릭합니다.
- 활성화 버튼을 클릭하고 적용할 테마를 선택합니다(보통 “기본값”).
검증
설치 후:
- 포럼 페이지를 새로고침합니다.
- 이미지를 포함하는 게시물을 확인합니다.
- 섬네일이 올바르게 표시되는지 확인합니다.
- 브라우저의 개발자 도구를 사용하여 이미지 요청이 모두 CDN 도메인을 가리키는지 확인합니다.
클라이언트 측 해결책은 특히 직접적인 서버 액세스가 제한된 경우 가장 간단하고 빠르며 위험이 낮은 접근 방식입니다.
결론
이 간단한 테마 컴포넌트는 서버 변경이나 복잡한 구성 없이 Discourse와 Cloudflare R2 스토리지 통합 시 이미지 URL 문제를 효과적으로 해결합니다. 근본 원인을 해결하는 것이 아니라 클라이언트 측에서 문제를 수정하지만, 구현이 쉽고 즉각적인 결과를 제공하며 이상적인 해결책입니다.
귀하의 Discourse 사이트에도 유사한 문제가 발생하고 있다면, 이 해결책을 시도해 보시기 바랍니다.


