My Top 9 Books의 역사

My Top 9 Books는 가벼운 마음으로 4시간 만에 개발하고 배포했던 사이트로,
출시 직후 트위터에서 바이럴 되면서 실시간 트렌드에 오르기까지 했었다.
1차 바이럴 후 3-4개월 동안은 하루 20명 정도의 이용자수를 유지하며 잔잔하게 흘러갔다.
그러다 7월에 내가 3월에 올렸던 서비스 소개 트윗이 갑자기 다시 리트윗 되기 시작하면서
해당 트윗의 조회수가 100만을 넘고, 사이트 이용자수도 급격히 늘어나며 2차 바이럴을 맞이했다.
2차 바이럴 이후에는 예전보다 꽤 늘어난 하루 70~80명 수준의 이용자수를 유지했다.
👇 이전 개발 후기
[My Top 9 Books] 4시간만에 만든 프로젝트가 X 트렌드에 오르기까지
https://www.mytop9books.com/ 개발 계기어느 날 인터넷을 보다가 요즘 '나를 구성하는 9가지의 게임'을 골라서 공유하는 사이트가 유행이라는 글을 봤다.👉 https://my9games.com/ 이미 유행이 시작된 지 몇
divheer.tistory.com
[My Top 9 Books] 이용자 수 3000% 증가한 개인 프로젝트에 대응했던 일주일
발단올해 3월, My Top 9 Books라는 개인 프로젝트를 출시했다. '내가 좋아하는 책 9권'을 선택해 이미지를 만들고 공유하는 서비스였는데,트위터에서 바이럴 되면서 출시 한 달 만에 이용자 수 2만 명
divheer.tistory.com
트렌드 포착 그리고 즉시 실행
그러던 8월의 어느 날, 나는 트위터 추천 탭에서 재미있는 트윗을 발견했다.

트위터가 업데이트되면서 여러 장의 이미지를 올릴 때
기존의 2x2 그리드 대신 가로로 길게 나열되는 형태로 바뀌었는데,
그 점을 이용해 책등 이미지를 나란히 늘어놓는 트윗을 올리는 것이 유행하고 있었다.
마침 얼마 전 도서 검색 API를 YES24로 마이그레이션하면서
YES24의 책등 이미지를 활용해보고 싶다는 생각을 하던 차였다.
이 트윗을 보자마자 '이걸 내 서비스에 도입해야겠다'는 생각이 들었고,
그 즉시 개발에 들어가 2시간 반 만에 기능 추가를 완료하고 홍보 트윗을 올렸다.
트위터를 넘어 스레드, 인스타그램까지
나는 주로 트위터에서만 서비스 홍보를 하고 있었기 때문에 이번에는 스레드에 도전해 보기로 했다.
(사실 스레드에는 예전에도 글을 몇 번 올렸지만 별 반응을 얻지 못했다...)

그런데 이번에는 스레드에서 생각보다 열렬한 반응이 있었다!
이 글로 인해 스레드에서 내가 좋아하는 책의 책등 이미지를 올리는 것이 유행이 되었다.

그래서 서비스 홍보용으로 색깔별 책등 이미지 모음을 모아서 올리기도 했다.
이번에 스레드와 트위터의 차이도 확실히 느낄 수 있었는데,
이 부분은 뒤에서 좀 더 자세히 다뤄보려 한다.

또 이번에는 인스타그램에도 내 서비스를 소개하는 릴스나 캐러셀 게시물이 올라왔다는 점이 신기했다.
인스타그램은 홍보를 어떻게 해야 할지 감이 오지 않아서 손 놓고 있었는데,
서비스에 애정을 가지고 직접 사용법을 소개해주는 게시물을 올려주셔서 너무 감사했다.

이러한 SNS 바이럴 덕분에 My Top 9 Books는 일주일 동안 1만 7천 명의 사용자를 기록했고,
서비스를 오픈한 이후로는 누적 사용자수 5만 명을 돌파했다!
책등으로 보기 기능 추가

