손수 제작하고 싶었던 서비스형 블로그에서 추가하고 싶었던 다양한 기능을 구현하기 전에 어떻게 구현할지 생각해 놓은 글이다. 본래는 제작된 사이트 내부에 시리즈로 기록했으나 본 블로그로 이전하게 되었다.


사용자 댓글 태그 알고리즘

대댓글을 사용하지 않는 이유?

  • UX를 위해서 한칸 들여서 보여줘야 하므로 UI가 이쁘지 않음
  • 답글이 굳이 필요한 이유를 찾을 수 없으며 그룹 넘버나 답글의 답글로 인한 불필요한 데이터가 낭비됨

이 방식을 사용하면 얻는 단점

댓글이 급작스럽게 많이 달리는 경우 사용자가 어디서 태그됐는지 알 지 못함 => 댓글에 순번을 삽입하고 알림의 리다이렉션 경로에 해당 순번을 링크하면 됨

그래서 알고리즘

  1. 댓글 텍스트 에어리어를 선택하면 현재 글에 댓글을 작성한 사용자 목록을 가져온다.
    • 지속적인 호출을 방지하기 위해서 한번만 호출할 수 있도록 대비를 해둬야 함
    • 하지만 위 대비를 하는 경우 실시간으로 달린 유저를 태그할 수 없음
  2. 댓글 텍스트 에어리어에서 @를 입력하면 사용자 가져올 준비
    • 현재는 자바스크립트의 키코드를 이용하여(Shift + 2) 사용하고 있지만 더 나은 방법이 있다면 개선할 예정
  3. 문자를 입력하면 알맞은 사용자를 매칭한다.
    • 자바스크립트의 keycode를 사용하여 지속적으로 매칭을 해주려고 했으나 영어를 제외한 키코드를 찾을 수 없었다.
    • 우선은 프롬프트에 사용자를 입력하고 작성한 사용자가 목록에 있는 경우 전송할 목록에 추가하고 아니면 없다고 알려준다.
    • 프롬프트는 일단 너무 초라하니까 모달같은 것으로 먼저 업그레이드하고 해당 인풋박스에서 사용자를 찾아주는 방식으로 만들자.
    • 부트스트랩에 팝오버라는 레이아웃이 있는데 이걸 사용하면 유저 선택시 프로필을 볼지 태그를 실시할지 선택할 수 있게 할 수 있을 것 같지만 팝오버안에 링크를 거는 방법을 모르겟다.
  4. 사용자 목록은 드롭다운 형식으로 출력하고 댓글 작성자가 드롭다운에서 사용자를 클릭하면 알림을 전송할 목록에 추가한다.
    • 현재는 프롬프트지만 위 문제를 해결하면 이 모델이 최종적으로 적용될 것이다.
  5. 댓글을 단다.
  6. 목록에 사용자에게 알림을 전송한다.




사용자와 시리즈와 포스트의 관계

  • 사용자는 시리즈를 여러개 가질 수 있다.
  • 시리즈는 오직 한 명의 사용자만 가질 수 있다.
  • 사용자 1 - N 시리즈


  • 시리즈는 포스트를 여러개 가질 수 있다.
  • 포스트는 오직 하나의 시리즈만 가질 수 있다.
  • 시리즈 1 - N 포스트


원래는 위 관계가 정석인데 내가 무슨 생각으로 시리즈와 포스트의 관계를 다대다로 만들어 버렸다. 포스트에다 시리즈를 외래키로 넣었으면 끝날일을… 구현하다가 문득 “엇… 뭔가 잘못됐다” 라는 것을 느꼈다. 그래서 일단 구현을 멈추고 진지하게 개선할 방법을 찾아야했다. 시리즈와 포스트의 이 독특한 관계를 개선할 방법을 말이다.

  • 시리즈는 포스트를 여러개 가질 수 있다.
  • 포스트는 시리즈를 여러개 가질 수 있다.

이미 이러한 관계는 ‘태그’라는 존재가 진행하고 있다. 하지만 문득 생각해보면 시리즈도 여러개면 좋은 경우가 더럿있을 수 있다. 예를들어 한 작가가 BLEX에서 소설 A를 집필하고 외전을 냈다.

  • 소설 A 1권
  • 소설 A 2권
  • 소설 A 외전

그리고 소설 B를 집필하셨다.

  • 소설 B 1권
  • 소설 B 2권
  • 소설 B 3권
  • 소설 B 외전

그런데 사람들이 외전을 좋아하면 작가는 ‘외전 시리즈’를 만들어 사람들에게 제공해 줄 필요가 있다. 이렇게 하려면 어떠한 추가정보가 필요한가?

  • 소설 A 외전
    • 소설 A 시리즈
    • 외전 시리즈

소설 A 외전은 아래와 같이 두가지의 시리즈를 가지고 있을 것이다. 사용자가 소설 A 외전에 접근 했을때 사용자가 진정으로 원하는 시리즈는 무엇일까? 1권에 접근했으면 당연히 A 시리즈를 보고 싶은거겠지만 외전에 먼저 접근했다면 외전 시리즈를 보기 위함으로 생각된다.

  • 접근한 게시물의 시리즈가 2개일 때
    • 시리즈의 가장 최상위 게시물이 접근한 게시물인 시리즈를 연결한다.

