사이트맵을 리소스 단위로 영속화(sitemap_urls)해 진정한 증분 갱신과 도메인 재쿼리 없는 파일 재작성을 구현했다. 리소스 공개/비공개/삭제 시 해당 항목만 색인이 갱신되고, 관리자=full·스케줄러=auto·리소스 변경=증분으로 동작한다. - sitemap_urls 마이그레이션 + SitemapUrl 모델. loc(2048) 를 unique 에 직접 넣으면 InnoDB 키 길이를 초과하므로 loc_hash(sha256) 컬럼을 identity 로 사용 - SitemapUrlRepository(멱등 upsert / remove / 스트리밍) + SitemapIndexer (+ 제3자용 sitemap.index.collect_for_resource 필터 훅) - 4 리스너 재배선: 공개→색인 / 비공개·삭제→색인 해제 + 재생성 잡 디바운스 디스패치. 3 기여자가 resource_type/resource_id 를 함께 emit 해 전체·증분 identity 를 일치 - 재생성 모드를 SitemapGenerationMode Backed Enum 으로 통일(Command→Job→Manager) - seo:generate-sitemap 에 --rebuild / --mode 옵션 추가
57 lines
2.2 KiB
PHP
57 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace App\Seo;
|
|
|
|
use App\Contracts\Extension\StorageInterface;
|
|
use App\Contracts\Repositories\SitemapUrlRepositoryInterface;
|
|
use App\Extension\Storage\CoreStorageDriver;
|
|
use App\Repositories\SitemapUrlRepository;
|
|
use App\Seo\Contracts\SeoCacheManagerInterface;
|
|
use App\Seo\Contracts\SeoRendererInterface;
|
|
use Illuminate\Support\ServiceProvider;
|
|
|
|
class SeoServiceProvider extends ServiceProvider
|
|
{
|
|
/**
|
|
* 서비스 컨테이너 바인딩을 등록합니다.
|
|
*/
|
|
public function register(): void
|
|
{
|
|
// 인터페이스 → 구현체 바인딩
|
|
$this->app->singleton(SeoCacheManagerInterface::class, SeoCacheManager::class);
|
|
$this->app->singleton(SeoRendererInterface::class, SeoRenderer::class);
|
|
$this->app->singleton(SitemapUrlRepositoryInterface::class, SitemapUrlRepository::class);
|
|
|
|
// 싱글톤 등록
|
|
$this->app->singleton(SeoCacheRegenerator::class);
|
|
$this->app->singleton(SeoInvalidationRegistry::class);
|
|
$this->app->singleton(BotDetector::class);
|
|
$this->app->singleton(ExpressionEvaluator::class);
|
|
$this->app->singleton(ComponentHtmlMapper::class);
|
|
$this->app->singleton(DataSourceResolver::class);
|
|
$this->app->singleton(TemplateRouteResolver::class);
|
|
$this->app->singleton(SeoMetaResolver::class);
|
|
$this->app->singleton(SitemapGenerator::class);
|
|
$this->app->singleton(SeoConfigMerger::class);
|
|
$this->app->singleton(SitemapFileStore::class);
|
|
$this->app->singleton(SitemapIndexer::class);
|
|
|
|
// Sitemap 파일 입출력은 비공개 디스크(local = storage/app/private, serve=false)를 사용합니다.
|
|
// public/storage 심볼릭 링크에 의존하지 않고 컨트롤러 스트리밍으로 서빙합니다.
|
|
foreach ([SitemapManager::class, SitemapFileStore::class] as $sitemapConsumer) {
|
|
$this->app->when($sitemapConsumer)
|
|
->needs(StorageInterface::class)
|
|
->give(fn () => new CoreStorageDriver('local'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 서비스 부트스트랩을 수행합니다.
|
|
*/
|
|
public function boot(): void
|
|
{
|
|
// SeoMiddleware는 bootstrap/app.php에서 별칭 등록
|
|
// routes/web.php에서 라우트 그룹에 부착
|
|
}
|
|
}
|