# 콘텐츠 시스템

## 데이터와 게시판

Tenant의 Board가 게시판 설정과 접근 정책을 갖고, Post가 글 본문·상태·SEO·발행 시각을 갖는다. Board type/skin의 실제 값과 렌더링 분기는 `Tenant\PostController`, `PostListingService`, board model 및 `resources/views/tenant`를 기준으로 확인한다. Platform에도 별도 Board/Post 모델과 관리 흐름이 있다.

## Pages

`pages` 게시판의 `home` 글은 tenant home 렌더링용 내부 콘텐츠다. 외부 URL과 sitemap canonical을 혼동하지 않는다. DB HTML에 Tailwind 클래스를 저장할 수 있어 safelist가 필요하며, 현재 위치는 `resources/css/pages-tailwind-safelist.html`과 `resources/css/app.css`다.

## 편집과 이미지

Post form은 `resources/views/components/posts/form.blade.php`를 공통으로 사용한다. TipTap은 `resources/js/tiptap-editor.js`가 `#editor`/`#hidden-input`을 연결하고, HTML 콘텐츠는 서버 검증·정리 후 렌더링된다. 업로드 이미지는 tenant별 파일 경로로 저장하고 `PostImage`, 본문 참조, thumbnail을 함께 관리한다. 고아 파일 정리는 `qpost:tenant-cleanup-orphan-images` 명령을 사용한다.

## 발행과 sitemap

공개 여부, 발행 상태, `published_at` 예약 시각, 비밀번호/접근 제한은 게시글 노출과 sitemap을 각각 검증한다. 예약 글은 시간이 되기 전 공개 목록·검색·sitemap에서 제외되어야 한다. 관련 구현은 Tenant Post controller와 `app/Core/Sitemap` generator들이다.

## AI

Tenant `PostController@aiWrite`가 `AiPlanResolver`, `AiManager`, 가격/credit service를 통해 요청을 처리한다. OpenAI 등 provider는 `AiProviderInterface`로 추상화되고, 결과 계약은 title/content/meta_description/tags/meta_keywords다. AI 이미지 생성은 별도 manager/provider와 공통 Credit을 사용한다. UI는 `tenant-ai-writing.js`, `tenant-ai-image.js`의 동적 import로 초기화된다.

## 기능 변경 체크

데이터 모델/tenant migration → query/service → controller route/권한 → Blade 렌더링 → sitemap/search/SEO → Feature/Unit 테스트 순으로 영향을 확인한다. Central 데이터나 Credit을 tenant DB에 복사하는 방식은 사용하지 않는다.