<서재 만들기> 페이지에 '책표지로 보기 / 책등으로 보기' 토글 버튼을 추가해서
책등뷰 이미지까지 확인한 후 저장할 수 있도록 했다.
모든 책등 이미지를 받아와서 보여줄 수 있다면 좋았겠지만,
일부 일반 도서와 전자책, 해외도서의 경우에는 책등 이미지가 제공되지 않는 경우가 많아
이에 대비하기 위한 폴백 책등 컴포넌트를 만들어야 했다.

책등 이미지가 제공되지 않는 경우에는 표지 이미지를 조금 어둡게 처리해서
책등 이미지와 비슷한 느낌으로 만들어 제공했다.
그리고 책등 이미지를 한 장씩 저장해서 트위터에 직접 올리고 싶은 분들을 위해
(모바일 기준) 책등 이미지를 꾹 눌러서 갤러리에 다운받을 수 있도록 했다.
처음 업데이트할 때는 개발 속도를 우선시해서 일단 <서재 만들기> 페이지에서만 책등 뷰를 확인할 수 있도록 했다.
먼저 사용자들의 반응을 지켜봤는데 기능이 안정적으로 잘 사용되는 것 같아서
바로 다음 날에 <서재 구경하기> 페이지에도 '책등으로 보기' 기능을 추가했다.
이미지 다운로드 오류 개선
3월부터 고질적인 문제였던 이미지 저장 실패 문제...
그동안 에러 로그를 찾아봐도 원인을 알 수 없었는데,
클로드의 도움으로 iOS나 인스타그램, 스레드 인앱 브라우저로 접속했을 때
이미지 저장에 실패하는 것 같다는 추측을 할 수 있었다.

일단 기존에 이미지 저장 시 로컬에서 `data` 형식으로 생성하던 방식을 `blob`으로 변경했다.
덕분에 파일 다운로드 시 "출처"도 더 깔끔하게 표시되고 메모리 효율도 높일 수 있었다.
원래는 이미지를 자동으로 저장하는 방식 대신
직접 이미지를 꾹 눌러서 저장하면 오류를 우회할 수 있을 거라고 생각했다.

그래서 이미지 저장에 실패한 것을 감지하면 바로 이미지 저장 팝업을 띄우기로 했다.
처음에는 `blob`으로 생성한 이미지를 보여줬는데,
안드로이드 테스트해본 결과 `blob` 이미지는 꾹 눌러도 '이미지 다운로드'가 되지 않는 것을 확인했다.
그래서 최종적으로는 팝업을 열기 전에 이미지를 R2에 업로드해서 다운로드 받을 수 있게 하고,
팝업을 닫으면 즉시 DB에서 이미지가 삭제되는 방식으로 구현했다.
아쉬운 점은 iOS에서는 팝업을 통해 이미지가 저장되는 것을 확인했지만
인스타그램이나 스레드 인앱 브라우저로 접속한 경우에는 팝업에서도 이미지 저장이 불가능한 것으로 확인됐다.
이 부분은 앞으로 또 다른 방식을 고민해봐야 할 듯하다.
그 외 자잘한 개선사항
이번에 많은 분들이 유입된 점을 계기로 삼아 이곳저곳 개선을 많이 했다.
자동 스크롤 적용

책표지 혹은 책등 뷰를 전환할 때 자동으로 상단까지 스크롤되도록 적용해서
더욱 편하게 내가 선택한 9권을 확인할 수 있게 했다.
롱프레스로 드래그 앤 드롭 개선

원래도 드래그 앤 드롭으로 책표지의 순서를 조정할 수 있었는데,
기존에는 터치만 해도 드래그앤드롭 기능이 즉시 작동해서
스크롤을 위아래로 내리려다가도 의도치 않게 표지가 이동하는 바람에 이용에 불편함이 있었다.
그래서 이 점을 개선하고자 표지 이미지를 0.2초 이상 롱프레스 해야
표지 이동 기능이 작동하도록 기능을 수정했다.
도서명 정제

