diff --git a/CHANGELOG.md b/CHANGELOG.md index 060f0f97..39a4202f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ - 확장 기능이 화면을 그릴 때, 방문자의 접속 기기 종류처럼 요청마다 달라지는 정보를 화면 구성 데이터에 함께 실어 보낼 수 있는 통로를 마련했습니다. 쇼핑몰의 애플페이가 iOS 기기에서만 표시되도록 하는 데 이 통로가 쓰입니다. - 확장 기능이 특정 요청 경로에만 자기 처리 로직을 끼워 넣을 수 있는 표준 연결 방식을 마련했습니다. 각 확장은 자기가 개입할 대상 경로를 명시해 선언하고, 코어가 요청이 들어올 때 대상에 해당하는 확장 로직만 골라 실행합니다. 이를 통해 쿠키 동의 처리나 결제 입금통보의 발신 서버 확인 같은 기능이 필요한 경로에서만 정확히 동작하도록 정리했습니다. +### Fixed + +- 검색엔진 노출용으로 만들어 내보내는 페이지에 실제로 존재하지 않는 스타일 파일 주소(`/build/assets/app.css`)가 포함되어, 브라우저 콘솔에 404 오류가 남던 문제를 수정했습니다. 이 주소는 화면 표시에 쓰이지 않는 파일을 가리키던 불필요한 참조였으며, 검색엔진 노출용 페이지의 스타일은 템플릿이 제공하는 파일이 그대로 담당하므로 화면에는 영향이 없었습니다. 이제 이 참조를 제거해 오류가 발생하지 않습니다. (#64 @bigmsg 님께서 제보해주셨습니다.) + ## [7.0.4] - 2026-07-14 ### Security diff --git a/app/Seo/SeoRenderer.php b/app/Seo/SeoRenderer.php index cf2ab421..65f78ddb 100644 --- a/app/Seo/SeoRenderer.php +++ b/app/Seo/SeoRenderer.php @@ -464,7 +464,6 @@ class SeoRenderer implements SeoRendererInterface 'googleAnalyticsId' => $meta['googleAnalyticsId'], 'googleVerification' => $meta['googleVerification'], 'naverVerification' => $meta['naverVerification'], - 'cssPath' => $this->getCssPath(), 'stylesheets' => $allStylesheets, 'extraHeadTags' => '', 'extraBodyEnd' => '', @@ -732,28 +731,6 @@ class SeoRenderer implements SeoRendererInterface return $tags; } - /** - * Vite 빌드 CSS 경로를 반환합니다. - * - * @return string CSS 경로 - */ - private function getCssPath(): string - { - $manifestPath = public_path('build/manifest.json'); - if (file_exists($manifestPath)) { - $manifest = json_decode(file_get_contents($manifestPath), true); - foreach ($manifest as $entry) { - if (isset($entry['css'])) { - foreach ($entry['css'] as $css) { - return '/build/'.$css; - } - } - } - } - - return '/build/assets/app.css'; - } - /** * SEO 렌더링용 _global 컨텍스트를 구성합니다. * diff --git a/resources/views/seo-preview.blade.php b/resources/views/seo-preview.blade.php index 2a05bb3e..df6019c9 100644 --- a/resources/views/seo-preview.blade.php +++ b/resources/views/seo-preview.blade.php @@ -4,7 +4,7 @@ 검색엔진 탭·레이아웃·모듈/코어 SEO 환경설정이 "설정/정의한 것의 산출물" 만 렌더한다. 운영 seo.blade.php 와 달리 다음은 SEO 설정 산출물이 아니므로 미포함: - body 컴포넌트 마크업($bodyHtml) — 페이지 본문(검색엔진 탭과 무관) - - CSS($cssPath/$stylesheets) — 에셋 + - CSS($stylesheets) — 에셋 - 시스템 기본 메타(charset/viewport/generatorTag) — SEO 설정과 무관 - Google Analytics 스크립트 — 추적(검색 노출 산출물 아님) - extraHeadTags/extraBodyEnd — 훅 주입 비-SEO 슬롯 diff --git a/resources/views/seo.blade.php b/resources/views/seo.blade.php index 957c135d..926345c3 100644 --- a/resources/views/seo.blade.php +++ b/resources/views/seo.blade.php @@ -27,8 +27,7 @@ {{-- Twitter Card --}} {!! $twitterTags ?? '' !!} - {{-- CSS --}} - + {{-- CSS (템플릿 CSS만 — 코어 app.css 는 사용자 화면에서 미참조하는 Laravel 기본 빌드 파일이라 미포함) --}} @foreach($stylesheets as $stylesheet) @endforeach diff --git a/tests/Feature/Seo/SeoBladeCssTest.php b/tests/Feature/Seo/SeoBladeCssTest.php new file mode 100644 index 00000000..db485ac0 --- /dev/null +++ b/tests/Feature/Seo/SeoBladeCssTest.php @@ -0,0 +1,77 @@ + 'ko', + 'title' => '베이직 오버핏 코튼 티셔츠', + 'titleSuffix' => ' | 코지홈', + 'description' => '사계절 입기 좋은 오버핏 기본 티셔츠', + 'keywords' => '티셔츠,오버핏', + 'canonicalUrl' => 'https://example.com/shop/products/1', + 'hreflangTags' => '', + 'ogTags' => '', + 'twitterTags' => '', + 'jsonLd' => '{"@type":"Product","name":"베이직 오버핏 코튼 티셔츠"}', + 'bodyHtml' => '
', + 'googleAnalyticsId' => '', + 'googleVerification' => '', + 'naverVerification' => '', + 'stylesheets' => [ + '/api/templates/assets/sirsoft-basic/css/components.css', + ], + 'extraHeadTags' => '', + 'extraBodyEnd' => '', + 'generatorTag' => '', + ], $overrides); + } + + private function renderSeo(array $overrides = []): string + { + return View::make('seo', $this->viewData($overrides))->render(); + } + + public function test_봇_HTML에_코어_app_css_고정경로_링크가_없다(): void + { + $out = $this->renderSeo(); + + $this->assertStringNotContainsString('/build/assets/app.css', $out); + $this->assertStringNotContainsString('/build/', $out); + } + + public function test_템플릿_stylesheets는_정상_링크된다(): void + { + $out = $this->renderSeo(); + + $this->assertStringContainsString( + '', + $out, + ); + } + + public function test_cssPath_변수_없이도_예외없이_렌더된다(): void + { + // cssPath 를 뷰 데이터에서 완전히 제거해도 (undefined variable 등) 예외가 없어야 한다. + $out = $this->renderSeo(); + + $this->assertStringContainsString('