오늘은 임시 저장 기능을 구현한 것에 대해서 벨로그로 작성해보려고 한다.
이번 기능 구현이 지금까지 구현한 기능 중 사실 가장 힘들었다.
되게 쉬울 것 같았는데.. 이미 만들어진 코드에서 새로운 기능을 추가하려니까 고칠게 한 두가지가 아니었다.
벨로그에서 게시글 작성 중 임시저장 버튼을 클릭하면 해당 이미지와 같이 "포스트가 임시저장되었습니다"라는 알림이 우측 상단에 나타나게 된다.
그리고 임시 저장된 게시글들은 "/saves" 페이지에서 확인 할 수 있다.
일단 이걸 보고나서, 머릿속으로 구상한 것은..
- 임시 글 목록 리스트를 따로 관리하기.
- 임시 저장 버튼을 클릭하면 알림이 나타나게 하기.
- 임시 글을 다시 작성하려고 하면 이전에 작성된 글 내용 불러오기.
순서로 머릿속에 떠올랐다.
생각보다 간단할 것 같았는데.. 생각외로 좀 오래 걸렸다. 이 글을 작성하는 지금까지도 완벽하게 구현한 것 같다는 느낌은 아니다. 🥲
임시 저장된 게시글 작성 화면 구성은 사실 게시글 작성 화면 구성과 완전하게 동일 하기 때문에, writePage.js 파일을 이용해서 임시 작성 게시글 기능을 구현하려고 처음에 시도하였다.
그러나, 이렇게 writePage.js 위에 해당 기능을 구현하는데 문제점이 여럿 있었다.
- 현재 작성하려는 것이 새로운 글인지, 임시 저장된 게시글인지 파악하는 문제.
- 임시 저장글일 경우, 출간할 때 해당 임시 글을 전체 임시 글 리스트에서 어떻게 제거할 것 인지.
- 인덱싱은 어떤식으로 처리해야할 것 인지.
거의 1~2 시간 정도를 writePage.js 를 이용해서 기능을 구현하려고 했으나.. 결국 실패했다.
너무 겹치는 코드가 많았고, 하나의 기능에 연계된 기능들이 많았으며, 각각의 기능을 어떻게 변경할 것인가에 대해서 여러 방도로 시도를 했으나..
그냥 새로운 임시 저장 게시글 작성용 페이지를 만드는 것이 훨씬 수월할 것이라고 판단했다.
그래서 새로운 saveWritePage.js 파일을 만들게 된다.
<Route
path="/write/saved/:id"
element={
<SaveWritePage
postID={postID}
setPostID={setPostID}
postList={postList}
setPostList={setPostList}
savePostList={savePostList}
setSavePostList={setSavePostList}
/>
}
/>
위 코드와 같이 새로운 /write/saved/:id
경로를 설정하여 write 페이지와 겹치지 않게 설정하였다.
전체적인 화면 구조는 write 페이지와 saveWrite 페이지가 같기 때문에 코드 수정은 크게 없었으나, 임시 저장 된 데이터를 화면에 불러오는 코드가 추가 되었다.
// savePage.js
// 임시 저장된 게시글의 경로 설정은 해당 item의 id 값으로 설정한다.
return (
<Link to={`/write/saved/${item.id}`} className="savePost">
<span className="title">{item.title}</span>
<span className="content">{firstContent}</span>
<section className="functions">
<span className="date">{item.date}</span>
<span className="deleteButton">삭제</span>
</section>
</Link>
);
// saveWritePage.js
// useLocation 을 사용해 현재 경로 위치의 id 값으로 임시 저장된 게시글을 찾는다.
const savedPost = savePostList.find(
(item) => item.id === parseInt(location.split("/")[3])
);
// 처음 화면이 불러와질 때, 저장된 데이터를 불러와준다.
useEffect(() => {
titleTextareaRef.current.value = savedPost.title;
contentTextareaRef.current.innerHTML = contentHTML;
previewTitleRef.current.value = savedPost.title;
previewContentRef.current.innerHTML = contentHTML;
});
위 코드와 같은 구조로 임시 저장된 게시글 정보를 불러온다.
임시 저장된 게시글 목록에서 임시 저장 게시글을 수정하려고 클릭하면 해당 id 값을 경로로 설정하여 saveWritePage.js의 props 로서 사용할 수 있도록 한 것이다.
const handleAddPost = () => {
if (!isError) {
const today = new Date();
const title = titleTextareaRef.current.value;
const content = previewContentRef.current.outerHTML;
const newPost = {
userID: savedPost.userID,
id: postID,
title: title,
content: content,
date: today.toLocaleDateString(),
likesCount: 0,
};
setPostList([...postList, newPost]);
const headerContainer = document.querySelector(".headerContainer");
headerContainer.classList.remove("hide");
setPostID(postID + 1);
const result = savePostList
.filter((item) => item !== savedPost)
.filter((item) => item !== undefined);
setSavePostList(result);
navigate("/");
}
};
임시 저장된 게시글을 출간 할 경우를 처리하는 코드이다.
일단 에러 체크를 하고, 새로운 게시글을 postList에 넣어준다.
그리고 임시 저장 목록에서 현재 게시글의 정보를 없애기 위해 filter 메소드를 사용해주었다.
.filter((item) => item !== savedPost)
로 현재 출간된 포스트를 목록 상에서 없애주고, .filter((item) => item !== undefined)
로 undefined 된 게시글 정보를 없애준다.
완성된 임시 글 목록 화면과 임시 저장된 게시글 작성 화면이다.
내가 생각했던 대로 코드들은 정상적으로 동작했다.
경로 설정도 제대로 되고, 게시될 경우 임시 저장 목록에서도 삭제된다.
내가 공부를 게을리 했다.
변명할 거 없이, 그냥 내가 최근 3일동안 공부를 게을리 했다.
하루도 빠짐없이 맥북을 켰지만.. 집중한 시간이 두시간 이상 될런지...
전반적인 코드 동작 방식을 변경해야했다.
임시 저장 기능을 생각하지 않고 게시글 작성 기능을 만들었기 때문에, 이 부분 부터 게시글 인덱스 설정까지 수정해야할 부분이 너무 많았다.
임시 저장 기능을 구현한 지금도 다 갈아 엎어야 할 정도로, 수정이 필요하다.
지금은 단순하게 전체 게시글 정보를 하나의 리스트가 관리하고 있는데, 이것을 사용자 정보 안에 넣어줘야 할 것 같다.
그러면 굳이 불필요하게 게시글의 작성자를 찾아서 불러올 필요가 없다. 불필요한 로직이 너무 많다.
css-module 을 전부 삭제했다.
처음에는 css-module로 관리하는 것이 화면 디자인을 짜는데 편리했으나.. 어쩔수없이 querySelector
로 엘리먼트를 접근해야할 상황이 생길 때, 오히려 css-module 은 독이 됐다.
css-module을 사용하다 보니, 중첩되는 클래스명이 너무 많았다. 물론 자동으로 뒤에 더미 값들이 붙지만.. 쿼리셀렉터로는 내가 지정한 클래스명으로 엘리먼트들을 찾다보니까.. 아무튼 그래서 css-module을 전부 css로 바꿔줬다. 클래스명도 전부 중첩되는 것 없게 수정했다.
styled-component를 다음 프로젝트부터 써볼까 한다.
DOM
을 직접 받아오는 부분에 대한 이해도가 부족했다.
처음 구현하는 부분들이 많다보니까, 아직 DOM
자체를 보내주고 받아오는 방법에 대한 이해도가 부족해서, 이번 기능 구현에 이렇게 오래 걸린 것 같다. 열심히 개발하면서 공부해야할 부분...
아무튼.. 원래는 매일매일 벨로그를 작성하는게 목표였으나, 기능을 구현하지 못한 상태에서 벨로그를 작성하는건 조금은 무의미하다 판단하여 작성일이 늦춰젔다.
그래도 기능 구현은 완료했으니.. 이제는 새로운 기능을 구현하기보다 지금까지 구현한 기능들을 다듬고 더 완성도있게 만들어보려고한다.
뭔가.. 재미없을 것 같지만.. 그래도 반드시 해야하니까.. ㅎ.. 😭😭😭😭
좋은 글 감사합니다. 자주 올게요 :)