관리자 페이지에 책 제목에서 불필요한 문자열을 삭제해서 가독성을 높이는 등의 관리 기능을 추가했다.
'나와 취향이 비슷한 서재' 개선

서재 페이지에서 '나와 취향이 비슷한 다른 사람의 서재' 섹션에도 개선 사항이 있었다.
첫 번째는 서재 정렬을 최신순으로 바꿔서,
나와 취향이 비슷한 새로운 서재가 등록되었을 때 더욱 편하게 확인할 수 있도록 했다.
취향이 비슷한 서재는 '더 불러오기' 버튼을 클릭할 때마다 4개씩 서재를 추가로 불러오는데,
기존에는 서재를 추가로 불러온 상태에서 특정 서재를 눌러 페이지를 이동했다가 돌아오면
'더 불러오기'를 눌렀던 상태가 초기화돼서 연속으로 서재를 확인하기 불편했다.
그래서 서재를 클릭했을 때 '기존 탭에서 새로 열기' 대신 '새 탭으로 열기'를 적용해서 이 문제를 해결했다.
블라인드북 카드 스크롤

블라인드북 페이지를 모바일로 확인할 때는 카드 크기가 줄어들기 때문에
간혹 텍스트가 넘쳐서 전체 내용을 확인하지 못하는 경우가 생긴다.
그래서 카드 내부에 스크롤이 가능하도록 수정해서 잘린 텍스트까지 확인할 수 있도록 개선했다.
랭킹 100위까지 확대

랭킹 페이지는 원래 50위까지만 순위를 제공했는데
이제 데이터가 충분히 쌓여서 추가 순위를 제공해도 좋겠다고 판단해서 랭킹 제공 범위를 100위권까지 확대했다.
셔플 버튼 삭제

원래 <서재 구경하기>와 <블라인드북> 페이지에는
서재나 블라인드를 랜덤으로 추천받을 수 있는 셔플 버튼이 있었다.
내 취향과 무관하게 랜덤으로 데이터를 구경하고 싶은 사용자도 있지 않을까 해서 추가했던 기능인데
GA 데이터를 확인해 보니 이용률이 너무 저조한 데다가
괜히 UI만 조잡하게 만드는 거 같아서 결국 이 기능은 삭제했다.
표지 이미지 저장 구조 개선

공유 서재를 등록할 때 원래는 API에서 제공하는 표지 이미지 링크를 그대로 사용했는데,
좀 더 일관되게 (리커버로 인해 표지가 바뀌는 경우가 잦음) 표지 이미지를 제공하기 위해
표지 이미지를 스토리지에 별도로 저장하기로 했다.
처음에는 고화질 표지 이미지만 저장했는데,
<서재 구경하기> 페이지에서 9권 x 10개의 서재 표지 이미지를 한 번에 로드하다 보니
속도가 따라주지 못해서 표지가 뒤늦게 로드되는 등 불편함이 있겠다고 판단했다.
그래서 처음에는 R2의 Image Transformations 기능으로 기존 이미지를 리사이징 해서
섬네일 크기로 가져오도록 구현했는데, 월 5,000회의 무료 한도가 금세 넘어가면서
이 구조로는 섬네일 이미지를 지속적으로 가져오기 힘들겠다고 생각했다.
그래서 결국 표지 이미지를 생성할 때
고화질의 기본 이미지와 섬네일 크기의 이미지를 동시에 저장하도록 구조를 변경해서
표지 이미지를 작게 보여줄 때는 섬네일 이미지를 가져오도록 최적화했다.
YES24 애드온 연동 결과
원래는 일일 검색 한도 때문에 네이버 + 알라딘 도서 검색 API를 함께 사용하고 있었는데,
얼마 전에 YES24에서도 도서 검색 API가 출시되었다는 소식을 듣고
도서 검색 API를 YES24로 교체하면서 기존 데이터에 연동되어 있던 도서 링크도 전부 YES24로 바꿨다.
YES24 도서 검색 API는 '애드온 링크'라는 것을 제공하는데,
이 링크를 통해 접속한 뒤 24시간 이내에 상품을 구입하면 나에게 약 3%의 수수료가 지급된다.
현재 My Top 9 Books는 광고 없이 무료로 제공되고 있기 때문에
서버 비용이라도 보전해 보자는 생각으로 애드온 링크를 연동했다.
마침 링크를 모두 교체한 지 얼마 되지 않아서 SNS에서 서비스가 바이럴 되면서
약 2만 명의 사용자가 유입되고 5천 회 이상 링크가 클릭되었기 때문에
이 정도면 애드온 링크로 얼마나 수익을 낼 수 있을지 확인해 볼 좋은 기회라고 생각했다.
과연 결과는??