하지만 위와같이 설정한 경우 문제가 있겠다. 소설 A 외전 이후 소설 A 3권을 집필 하셨다면 문제가 커진다.

소설 A 1권 -> 소설 A 2권 -> 소설 A 외전 -> ?

만일 위 알고리즘으로 구성한 경우 다음 추천 시리즈가 소설 B 외전으로 바뀌게 된다. 이를 해결하는 방법은?

  • 접근한 게시물의 시리즈가 2개일 때
    • 시리즈의 가장 최상위 게시물이 접근한 게시물인 시리즈를 연결한다.
    • 시리즈를 통해서 다음으로 넘어간 경우 GET으로 series를 보내서 올바른 시리즈를 유도한다.

잘못된 관계로 시작했지만 끝은 창대해졌다. 구현만 된다면 말이다. 하지만 걱정되는 건 SEO다… 같은 글이 여러개 복제되면 그닥 좋을 일은 없을텐데… 괜찮은까?… series가 포함된 URL은 noindex 태그를 추가하여 크롤링을 막던지 해야겠다.


완성된 알고리즘

1권에 바로 접근했을때 모습이다. A 시리즈는 1권, 2권, 외전, 3권을 포함하고 있다.

A 외전에 바로 접근했을때 모습이다. 다음 시리즈로 B 외전을 추천하고 있다.

1권에서 A 외전으로 순차적으로 접근했을때 모습이다. 다음 시리즈로 3권을 추천하고 있다.




포스트 추천 알고리즘

최근 인기 ref. OKKY

  • ref. OKKY

오키에서 주간 베스트라는 항목이 있는데 이 항목에 글들을 어떻게 배치할 수 있을까? 솔직히 매우 간단한 알고리즘이라 생각된다. 일주일 이내에 작성된 글을 먼저 필터링하고 조회수 높은 순서로 배치해주면 되겠다. 굳이 좋아요가 아닌 조회수를 사용한 이유는 좋아요는 친목으로 인해 쉽게 상위로 갈 수 있기 때문이다. 다만 제목으로 어그로를 끄는 경우를 대비하여 조회수 대비 좋아요 비율을 측정하여 포스트를 배치하면 되겠다.

현재는 순전히 조회수 순으로 배치하고 있다.


사용자 맞춤 추천 ref. YouTube

유튜브에는 사용자 맞춤 영상 추천 알고리즘을 가지고 있다. 어떤 방식으로 돌아가는 걸까 고민하며 나름 나만의 방식으로 추천 방법을 생각해 보았다.

  1. 포스트 목록을 최신순으로 불러온다.
  2. 포스트를 리스트로 변경하고 각각의 포스트 옆에 우선순위 값(100)을 추가한다.
  3. 사용자가 추천한 글과 같은 태그의 글의 우선순위에 1.?를 곱한다.
  4. 사용자가 구독한 사용자의 글을 찾아 우선순위에 1.?를 곱한다.
  5. 사용자가 읽은 글의 시리즈를 찾아 우선순위에 1.?를 곱한다.
  6. 사용자가 읽은 글의 태그를 찾아 우선순위에 1.?를 곱한다.
  7. 사용자가 이미 읽은 글은 우선순위에 0.?를 곱한다.

먼저 위 방식을 사용하기 위해서 가장 필요한 건 사용자가 읽은 포스트에 대한 정보다. 이를 보관하는 방법을 어떻게 하는게 효율적일까? 텍스트 필드에 콤마 형식으로 분할하여 스플릿? 아니면 varchar 형식으로 일일이 저장? 지금은 먼저 전자의 방식으로 진행할 것이다. 또한 이는 사용자의 활동 정보를 수집하는 것이므로 계정 설정에서 허용하거나 해지할 수 있도록 해줘야겠다.


트랜디한 포스트 ref. Velog

밸로그에는 트랜디한 포스트를 출력한다. 트랜디한 포스트라… 처음엔 당연히 좋아요가 최근에 많이 된 글을 찾으면 되리라 생각했지만 그 글을 어떻게 찾느냐가 문제였다. 나름 나만의 방식으로 생각해 본 것은 아래와 같다.

최근에 추천을 많이 받았다?

  • 얼마나 주기가 짧은지 비교해야 된다.
  • 마지막으로 추천된 날짜를 보관하고 사용자가 추천하면 그 텀을 비교한다.
  • 식은 (20/(내가 추천한 날짜 - 마지막 추천된 날짜 + 1)) 정도면 되지 않을까?
  • 좋아요를 지속적으로 좋아요 취소하는 경우를 대비하여 취소시 과감하게 -20을 제공한다.
  • 트랜디 수치는 절대로 0 이하로 내려가지 않게 한다.
  • 해당 점수는 데이터베이스에 트랜디값으로 보관하고 트랜디값으로 정렬하면 될듯하다.
  • 또한 수치를 일정 기간에 한번 감소시키던 초기화하던 해야겠다.




