에디터 고도화 개발 명세 (FRD)¶
요지¶
공용 에디터(Tiptap)에 이미지·파일·링크 첨부를 더하는 구현을 정리한다. 설계의 핵심은 중복을 없앤 것이다 — 첨부 처리 로직을 한 곳(MediaAssetService/MediaAssetContentResolver)에 모아, 수업노트·Q&A·과제가 각자 만들지 않고 그대로 가져다 쓴다.
상위 PRD¶
기획(첨부 3종 + 기본 서식 + 공용 미디어 연결)은 prd이며, 바뀌면 이 문서도 갱신한다.
기술 접근 · 아키텍처¶
기능 정의¶
이미지 업로드 — 에디터 상단 [이미지] 클릭 또는 드래그&드롭 → 업로드 로딩 → 본문 삽입. 허용: jpg/png/gif/webp, 1개당 5MB(추후 BM 확장). 썸네일 미리보기·가로/세로 크기 조절·글자 정렬. 예외: 용량 초과 알림, 네트워크 오류 재시도.
파일 첨부 — 허용: pdf/docx/pptx/hwp/hwpx/xlsx/zip, 1개당 30MB(추후 BM 확장). 첨부 후 다운로드 링크(아이콘+파일명+용량), 다중 업로드. 예외: 미지원 확장자, 용량 초과.
링크 연결 — Ctrl+K 또는 버튼. 외부 링크 og 미리보기 카드, 링크/표시 문구 개별 편집, 임베드. 예외: 잘못된 URL 형식 경고.
기본 기능 — 말머리/글번호, 들여쓰기(Tab)/내어쓰기(Shift+Tab), 제목 타입(#·##·###), bold(Ctrl+B), 기울임(Ctrl+L).
공통 정책¶
- 작성자·조회 권한자는 이미지/파일 다운로드 가능.
- 비로그인 사용자는 다운로드 불가 → 접근 시 로그인 화면 라우팅, 로그인 후 원래 화면 복귀.
API · 데이터 모델¶
미디어 연결 구조 (BE)¶
MediaAssetService / MediaAssetContentResolver로 첨부를 공통 처리. 적용 리소스: 수업노트(TeachingNote — teaching-note), Q&A(qna), 과제(과제관리).
- TargetType에 리소스 타입 추가.
- 생성/수정: 요청 DTO에
mediaIds추가 → 서비스에서mediaAssetService.attachMediaAssets(리소스 id, mediaId 리스트, targetType)호출. - 본문 저장: Tiptap content에 첨부를
media://<mediaId>참조로 저장(원본 URL 비저장). - 상세 조회: 응답 DTO에
ResolvedContent추가 →mediaAssetContentResolver.resolveMediaInContent(원본)로media://참조를 S3 presignedUrl·만료시간이 채워진 콘텐츠로 치환 반환.
의존성 · 영향 범위¶
수업노트(teaching-note)·Q&A(qna)·과제(과제관리)가 첨부를 공유하므로, MediaAsset이나 TargetType을 바꾸면 이 셋 모두에 영향이 간다. 실제 파일은 S3 presignedUrl로 내려주며, 버킷명·시크릿은 환경변수로만 둔다.
테스트 계획¶
용량·확장자·권한 경계가 핵심이라 케이스를 표로 정리해 둔다. 공통 전략은 qa-playbook을 따른다.
| 구분 | 시나리오 | 기대 결과 |
|---|---|---|
| 이미지 | 5MB 이하 PNG | 정상 삽입 |
| 이미지 | 초과 용량 | "용량 초과" 알림 |
| 파일 | 30MB 초과 | 삽입 실패, "용량 초과" 알림 |
| 파일 | .hwp |
정상 삽입, 다운로드 링크 표시 |
| 링크 | 유효하지 않은 URL | "잘못된 주소입니다" 경고 |
| 비로그인 | 첨부파일 클릭 | 로그인 화면 → 원래 화면 복귀 |
작업 분해¶
완료 추적은 GitHub 이슈에서 한다.