조회수 어뷰징은 어떻게 막아야 할까?
어뷰징 (Abusing) : 의도적인 조작을 통해 조회수나 클릭수를 높이기 위한 일련의 행위
CRUD 커뮤니티 프로젝트를 하면서 고민했던 주제입니다.
다른 프로젝트에서는 커뮤니티 부분을 개발하지 않아서 생각하지도 않았던 문제인데, 개인적으로 따로 해보려니 많은 고민이 필요했습니다.
🧐 조회수는 무엇일까?
- 게시글을 1명의 사용자가 여러번 접속해도 카운트하는 것?
- 게시글을 1명의 사용자가 여러번 접속해도 한 번만 카운트하는 것?
- 게시글에서 1명의 사용자는 하루에 1번만 카운트하는 것?
- 비회원의 경우에도 게시글 접속하면 카운트하는 것?
- 1명의 사용자가 여러 장소(여러 IP)에서 접속했을 때, 조회수 증가는 어떻게 할까?
- 쿠키 기반이라면 고의로 삭제했을 때 어떻게 해야할까?
- ...
위와 같이 조회수 증가에 대한 깊은 고민을 하다보니 제가 너무 쉽게 생각했었던 것 같았습니다.
조회수 기능을 넣었던 학교 동기에게 물어보면 큰 고민없이 접속하면 카운트되거나, 조회수 증가 API를 따로 만들어서 보내고 있었습니다.
그래서 각종 커뮤니티 게시글을 참고해보았는데 비회원의 경우에도 여러번 접속해도 조회수가 올라가는 경우가 많았습니다.
유튜브처럼 수익으로 연결되는 부분은 민감하게 처리를 하는 것 같았고,
다른 커뮤니티 사이트들은 (조회수가 많다 == 이용자가 많다) 라는 소비자의 관점에서 만든게 아닐까 싶습니다.
만약 그렇다면 조회수를 가지고 무언가를 기획(이벤트)하기에는 어려움이 많을 듯 싶습니다. (조회수 어뷰징 문제)
따라서 조회수가 아닌 추천수를 만들기도 하는 것 같습니다.
- 조회수 == 이용자수
- 추천수 == 가치있는 정보(게시글)
이용자 수가 많다는 것을 조회수로 보여주고, 가치있는 정보글이라는 것을 추천수로 보여주기에 두 마리의 토끼를 잡은게 아닐까 싶습니다.
서비스마다 다르겠지만 유튜브와 같이 정보서비스업을 한다면 (조회수==수익) 이라는 중요한 부분이 될 수 있습니다.
또한, 조회수가 높을수록 가치있는 정보(게시글)이라는 의미가 될 수 있기 때문에, 커뮤니티 서비스가 있는 곳이라면 깊게 생각해볼만한 주제인 것 같습니다.
유튜브는 다음과 같이 조회수 증가 규칙을 정한 것 같았습니다.
- 사용자가 의도적으로 동영상을 시작한다
- 사용자는 적어도 30초동안 영상을 시청한다
- 최대 반복수는 300번으로 예상된다
- 최대 반복수를 넘었을 시 봇을 이용하는지 유효성 검사 단계가 수행되면서 더 이상 조회수가 증가하지 않는다
- 조회수 증가하지 않는 상황
- 많은 장치에 대해 하나의 IP 주소를 사용하여 동시에 동일한 영상을 시청할 때
- 윈도우 또는 탭을 많이 실행시켜 영상을 동시에 보는 행위
- 영상을 시청하는 30초마다 페이지 새로고침
이렇게 다양한 조회수 증가 방법이 있기 때문에, 먼저 현재 서비스에서 필요한 조회수 증가는 어떤 것인가를 정해야합니다.
저는 다음과 같이 조회수를 증가시키기로 정했습니다.
- 하루에 1번 조회수 증가
- 비회원도 조회수 증가
회원과 비회원의 경우에 따라서도 조회수 증가를 구현하는 방법이 달라질 수 있으니 이것도 명확히 정해야합니다.
간단하게 예시를 들자면 다음과 같습니다.
- 회원일 경우 : 로그인 인증값으로 조회수 증가 로직 만듬
- 비회원일 경우 : IP, Mac Address으로 조회수 증가 로직 만듬
🧐 조회수 증가 로직을 구현하는 방법
- 전체 게시글 페이지에서 클릭했을 때 조회수 증가
- 세션 또는 쿠키 사용
- IP 또는 Mac Address 이용
- DB 이용
1. 전체 게시글 페이지에서 클릭했을 때 조회수 증가
- 클릭했을 때만 조회수 증가 O
- 새로고침 시 조회수 중복 방지 O
- URI로 직접 접속하면 조회수 증가 X
- 비회원도 조회수 증가 O
- 클릭했을 때의 요청 API를 고의로 보내는 문제
이 방법은 사용자가 클릭했을 때만 조회수가 증가되며, 비회원도 가능하며, 새로고침 시 조회수 방지가 됩니다.
하지만 URI는 조회수로 취급하지 않습니다. 그리고 결정적으로 클릭했을 때의 이벤트 요청 URI를 획득하여 수많은 요청을 보냈을 시 문제가 됩니다.
2. 세션 또는 쿠키 사용
- 페이지 접속했을 때 하루 기준으로 조회수 증가 O
- 새로고침 시 조회수 중복 방지 O
- URI로 직접 접속해도 조회수 증가 O
- 비회원도 조회수 증가 O
- 쿠키 고의 삭제의 문제점 발생
페이지를 접속했을 때를 기준으로 조회수 증가 로직이 실행되기때문에 내가 원하는 방법에 근접하고 있다.
하지만 단점으로는 HTTP 요청마다 쿠키를 보내야하므로 쿠키값이 커질경우 네트워크 트래픽에 부담을 준다.
RFC 2109 쿠키 표준안에 따르면
- 300개까지 생성 가능
- 최대 크기 4,096 바이트
- 하나의 호스트나 도메인에 최대 20개까지 생성 가능
대부분의 브라우저는 위 표준안과 비슷하거나 적은 개수의 쿠키를 지원한다.
char(2바이트)를 3개씩 써서 게시글을 표현한다면, 약 682개 게시글을 쿠키에 담을 수 있다고 생각할 수 있지만
네이버의 어떤 게시글 번호를 보면 1,000억 단위인 경우도 있고 그 이상일 수도 있다.
그랬을때 28바이트이므로 약 146개의 게시글을 표현할 수 있다.
세션의 경우는 scale-out하여 서버가 여러대일 경우 1번 서버에 저장된 값이 2번 서버에는 없으므로 쿠키로 하는것이 맞다.
하지만 쿠키의 경우 위의 단점들이 있는것을 생각하여 사용해야한다. (게시글 번호에 따른 쿠키 저장값)
거기다가 제일 큰 문제점은 사용자가 고의로 쿠키를 삭제했을 때이다.
3. IP 또는 Mac Address 이용
- 페이지 접속했을 때 하루 기준으로 조회수 증가 O
- 새로고침 시 조회수 방지 O
- URI로 직접 접속해도 조회수 증가 O
- 비회원도 조회수 증가 O
- 저장 장소의 문제점
- DB 비용은 비싸므로 인메모리 데이터 저장소 사용
- 접속 장소의 문제점
IP는 장소에 따라 유동적으로 변할 수 있는 문제점이 있다.
장점이자 단점으로 근처 여러 기기로 비회원이든 회원이든 접속해도 동일 유저로 식별된다는 것이다.
Mac 주소는 어느 장소에서도 식별이 가능하다.
하지만 기기를 변경하면 다른 유저로 식별이 된다.
또한 IP와 Mac 주소는 값이 길기 때문에 수많은 유저와 수많은 게시글과 날짜를 함께 저장하기에는 저장 장소의 문제점이 있다.
또한 DB에 자주 I/O를 하게 될텐데 거기에 따른 문제점도 있다.
따라서 인메모리 데이터 저장소인 Redis를 사용하는 방법으로 해결할 수 있겠다.
4. DB 이용
- 페이지 접속했을 때 하루 기준으로 조회수 증가 O
- 새로고침 시 조회수 방지 O
- URI로 직접 접속해도 조회수 증가 O
- 저장 장소의 문제점
- 비회원은 어떻게 식별할 것인지에 대한 문제점
이것은 3번 IP 또는 Mac Address 이용과 비슷하다. 사실 같다고 봐도 된다.
비회원도 조회수 증가가 되어야하므로 비회원을 식별하는 방법은 IP나 Mac 주소밖에 없다.
그랬을 때 DB를 오늘 게시글 조회했는지 기록용으로 사용하기에는 성능 문제도 있다.
따라서 인메모리 데이터 저장소인 Redis를 사용한다.
📚 결론
조회수를 언제 증가시킬것인지 정의하고 구현 방법에 대해 생각하자.
서버가 확장될 가능성과 어뷰징을 막는 용도로 하기에는 3번과 4번 (같은 의미이지만)을 사용하는 것이 좋아보인다.
2번 쿠키를 사용하는 것이 나쁘지는 않지만 고의로 쿠키를 삭제하는 방법과 쿠키의 데이터량에 따른 네트워크 비용증가가 좋지 않다.
따라서 3번과 4번이 남는데 두 개는 거의 같은 의미로 썻기 때문에 결론을 내리자면 인메모리 데이터 저장소인 Redis를 활용해서 IP 또는 Mac Address와 게시글을 key-value 구조로 저장하면 제일 좋은것 같다.