아무래도 도서 판매처가 다양하기도 하고, 책은 장바구니에 모아뒀다가 한 번에 주문하는 경우도 많다 보니
여러 이유로 책 제휴 링크를 통해서는 큰 수익을 내기는 어렵다는 것을 알게 됐다. 🤔
서비스를 지속적으로 운영하려면 다양한 수익화 방법을 좀 더 고민해 봐야겠다.
직접 느낀 트위터와 스레드의 차이점
이번에 트위터와 스레드에 둘 다 홍보 글을 올리면서 어느 정도 반응이 있었기 때문에
두 플랫폼에서 실질적으로 많은 차이점을 느낄 수 있었다.

동일한 멘트로 두 플랫폼에 각각 글을 올렸다.
우선 반응 면에서, 트위터에서는 기능 자체에 집중해서
'이렇게 책등으로 모아 보니 예쁘다'든가 '어떻게 이렇게 만드냐'는 등의 반응이 많았다.
반면에 스레드에서는 내가 어떤 책을 골랐는지에 더 집중해서
'나는 이 중에 n권 읽었다' 또는 '이 책은 어때, 재밌어?' 같은 반응이 많았다.
스레드가 아무래도 반말이 가능한 커뮤니티다 보니
처음 보는 사이에도 더 적극적으로 답글을 달고 소통하며
자신의 생각이나 취향을 자유롭게 나누는 분위기가 강했던 거 같다.
그리고 스레드의 알고리즘이 좋았던 점은 홈에 내가 관심 있는 분야의 게시물을 두루 보여준다는 점이었다.
예를 들어 내가 만든 서비스의 책등 이미지를 사용자들이 어떻게 이용하고 있는지 모니터링하고 싶을 때,
트위터에서는 인용을 확인하거나 직접 '책등' 같은 검색어를 입력해서 소수의 게시물만 확인할 수 있었는데
스레드에서는 홈 탭에 책등 이미지가 들어간 게시물을 자동으로 띄워줘서 확인하기 정말 좋았다.
글의 인기도와 상관없이 좋아요가 10개 미만이거나 올린 지 5분도 안 된 게시물까지도 확인할 수 있었다.
여기서 더 나아가 스레드에서는 책등 이미지를 올릴 때
타래로 내 서비스 링크를 함께 올리면서 출처를 표시해 주신 분들이 많아서 감사했다.
이번 기회에 확실히 스레드가 소규모 서비스 개발자나 창업자들이
서비스를 홍보하기에 유리한 플랫폼인 것 같다는 생각을 했다.
(그럼에도 불구하고 나는 트위터를 오래 해왔기 때문에 트위터가 더 편안하게 느껴지긴 한다...)
회고
이제 바이럴로 사용자수가 급격히 치솟았다가 자연스레 줄어드는,
그 씁쓸한 느낌에도 조금은 익숙해진 거 같다.
그래도 바이럴이 끝난 뒤에도 이전에 비해서는 MAU가 상승하는 추세인 걸 보면,
점점 더 많은 분들이 내 서비스를 인식하고 정기적으로 찾아주시는 것 같아 감사하다.
이번에는 지난 경험에서 배운 점을 이용해,
유행이 생겼을 때 이를 발 빠르게 캐치해서 바로 기능을 추가하는 경험을 해봤다.
이런 과정을 통해 개발자로서도, 서비스 운영자로서도 성장해 나가는 것 같다!