글 작성 시, 첨부파일이나 썸네일 이미지는 별도의 관리가 가능하지만,
글 내부에 포함된 이미지를 클라우드 스토리지에 업로드하는 방식은 다소 복잡할 수 있습니다. 특히, 글 내부의 이미지는 HTML 구조로 스타일링 되어 있기 때문에, img 태그를 찾는 작업이 까다로울 수 있습니다. 단순히 HTML에서 태그를 찾는 방식은 유저가 <
나 >
를 포함시킬 수 있기 때문에 태그를 파싱하는 로직을 추가하는 것도 많은 고려사항을 필요로 합니다.
그러다 눈에 들어온 공식문서
https://tiptap.dev/docs/guides/output-json-html
Tiptap 에디터는 작성된 콘텐츠를 JSON 또는 HTML로 변환할 수 있는 메서드를 제공하고 있습니다.
JSON 구조에서는 각 요소들이 명확히 정의된 객체 형태로 관리되므로, 이미지 태그를 찾는 작업이 보다 훨씬 수월해집니다.
같은 글로 비교를 해봅시다
요렇게 에디터에서 작성하고 각각 파싱을 해보면
Tiptap에서 생성된 JSON은 ProseMirror 문서 구조를 따르며, 이는 계층적인 형태로 데이터를 표현합니다. 각 콘텐츠 항목은 type과 attrs 속성을 통해 스타일과 구조를 정의합니다. 예를 들어, 이미지의 경우 type이 "image"로 지정됩니다.
{
"type": "image",
"attrs": {
"src": "image_url",
"alt": "image"
}
}
이런 형태입니다!
이를 통해 객체 내부를 순회하며 type 속성이 "image"인 항목을 찾으면 이미지를 추출할 수 있습니다.
const url = URL.createObjectURL(file);
addFile(file, url);
에디터 내 이미지를 관리하는 함수의 일부입니다. 에디터에서 작성시의 사진의 미리보기 기능을 위해서 로컬 파일을 임시 URL로 변환합니다. 그 임시 url와 파일을 매핑해서 저장해둡니다.
const findFileByUrl = (url: string) => {
const entry = getFiles?.find((item) => item.url === url);
if (entry) return entry.file;
return null;
};
위 함수는 제출할 때, 해당 URL을 추적하여 파일을 찾아 업로드 작업을 진행하는 방식입니다. 만약 file이 없다면, 이는 두 가지 경우가 있을 수 있습니다:
1️⃣ 임시 저장된 파일: 사용자가 작성한 콘텐츠에서 이미 클라우드에 업로드된 이미지를 수정한 경우.
2️⃣ 기존에 업로드된 이미지: 이전에 작성된 콘텐츠에서 이미 클라우드에 업로드된 이미지를 수정하지 않고 그대로 사용하는 경우.
1️⃣ 이미지 URL 확인: json을 순회하면서 img를 발견하면, 해당 이미지가 getFiles 배열에서 존재하는지 찾습니다.
2️⃣ 이미지 업로드: 만약 이미지 파일이 존재하면, presigned URL을 통해 이미지를 클라우드에 업로드합니다.
3️⃣ 업로드된 URL 반영: 업로드가 완료되면, 해당 이미지를 새로운 URL로 src 속성에 업데이트합니다.
4️⃣ 기존 이미지 처리: 이미지 파일이 존재하지 않으면 기존 URL을 그대로 사용합니다.
5️⃣ 이 모든 과정은 각 탭에 대해 반복적으로 수행되며, 최종적으로 모든 이미지는 클라우드 스토리지에 업로드된 URL로 대체됩니다.
6️⃣ 이를 다시 HTML로 변환하여 요청을 보냅니다.