게시글 임시 저장 기능은 블로그 기능 및 많은 글 쓰기를 지원하는 플랫폼에서는 필수적으로 필요한 기능입니다.
Velog
처럼 블로그들의 주 기능은 바로 포스팅입니다.
글 작성 중 PC가 갑작스럽게 종료되거나 하는 이슈로 작성하던 글이 통째로 사라진 경험을 해보셨나요??
적지 않은 분들이 과제나 문서를 날려본 경험이 있으실 겁니다. 제가 그랬어요.. 마감 2분전에 저장을 안해서.. 😥
하지만, 요즘은 많은 플랫폼에서 임시 저장 기능을 제공합니다.
작성 중이던 글이 사라지는 경험을 하게 된다면 정말 끔찍하기 때문이죠. 🤬
최근 진행한 재밌는 프로젝트에서 임시 저장 기능을 구현했습니다.
편하게 임시 저장 기능을 사용하던 유저 입장에서 구현해야 하는 개발자 입장이 되니 고려해야 할 점들이 많았습니다.
임시 저장 기능을 구현하면서 고민한 내용과 해결해나간 내용을 간략하게 정리하며 적은 글이니 재밌게 읽어주시면 감사하겠습니다!!
게시글 임시 저장 기능을 구현하게 된 계기는 "게시글에 첨부한 이미지를 어떻게 관리할 것인가" 부터 출발했습니다.
게시글 작성 중 사용자가 이미지를 업로드하면 저장소(AWS S3
)에 바로 이미지가 업로드되는 방식으로 설계했습니다.
하지만, 유저가 게시글 작성 도중 이미지를 업로드한 후 게시글을 저장하지 않고 페이지를 떠난다면 게시글이 저장되지 않기 때문에 업로드된 이미지들이 연관관계가 없는 고아가 되는 문제가 발생했습니다.
고아가 된 이미지들은 해당 이미지를 업로드한 게시글이 존재하지 않기 때문에 삭제 작업이 제대로 이루어지지 않게 되는 것이죠.
고아 이미지 문제를 해결하기 위해 유저가 이미지를 업로드할 때 작성중인 게시글을 임시저장하는 방법을 시도했습니다.
게시글을 저장할 때는 해당 게시글의 id(postId), 제목(title), 내용(content)를 client에서 받아와 저장합니다.
[게시글 저장 형식]
{ "postId" : "7", "title" : "안녕하세요", "content" : "임시 저장해주세요!" }
참고 : 해당 게시글의 id(
postId
)의 유무로 새롭게 작성하는 게시글과 임시 저장 게시글, 출간한 게시글을 구분했습니다.
또한, 임시 저장된 게시글과 출간한 게시글을 구분하기 위해isPublished
라는 boolean형 변수를 사용했습니다.
임시 저장 기능을 구현하기 위해 고려한 경우의 수는 다음과 같습니다.
postId == null
&& isPublished == false
postId == [생성한 임시 저장 게시글 엔티티의 id]
&& isPublished == false
postId == null
&& isPublished == false
postId == [생성한 임시 저장 게시글 엔티티의 id]
&& isPublished == false
postId == null
&& isPublished == false
postId == [생성한 임시 저장 게시글 엔티티의 id]
&& isPublished == true
postId == [임시 저장 게시글 엔티티의 id]
&& isPublished == false
postId == [임시 저장 게시글 엔티티의 id]
&& isPublished == false
postId == [임시 저장 게시글 엔티티의 id]
&& isPublished == false
postId == [임시 저장 게시글 엔티티의 id]
&& isPublished == false
postId == [임시 저장 게시글 엔티티의 id]
&& isPublished == false
postId == [출간된 게시글 엔티티의 id]
&& isPublished == true
postId == [출간된 게시글 엔티티의 id]
&& isPublished == true
postId == [출간된 게시글의 사본 게시글 엔티티의 id]
&& isPublished == true
postId == [출간된 게시글 엔티티의 id]
&& isPublished == true
postId == [출간된 게시글의 사본 게시글 엔티티의 id]
&& isPublished == true
postId == [출간된 게시글 엔티티의 id]
&& isPublished == true
postId == [출간된 게시글 엔티티의 id]
&& isPublished == true
출간된 게시글의 경우, 수정 또는 이미지 업로드 행위가 발생하면 출간된 게시글의 사본을 만들어 해당 사본 게시글에 변경 사항을 적용했습니다.
원본 게시글과 사본 게시글을 구분하기 위해 게시글 엔티티에
originalPostId
변수를 추가하여 원본 게시글 엔티티의 id를 가지도록 했습니다.
originalPostId
와 해당 게시글 엔티티의 id가 동일하다면 원본, 동일하지 않다면 사본으로 구분했습니다.
위와 같이 9가지 경우에 대한 코드를 구현하면서 중복되거나 유사한 코드가 너무 많다고 느껴졌습니다.
예를 들어
유사한 경우들을 나누지 않고 하나로 처리할 수 있을 것 같은 느낌이 들었습니다.
임시 저장된 게시글과 출간된 게시글은 모두 postId
를 가지고 있기 때문에 하나의 경우에서 isPublished
변수를 사용한 분기 처리로 코드를 리팩토링했습니다.
9가지의 경우의 수를 6가지로 줄이면서 반복되는 코드를 제거했습니다.
당연하게 사용해왔던 임시 저장 기능을 직접 고민해보고 구현해보면서 저에게 문제를 깊이 고민해본 경험으로 남을 것 같습니다.
제가 만든 임시 저장 기능이 프로젝트에서도 잘 동작이 되는 것을 보면서 느꼈던 감정은 정말 최고였습니다.
임시 저장 기능을 구현하시는 분들은 제가 고민한 부분을 참고하시면 좋을 것 같습니다!
더 좋은 알고리즘 또는 최적화 포인트를 알고 계신다면 댓글로 남겨주시면 큰 도움이 될 것 같습니다 👍
좋은 정보 감사합니다! 저도 임시 저장 기능 구현해보고 싶네요 ㅎㅎ