대표 이미지 전용 카드 썸네일로 정리

This commit is contained in:
2026-06-08 15:54:39 +09:00
parent eb4018f92c
commit 806b181d1f
18 changed files with 236 additions and 147 deletions

View File

@@ -89,13 +89,14 @@
- 공유 모달은 게시물 썸네일/제목/요약 미리보기, X/Bluesky/Facebook/LinkedIn/Email 링크, 링크 복사 액션을 제공한다.
- 공유·SEO 설명은 SEO 설명이 있으면 우선 사용하고, 없으면 게시물 요약, 요약도 없으면 본문에서 마크다운 기호를 제거한 짧은 텍스트를 사용한다.
- 홈 Latest·게시물 목록·태그 목록의 카드 설명도 동일하게 요약이 비어 있으면 본문에서 `createPostSummary`로 짧은 텍스트를 만든다. 목록용 설명은 문자열에 수동 말줄임을 붙이지 않고 `post-summary-clamp` 전용 클래스가 실제 표시 줄 끝에서 말줄임을 처리한다.
- 게시물 상세 제목 아래 대표 이미지는 관리자 글쓰기의 `본문 상단 대표 이미지` 옵션이 켜진 게시물에서만 표시한다. 대표 이미지는 목록·공유용으로는 계속 사용할 수 있으며, 본문 상단 표시 기본값은 꺼짐이다.
### 게시물 업로드 이미지 썸네일
- 관리자 미디어 업로드 API는 JPG·PNG·WebP 파일을 `/uploads/posts/YYYY/MM/원본파일`에 저장한 뒤, 목록 카드용 WebP 썸네일을 `/uploads/posts/YYYY/MM/thumbs/원본파일명-card.webp` 함께 생성한다.
- 관리자 미디어 업로드 API는 JPG·PNG·WebP 파일을 `/uploads/posts/YYYY/MM/원본파일`에 저장한다. 업로드만으로는 카드 썸네일을 만들지 않고, 해당 이미지가 게시물 대표 이미지로 저장될 때 목록 카드용 WebP 썸네일을 `/uploads/posts/YYYY/MM/thumbs/원본파일명-card.webp`에 생성한다.
- 카드 썸네일은 640×360 기준 `cover` 리사이즈와 WebP 품질 82를 사용한다. GIF·동영상·문서 파일은 썸네일을 자동 생성하지 않는다.
- 공개 게시물 응답은 원본 대표 이미지 `featuredImage`를 유지하고, 대응 썸네일 파일이 실제로 존재할 때만 `featuredImageThumbnail`을 추가한다.
- 기존 업로드 이미지는 `npm run images:backfill-post-thumbnails``public/uploads/posts` 하위 파일을 스캔해 누락된 카드 썸네일을 생성한다.
- 기존 대표 이미지는 `npm run images:backfill-post-thumbnails`게시물 대표 이미지 URL만 스캔해 누락된 카드 썸네일을 생성한다. 관리자 미디어의 원본 이미지 상세에서도 카드 썸네일을 개별 생성·재생성할 수 있다.
### 공개 목록·상세의 발행일 표시
@@ -289,7 +290,8 @@ components/content/
| slug | String | URL 슬러그 |
| content | Text | Markdown 콘텐츠 |
| excerpt | String | 요약 |
| featured_image | String nullable | 대표 이미지 |
| featured_image | String nullable | 목록·공유용 대표 이미지 |
| show_featured_image | Boolean | 게시물 상세 제목 아래 대표 이미지 표시 여부 |
| is_featured | Boolean | 홈 Featured 및 목록 번개 표시용 추천 글 여부 |
| seo_title | String | SEO 제목 |
| seo_description | String | SEO 설명 |
@@ -301,7 +303,7 @@ components/content/
| created_at | DateTime | 생성일 |
| updated_at | DateTime | 수정일 |
> API 응답의 게시물 객체는 원본 대표 이미지 `featuredImage`, 목록용 카드 썸네일 `featuredImageThumbnail`, `isFeatured`, `commentCount`를 함께 반환한다. `commentCount`는 `published` 상태 댓글 수를 기준으로 한다.
> API 응답의 게시물 객체는 원본 대표 이미지 `featuredImage`, 상세 상단 표시 여부 `showFeaturedImage`, 목록용 카드 썸네일 `featuredImageThumbnail`, `isFeatured`, `commentCount`를 함께 반환한다. `commentCount`는 `published` 상태 댓글 수를 기준으로 한다.
> 공개 게시물 목록·상세는 `published` 상태만 기본 노출하며, `members` 상태는 VIP 이상 등급(`vip`/`admin`/`owner`) 회원에게만 노출한다. `private`와 `draft`는 공개 화면에서 노출하지 않는다.
### PostExportJobs / PostExportFiles
@@ -580,6 +582,7 @@ components/content/
- `PUT /admin/api/pages/:id` - 고정 페이지 수정
- `DELETE /admin/api/pages/:id` - 고정 페이지 삭제
- `GET /admin/api/media` - 업로드 미디어 목록(게시물용 이미지와 회원 아바타 포함; 회원 아바타에는 `avatarOwner` 요약이 붙을 수 있음)
- `POST /admin/api/media/thumbnail` - 게시물 대표 이미지 원본 URL에서 목록 카드용 썸네일을 생성 또는 재생성
- `PUT /admin/api/media` - 업로드 미디어 파일명 변경 또는 단일/복수 미디어 폴더 변경(회원 아바타 URL은 논리 폴더 `썸네일`만 허용, 일반 미디어를 `썸네일`로 옮기는 것은 거부; 썸네일 파일명 변경은 `users.avatar_url`이 해당 URL을 참조할 때만 거부)
- `DELETE /admin/api/media` - 업로드 미디어 삭제(게시물·페이지에서 사용 중이면 거부; `/members/avatars/` URL은 `users.avatar_url`이 해당 URL을 참조할 때만 거부)
- `GET /admin/api/media-folders` - 미디어 폴더 목록