7.0.7 페이로드 전수 검증에서 발견된 error 4건·warn 14건을 릴리즈 전에 처리했다. 미출시 분량의 자체 결함(회원 통합검색 500, 관리자 스코프 403 의 500 위장 등)이므로 페이로드에 합류시키고, 출시 대상 26개 CHANGELOG 의 버전 섹션 날짜를 2026-08-18 로 정렬했다. - 통합검색 import 복원 + 이커머스 관리자 typed 403 catch 대칭(테스트 동반) - admin 판정 스니핑 사설 사본 전수 수렴(BoardResource) + 조건 스캔 테스트 - 스케줄 인터프리터 변형 표기(확장자·버전 접미사) 정규화 차단 - ckeditor5 참조 판정 배치화·fail-safe, 결제 플러그인 진단 페이로드 대칭 - 템플릿 다크 대비·상태 Select value-제어 + --production 재빌드 - Upgrade_7_0_7 잔존 중복 색인 정리 스텝, API 문서·i18n(ko/en/ja) 동기
12 KiB
12 KiB
Uploads API 레퍼런스
소유: plugin
sirsoft-ckeditor5· 생성:php artisan api:docgen(실측 기반). @generated 블록은 재생성 시 갱신되며, 사람이 작성한 설명은 보존됩니다.
TL;DR (5초 요약)
1. 이 문서는 에디터 업로드 이미지 관리(조회·삭제) 엔드포인트 레퍼런스입니다
2. 각 엔드포인트: 메서드/URI/권한 + 요청 파라미터 표 + 요청 예시(raw HTTP) + 응답 필드 표 + 응답 예시(envelope)
3. 조회(uploads.read)와 삭제(uploads.delete)는 별도 권한입니다 — 삭제는 파일을 실제로 파기합니다
4. 참조 상태(referenced)는 저장 컬럼이 아니라 조회 시점에 판정한 값입니다
5. 갱신: 코드 변경 후 php artisan api:docgen 재실행
GET /api/plugins/sirsoft-ckeditor5/admin/uploads
- 라우트명:
api.plugins.sirsoft-ckeditor5.admin.uploads.index - 컨트롤러:
Plugins\Sirsoft\Ckeditor5\Http\Controllers\Admin\ImageUploadAdminController@index - 인증/권한:
auth:sanctum,permission:admin,sirsoft-ckeditor5.uploads.read
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| page | query | integer | 아니오 | min 1 | 페이지 번호 (기본 1) |
| per_page | query | integer | 아니오 | 1 ~ 100 | 페이지 크기 (기본 20). 참조 판정을 페이지 단위로 수행하므로 이 값이 곧 판정 비용의 상한이다. |
| search | query | string | 아니오 | max 255 | 원본 파일명 또는 해시 부분 일치 |
| referenced | query | string | 아니오 | all, referenced, unreferenced |
참조 상태 필터 (기본 all) |
| date_from | query | date | 아니오 | — | 업로드 시작일 (그날 00:00:00 포함) |
| date_to | query | date | 아니오 | — | 업로드 종료일 (그날 23:59:59 포함) |
| sort_by | query | string | 아니오 | created_at, file_size, original_name |
정렬 컬럼 (기본 created_at). 목록 밖 컬럼은 422 |
| sort_order | query | string | 아니오 | asc, desc |
정렬 방향 (기본 desc) |
요청 예시
GET /api/plugins/sirsoft-ckeditor5/admin/uploads?referenced=unreferenced&per_page=20 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| data[].id | integer | 12 |
업로드 기록 ID (삭제 요청의 대상 식별자) |
| data[].hash | string | a1b2c3d4e5f6 |
URL용 고유 해시 12자리 hex. 본문에 API 폴백형 URL 로 삽입될 때 이 값이 들어간다 |
| data[].original_name | string | banner.png |
업로드 당시 원본 파일명 |
| data[].file_size | integer | 78310 |
파일 크기 (bytes) |
| data[].mime_type | string | image/png |
MIME 타입 |
| data[].uploaded_by | integer|null | 1 |
업로드한 사용자 ID (탈퇴·미상이면 null) |
| data[].uploader_name | string|null | 관리자 |
업로더 표시명. 관계가 로드된 경우에만 채워진다 |
| data[].created_at | string | 2026-08-14 19:20:11 |
업로드 일시 (요청자 시간대 기준 포맷) |
| data[].download_url | string | /api/plugins/sirsoft-ckeditor5/images/a1b2c3d4e5f6 |
이미지 서빙 URL. 공개 자산 디스크가 직접 URL 을 지원하면 CDN 주소가 반환된다 |
| data[].referenced | boolean | false |
조회 시점 판정값(저장 컬럼 아님). 등록된 참조 소스 본문에 hash 또는 저장 파일명이 등장하면 true. 판정 불가 행은 안전 방향인 true 로 본다 |
| pagination.current_page | integer | 1 |
현재 페이지 |
| pagination.last_page | integer | 1 |
마지막 페이지 |
| pagination.per_page | integer | 20 |
페이지 크기 |
| pagination.total | integer | 3 |
총 건수 |
| pagination.from | integer|null | 1 |
현재 페이지 첫 항목 순번 (비어 있으면 null) |
| pagination.to | integer|null | 3 |
현재 페이지 마지막 항목 순번 (비어 있으면 null) |
| meta.scan_limited | boolean | false |
참조 상태 필터가 스캔 윈도우 상한에 걸렸는지. true 면 그보다 오래된 이미지는 목록에 포함되지 않는다 |
| meta.scan_window | integer | 500 |
참조 상태 필터가 훑는 최신 업로드 건수 상한 |
| meta.reference_sources_incomplete | boolean | false |
설치돼 있으나 비활성인 모듈이 있어 참조 판정이 불완전할 수 있는지. true 면 그 모듈 콘텐츠에서만 쓰이는 이미지가 「미참조」로 오판될 수 있으므로 화면은 경고를 표시해야 한다 |
응답 예시
{
"success": true,
"message": "요청이 성공적으로 처리되었습니다.",
"data": {
"data": [
{
"id": 12,
"hash": "a1b2c3d4e5f6",
"original_name": "banner.png",
"file_size": 78310,
"mime_type": "image/png",
"uploaded_by": 1,
"uploader_name": "관리자",
"created_at": "2026-08-14 19:20:11",
"download_url": "/api/plugins/sirsoft-ckeditor5/images/a1b2c3d4e5f6",
"referenced": false
}
],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 20,
"total": 1,
"from": 1,
"to": 1
},
"meta": {
"scan_limited": false,
"scan_window": 500,
"reference_sources_incomplete": false
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | sirsoft-ckeditor5.uploads.read 권한이 없는 경우 |
| 422 | Unprocessable Entity | 허용 목록 밖 sort_by/sort_order/referenced, per_page 범위 초과, 날짜 형식 오류 |
설명
에디터로 업로드된 이미지 목록을 관리 화면에 제공하는 엔드포인트다.
- 참조 상태는 저장하지 않는다. 참조 관계는 콘텐츠가 편집될 때마다 바뀌므로 스냅샷을 저장하면 "저장 당시엔 미참조였던" 이미지를 이후에 오판 삭제할 수 있다. 대신 판정 비용에 상한을 둔다 — 기본 목록은 현재 페이지(≤100행)만 판정하고, 참조 상태 필터를 쓸 때만 최신
meta.scan_window건을 훑는다. meta.scan_limited가 true 면 목록이 전수가 아니다. 화면은 이 값을 근거로 "최근 N건 기준" 안내를 표시해야 한다. 이 값을 무시하면 운영자가 "미참조 이미지가 이게 전부" 로 오해한다.- 판정 토큰은
hash와 저장 파일명 둘 다이다. 본문에 박히는 URL 이 API 폴백형(hash 포함)과 디스크 직접 URL(저장 파일명 포함) 두 형태이기 때문이며, 한쪽만 검사하면 다른 형태로 저장된 이미지를 미참조로 오판한다.
DELETE /api/plugins/sirsoft-ckeditor5/admin/uploads/{id}
- 라우트명:
api.plugins.sirsoft-ckeditor5.admin.uploads.destroy - 컨트롤러:
Plugins\Sirsoft\Ckeditor5\Http\Controllers\Admin\ImageUploadAdminController@destroy - 인증/권한:
auth:sanctum,permission:admin,sirsoft-ckeditor5.uploads.delete
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| id | path | integer | 예 | 숫자만 | 삭제할 업로드 기록 ID |
요청 예시
DELETE /api/plugins/sirsoft-ckeditor5/admin/uploads/12 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
성공 시 data 는 null 이며, 결과는 message 로만 전달된다.
응답 예시
{
"success": true,
"message": "이미지를 삭제했습니다.",
"data": null
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | sirsoft-ckeditor5.uploads.delete 권한이 없는 경우 (조회 권한만으로는 삭제 불가) |
| 404 | Not Found | 해당 ID 의 업로드 기록이 없는 경우 |
| 500 | Internal Server Error | 물리 파일이 존재하는데 삭제에 실패한 경우 — 기록은 보존되며 다음 시도에서 재시도할 수 있다 |
설명
업로드 이미지 1건을 파일과 기록까지 삭제한다.
- 삭제 순서는 파일 먼저, 기록 나중이다. 반대로 하면 기록이 사라진 파일은 어떤 경로로도 다시 찾을 수 없어 영구 고아가 된다.
- 파일이 이미 없는 행은 고아 기록으로 보고 기록만 지운다. 그러지 않으면 매 회차 같은 행을 재시도하는 루프가 된다.
- 행마다
storage_disk가 다를 수 있으므로 삭제는 그 행에 기록된 디스크를 향해 수행된다(디스크 전환 이후 혼재 대응). - 이 경로는 정리 커맨드(
sirsoft-ckeditor5:prune-unused-images)와 같은 삭제 구현을 공유한다 — 화면 삭제와 자동 정리의 동작이 갈리지 않게 하기 위함이다.
POST /api/plugins/sirsoft-ckeditor5/admin/uploads/bulk-delete
- 라우트명:
api.plugins.sirsoft-ckeditor5.admin.uploads.bulk-delete - 컨트롤러:
Plugins\Sirsoft\Ckeditor5\Http\Controllers\Admin\ImageUploadAdminController@bulkDestroy - 인증/권한:
auth:sanctum,permission:admin,sirsoft-ckeditor5.uploads.delete
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| ids | body | array | 예 | 1 ~ 100개 | 삭제할 업로드 기록 ID 목록 |
| ids.* | body | integer | 예 | 존재하는 업로드 ID | 각 항목은 실재하는 기록이어야 한다 (아니면 422) |
요청 예시
POST /api/plugins/sirsoft-ckeditor5/admin/uploads/bulk-delete HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"ids": [12, 13, 14]
}
응답 필드 (data 내부)
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| deleted | integer | 3 |
파일·기록이 함께 삭제된 건수 |
| failed | integer | 0 |
물리 파일 삭제 실패로 기록을 보존한 건수 (다음 시도에서 재시도 가능) |
응답 예시
{
"success": true,
"message": "선택한 이미지 3건을 삭제했습니다.",
"data": {
"deleted": 3,
"failed": 0
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | sirsoft-ckeditor5.uploads.delete 권한이 없는 경우 |
| 422 | Unprocessable Entity | ids 누락/빈 배열/100개 초과, 또는 존재하지 않는 ID 포함 |
| 500 | Internal Server Error | 요청한 전부가 파일 삭제에 실패한 경우 (일부만 실패하면 200 + failed 로 보고) |
설명
관리 화면에서 체크한 이미지를 한 번에 삭제한다.
- 선택 범위는 화면에 보이는 페이지로 한정된다(화면 계약). 검색·필터·페이지 이동으로 목록에서 빠진 행의 선택이 남아 대상에 실리면, 운영자가 보지도 체크하지도 않은 파일이 지워지기 때문이다.
- 일부만 실패한 경우 요청 자체는 성공(200)으로 응답하고
failed로 보고하며, 응답 메시지도 "N건 삭제, M건 실패" 형태(messages.uploads.bulk_partially_deleted)로 실패 사실을 함께 안내한다. 전부 실패한 경우에만 500 이다 — 부분 성공을 실패로 되돌릴 방법이 없기 때문이다.