지금까지는 <textarea> 태그로 단순히 텍스트만 입력 가능했지만, 오늘 이미지 추가 기능을 구현해서 좀 더 완성도 있는 포스팅 기능을 구현하려고 한다.
첫번째로 해야할 것은 <textarea>태그를 이미지를 추가할 수 있는 태그로 변경하는 것.
<textarea>에는 오로지 텍스트만 입력할 수 있으므로, 이미지를 추가할 수 있고 텍스트도 입력할 수 있는 태그를 찾아야한다.
처음 머릿속으로는 <div> 태그안에 <image> 태그를 추가하고, 텍스트들은 <span> 태그로 관리할려고 생각했었다.
근데.. 이러면 좀 이미지를 추가하고, 또 글을 작성하고, 또 이미지를 추가하고 이렇게 하다보면 이렇게 하나하나 DOM에 appendChild() 방식으로 하는 것은, 매우매우 비효율적이라고 생각했다.. 🤔
그래서! 구글링을 했다..🤣
생각보다 여러 사람들이 <textarea> 태그에 이미지를 넣는 방법에 대해 질문이 많았다.
정답은 <div> 태그에 contentEditable 속성을 추가하는 것이었다.
contentEditable 속성을 추가하면 <div> 태그도 마치 <textarea> 태그처럼 텍스트를 입력할 수 있게 변한다.
previewContentRef.current.innerHTML = contentTextareaRef.current.innerHTML;
내부에 따로 value 값으로 요소들이 입력되는 것이 아니라, HTML 태그들로 입력되기 때문에 상태 변화는 innerHTML로 체크한다.

<div> 태그를 찍어보면 위와 같은 형태로 작성된다.
저 안에 이미지를 추가하면 자식 요소로<img> 태그가 추가된다.
참고한 사이트 : https://dev-bak.tistory.com/16
<div>태그에 여러 텍스트 스타일 적용과 이미지 추가에 대해 자세하게 설명하고 있다.

작동 영상을 보면 이미지가 정상적으로 업로드 되고, 텍스트 역시 정상적으로 입력할 수 있는 것을 볼 수 있다.
<div> 태그를 이용해서 이미지, 텍스트가 있는 게시글 객체 만들기는 완성을 했는데..
이 게시글을 어떻게 저장하고, 또 어떻게 보여줘야 할 까?
그냥 무작정 기존에 포스트 정보를 담던
const newPost = {
userID: userID,
id: postList.length.toString(),
title: title,
content: content,
date: today.toLocaleDateString(),
likesCount: 0,
};
로 게시글 객체를 저장하면, 당연히 오류가 발생한다.
게시글 정보를 넘겨주는게 아니라 그냥 객체 자체를 넘겨주기 때문에 {content}로 출력하면 [object] 로 출력되거나, 아예 컴파일 조차 되지 않았다.
그래서 <div> 객체 자체를 string으로 변환하고, 화면에 띄워줄 때 다시 html 형태로 변환 해주면 정상적으로 객체를 넘겨 받을 수 있었다.
먼저 DOM 객체를 string 형태로 저장하려면, 그냥 outerHTML 속성을 사용하면 된다. 쉽네..?
const handleAddPost = () => {
const today = new Date();
const title = titleTextareaRef.current.value;
const content = previewContentRef.current.outerHTML;
const newPost = {
userID: userID,
id: postList.length.toString(),
title: title,
content: content,
date: today.toLocaleDateString(),
likesCount: 0,
};
setPostList([...postList, newPost]);
const headerContainer = document.querySelector(".headerContainer");
headerContainer.classList.remove("hide");
};
이렇게 넘겨주게 되면,
이렇게 HTML 코드가 string 형태로 넘겨지게 된다.
그러면 이제 string으로 받은 HTML 코드를 다시 DOM 객체로 만들어주는 방법은 무엇일까?
그 방법은 DOMParser를 사용하는 것이다.
DOMParser
DOMParser는 String 형태의 XML 또는 HTML 코드를 DOM 문서로 분석, 구조화 할 수 있는 기반을 제공한다.
const trendingPosts = trendingPostList.map((item, index) => {
const contentElement = new DOMParser()
.parseFromString(item.content, "text/html")
.querySelector("div");
});
마지막에 .querySelector("div")를 붙여준 이유는, DOMParser를 이용해 html 문자열을 파싱하면 자동으로 <head>, <body>등의 요소가 생성된다.
그래서 우리가 필요한 <div> 태그만 선택해서 작업하기 편하게 선언했다.
정상적으로 HTML 코드로 변환했으니, 이제 내가 필요한 위치에 이 객체를 추가하기만 하면 될 것 같았다.
그래서, 그냥
<Link
to={`/post/${item.userID}/${item.id}`}
key={index}
className="postBox"
>
<div className="innerBox">
<span className="title">{item.title}</span>
<span className="content">{contentElement}</span>
</div>
<span className="date">{item.date}</span>
<section className="infoSection">
<div>
<div className="userIcon" />
<span className="userID">by {item.userID}</span>
</div>
<div className="likesCount">
<FontAwesomeIcon icon={faHeart} />
{item.likesCount}
</div>
</section>
</Link>
같이 코드를 작성했는데.. 안되더라.

이 에러는 React 상에서 객체를 직접 렌더링하는 것이 불가능하다는 말이다.
따라서, 객체를 React에서 정상적으로 렌더링 할 수 있게 JSX로 렌더링하여 반환해야 했다.
let thumbnailJSX;
try {
const thumbnail = contentElement.querySelector("img");
thumbnailJSX = React.createElement("div", {
dangerouslySetInnerHTML: {
__html: thumbnail.outerHTML,
},
});
} catch (err) {
thumbnailJSX = React.createElement("div");
}
const firstContent = Array.from(contentElement.childNodes).find(
(item) => item.nodeName === "#text"
).textContent;
가장 먼저 썸네일로 보여질 <img> 태그를 찾아 createElement() 메소드를 사용하여 <div> 태그를 생성한다.
그리고, 가장 먼저 입력한 텍스트 한 줄을 찾아서 firstContent에 변수로 저장한다.
querySelector()를 사용하지 않은 이유는,
<div> 내부로 입력된 첫번째 텍스트는 따로 <div> 태그안에 입력되지 않고 그냥 [object Text] 형태로 입력됐기 때문이다.
그래서 constElement.childNodes를 Array 형태로 변환하여 .find() 메소드를 사용한 것이다.
이제야 정상적으로 이미지 썸네일과 가장 첫번째 문장이 포스팅 카드에 보여진다.
이제 좀 진짜 게시글의 역할을 할 수 있게 된 것 같다.
느리지만 한 스텝, 한 스텝 발전해 가고 있다.. 완전히 개발 할 때 까지 뽜이아!!🔥🔥🔥🔥
DOMContentLoaded 이벤트를 사용한다.
document.addEventListener("DOMContentLoaded", () => {
//실행하고자 하는 코드를 작성한다.
}
HTML 코드를 String 형태로 변환하는 방법 / String 코드를 HTML 형태로 변환하는 방법
HTML 코드를 JavaScript에서 문자열로 변환하는 방법은 DOM 객체의
outerHTML속성 또는, jQuery의html()메소드를 사용하여 HTML 코드를 문자열로 변환할 수 있다.
==================================
문자열을 HTML로 변환하는 방법은 DOMParser를 사용하는 것이 일반적이다. DOMParser는 문자열을 파싱하여 DOM 트리를 생성하는 객체이다.
<div> 태그에 텍스트를 입력하는 방법
https://developer-talk.tistory.com/844
https://dev-bak.tistory.com/16