20210929 (42Sof 주요 기능에 대한 생각)

1. 전체 학습시간

오후 02:00 ~ 오전 03:00 (식사, 집안일, 운동 등 시간도 포함돼있음)

2. 학습 목표

42StackOverFlow 서비스 목표와 구현에 대한 고민

3. 학습 방법

하인호와 집단 지성

4. 다음 학습 목표

미정

5. 상세 학습 내용

42StackOverFlow 서비스 구현
(질문 게시글 페이지 불러오기 ,질문 리스트 특정 페이지 불러오기)
좋아요, 조회수 정보 추가하기

테이블 설계

게시글을 조회할 때 해당 그림처럼 좋아요의 갯수를 표시하고 싶습니다.
Like 테이블에 저장되어 있는 레코드를 매번 count 연산하여 해당 게시글의 좋아요의 갯수를 표시하는 방법 보다 Question(질문 게시글), Answer(답변 게시글) 테이블에 likeCount 따로 컬럼 생성하고 사용자가 좋아요를 누를 때마다 Like 테이블에 해당 게시글 id와 좋아요 상태를 저장하고 Question.likeCount에 증감하는 방법이 더 좋다고 생각이 들었습니다.
왜냐하면 좋아요 갯수를 표시할 때 Question 테이블에서 바로 가져올 수 있기 때문입니다. 그래서 위의 그림처럼 테이블을 설계했습니다.

게시글이 현재 Question(질문 게시글), Answer(답변 게시글)로 나누어져 있는 상태입니다. 그래서 좋아요 테이블도 AnswerLike , QuestionLike로 나누어져 있습니다. 이렇게 구분한 이유는 이후 좋아요 레코드가 많아지면 select 쿼리 속도가 느려질것 같아서 이를 분산 시키고자 나누었습니다.

조회수 중복방지

로그인한 사용자나 로그인을 안한 사용자가 게시글을 조회할 때 중복적인 요청은 거르고 조회수를 알맞게 증가시켜야합니다.
그래서 우리 서비스에 접속할 때 uuid 모듈을 사용해 중복되지 않도록 guestId을 발급하고
Cookie, 브라우저 Storage 중에 하나를 채택해서 해결할 예정입니다.

Cookie 를 사용할 경우

현재 우리 서비스는 로그인 성공시 accessToken을 쿠키에 저장하고 refreshToken은 LocalStorage에 저장했습니다. 그리고 쿠키 만료 시간과 accessToken 만료 시간을 30분으로 지정했습니다. 그리고 HttpOnly 설정을 통해 클라이언트의 접근을 완전히 차단함으로써 자바스크립트 코드를 통해 정보를 탈취하는 것을 방지했습니다.

accessToken이 만료되면 LocalStorage에 저장되어 있는 refresh 토큰 사용하여 검증 후 accessToken을 재발급 하도록 API를 제작했습니다. 그래서 조회수 중복 방지를 위해 쿠키 사용할 경우 위에서 설정해둔 만료시간 때문에 조회수 중복을 방지하는 guestId가 같이 사라집니다. 그래서 기존의 검증로직을 바꾸어야 합니다.

브라우저 Storage에 저장할 경우

클라이언트에서 게시글을 요청할 때 브라우저 Storage에 저장된 guestId를 서버로 넘겨주어야 합니다.

어떤 방법이 좋을지 피드백을 해주시면 감사하겠습니다.

redis 캐싱 전략

사용하려는 이유 :

조회수 반영에는 로그인 하지 않은 사용자도 포함 되어야하는데 이 데이터가 매우 많을 것으로 예상 또한 rdb에 저장시 guest 테이블 추가해줘야 하고 새로운 사람이 방문 할 때마다 guest 테이블에 데이터가 추가됩니다. guest 테이블에 이미 저장된 사용자가 로컬 스토리지에 저장된 guestId를 삭제하고 다시 방문시 guest 테이블에 다시 또 해당 사용자 정보가 추가되고 기존에 저장되어 있던 해당 사용자 정보는 죽은 데이터가 됩니다. 또한 I/O가 빈번하게 발생하기 때문에 해당 데이터를 데이터 베이스에서 관리하면 효율이 떨어질 것으로 예상됩니다. 이러한 여러 문제점들을 해결하기 위해서 조회수 기능은 레디스로 구현하려하고 있습니다.

레디스 저장 데이터 구조 :

레디스 저장 데이터 구조 : redis set 을 사용하여 guest의 guestId를 키로 사용하고 해당 키에 해당 guest가 방문한 question 의 questionId 들을 저장하고 guest가 question 페이지 방문시 해당 questionId가 레디스에 존재하는지 확인하여 조회수 중복 방지 처리에 사용할 예정입니다. 해당 데이터는 TTL 설정을 사용하여 일정 기간이 지나면 레디스에서 삭제되어 데이터가 과도하게 늘어나는 것을 방지할 것입니다. TTL 사용하여 데이터가 제거된다면 이후 조회수는 한번 더 체크 될 수 있으나 이는 같은 유저라 하더라도 충분한 시간 뒤에 다시 해당 question 페이지를 방문한 것은 해당 페이지의 추가적인 조회수 상승으로 인정해줄 예정입니다. 충분한 시간 뒤에 다시 방문한 것은 해당 페이지의 총 조회수에 반영되는 것이 맞다고 생각하였습니다. 그리고 총 조회수를 빠르게 확인하기 위해서 총 조회수 정보는 questionId를 키로 사용하여 value에 총 조회수를 저장하고 조회시 해당 데이터를 업데이트 시켜줄 예정입니다.

6. 실수한점

viewsChecking MiddleWares를 작성하다가 생긴 오류

ReplyError: WRONGTYPE Operation against a key holding the wrong kind of value 

특정키에 이미 다른유형의 값을 가지고 있을 때 발생

좋은 웹페이지 즐겨찾기