무한 스크롤 문제

무한 스크롤에 대한 사람들의 생각

일단 필자의 생각에는 무한 스크롤은 정말 좋은 시스템이라 생각한다. 온전히 시스템 입장에서 말이다. 사용자가 볼 만큼만 적당히 이미지나 리소스를 뿌려주기에 시스템의 부하를 줄일 수 있다. 하지만 많은 사람들은 무한 스크롤에 대한 거부감을 가지고 있다.


무한 스크롤 정말 짜증나지 않나요?

무한 스크롤이 언제부턴가 거의 대부분의 SNS 사이트들이 기본으로 채용하는 UI가 되었죠.. 근데 사실 이거 무지하게 불편한 UI 아닙니까? 무한 스크롤의 단점은 첫째 과거 게시물에의 접근성이 거의 0에 수렴한다는겁니다. 10페이지 뒤쪽 게시물을 보기 위해서 페이지 로딩 10번을 해서 차근차근 접근해야 한다니.. 이건 한마디로 보지마! 라고 말하는거나 다름없죠. 니 인내심이 이기나 내가 이기나 싸우자는겁니다. 게다가 웃긴건 간신히 몇번이고 스크롤을 아래로 댕기고 새로운 페이지를 로드하고 그래서 원하는 게시물을 찾았다고 치죠. 그걸 클릭해서 본 다음에 뒤로 돌아가면 다시 목록 처음부터 리셋!!!

출처 : XETOWN

사실 읽고나면 정말 공감가는 메세지다. 이 글 외에도 대부분 무한 스크롤에 반감을 가진 사람들은 같은 반응이다. 뒤쪽에 있는 게시물을 보기가 힘들고 대부분의 사이트는 무한 스크롤 된 게시물을 보고 뒤로가면 1-2페이지에서 미아가 된다. 사실 BLEX도 같은 문제를 앓고 있으며 필자는 그것을 애써 모른척하고 있었다.


일단 문제점을 정리하면

  1. 가장 뒤에 있는 글도 보고싶다.
  2. 스크롤 된 글을 읽고 뒤로가기 문제.

2번의 경우는 벨로그와 같은 훌륭한 서비스들은 해당 문제를 깔끔하게 극복했다. 이미 라이브러리가 존재하는지 아닌지는 모르겠다. 슬쩍 찾아보긴 했으나 불만글만 그득하고 ‘해결한 사이트도 있다더라~’ 라는 글만 볼 수 있었다. 하나는 해결방법에 대해서 나열되어 있는데 솔직히 필자가 이해하기 어려워서 다른 방법을 찾고 싶었다. 여기 있는 건 ‘이렇게 극복해 볼까?’ 하는 개인적인 생각을 정리하는 글이다.


가장 뒤에 있는 글도 보고싶다.

‘뒤에 있는 글을 왜 보고 싶을까?’라는 생각으로 밸로그의 첫 글이 궁금했다. 쉼없이 스크롤을 내렸지만 끝은 보이지 않았다. 근데 사실 이 문제는 해결이 너무 간단해 보였다. 정렬을 역순으로 해주면 그만이다. 3 페이지 정도를 넘어가면 글쓰기 버튼을 하단으로 내리는 버튼으로 교체시키고 버튼을 누르면 최상위로 (약간 워프하는 애니메이션 주면서) 이동시키고 역순으로 정렬한 페이지를 보여준다!


스크롤 된 글을 읽고 뒤로가기 문제.

이 문제를 해결하기 위해서 다양한 방법을 생각했다.

  • 스크롤을 내리면 페이지를 상승시키고 게시물을 누르면 페이지를 캐시해두고 뒤로가기시 캐시된 페이지로 넘어가는 것이다.

다만 위 알고리즘의 문제는 사용자가 맨 아래로 내렸다가 다시 위로 올라가서 게시물을 누르고 뒤로 돌아온 경우 무한 스크롤과는 전혀 반대의 문제를 겪는다.

  • 스크롤을 내리면 URL을 지속적으로 변경한다.

이는 어떤 워드프레스 블로그에서 봤던 방법을 착안한 것이다. 다만 페이지 전환없이 뒤로가기시 적용될 URL을 바꾸는게 가능한 것인지 모르겠다. 봤던 사이트에도 적용됐으니 어찌되건 되겠지만 좀 더 찾아봐야겠다. 다만 그 페이지가 불편했던게 뒤로가기 후 이전 페이지의 글을 볼 수 없었다는 것이다.

  • 각 포스트에 data-page를 저장한다.

이후 첫 방법과 동일하게 캐시에 저장했다가 돌아가게 할 것이다. 1번 보다 안정적이며 구현도 쉬울 것으로 생각된다. 하지만 2번의 단점을 똑같이 안고가야 한다. 저장된 캐시는 메인 페이지의 로고를 누르면 삭제하는 것으로 해결하자 :D

WRITTEN BY

배진오

소비적인 일보단 생산적인 일을 추구하며, 좋아하는 일을 잘하고 싶어합니다 :D
im@baejino.com