글 조회시 조회수 중복 증가 방지를 위해 Session VS Cookie
팀 프로젝트를 진행하면서 글의 조회수를 조작해서 방금 올렸던 글을 자기 자신이 100번 새로고침하면 조회수가 100회가 되는 마술이 있었습니다.
따라서 글의 조회수 중복 증가를 방지하지 위해 글 조회시 이전에 조회를 했던 이력이 있다면 조회수가 증가하지 않도록 구현하고싶었습니다.
처음에 나왔던 의견이 세션 스토리지를 활용하는 것이었습니다.
세션 스토리지를 활용한 흐름은 아래처럼 흘러갑니다.
1. 글을 조회 요청이 오면 세션에 글의 고유 ID를 키(Key)로 하는 값이 존재하는지 확인합니다.
2. 세션에 글의 고유ID가 존재하지 않는다면 세션 스토리지에 글의 고유 ID를 Key로 저장하고 글의 조회수를 증가시키고 글의 정보를 응답해줍니다.
3. 세션에 글의 고유 ID가 존재한다면 글의 조회수를 증가시키지 않고 글의 정보만 응답합니다.
이를 위해서 Redis까지 활용하려고 했습니다.
하지만! 현재 세션에 저장하려는 정보가 보안이 필요한 정보인가? 쿠키 쓰면 안돼? 라는 의문을 페어인 아마찌가 제안했고
그렇다면 근본적으로 세션은 왜 쓰는가? 라고 생각하여 현재 조회수 중복 증가 방지에는 세션이 개미잡는데 도끼를 쓰는 방법이라 했습니다.
생각해보니 세션도 어차피 쿠키로 JSESSIONID를 관리하게 될것이고 Session에 저장하고자 하는 글의 고유 ID는 누군가 탈취해도 아무 문제가 되지 않을것입니다. 세션을 쓰는것은 추가 비용만을 발생한다고 생각하여 쿠키로 구현하기로 했습니다.
쿠키로 구현하는 것도 결국 세션과 비슷한 흐름으로 갑니다.
1. 글을 조회 요청이 오면 HttpServletRequest에 글의 고유 ID를 키(Key)로 하는 쿠키가 존재하는지 확인합니다.
2. 글의 고유ID 쿠키가 존재하지 않는다면 글의 고유 ID를 Key로 쿠키를 추가하고 글의 조회수를 증가시키고 글의 정보를 응답해줍니다.
3. 글의 고유ID 쿠키가 존재한다면 글의 조회수를 증가시키지 않고 글의 정보만 응답합니다.
세션 -> 쿠키들로 바뀌었을 뿐입니다.
하지만 한가지 문제가 있습니다. 클라이언트(브라우저)에는 쿠키의 저장용량, 저장 개수가 한정 되어있습니다.
보통 아래에 적힌것이 표준안입니다.
- 총 300개
- 하나의 도메인 당 20개
- 하나의 쿠키 당 4kb(=4096byte)
하지만 대부분의 브라우저는 위의 표준안보다 훨씬 적은 개수를 사용할 수 있다고 합니다..
그렇다면 어떤 방법이 있을까요?
현재는 하나의 클라이언트(브라우저)에서 1개의 글을 조회하면 1개의 쿠키가 생깁니다.
표준안에 따르면 하나의 도메인에 20개밖에 저장할 수 없기때문에 20개 이상의 글을 조회하면 다시 조회수 조작이 가능한 상태가 됩니다.
대안으로 하나의 쿠키에 "1/2/3/4/5" 이런식의 문자열로 여러개의 저장해서 split 하는 방법도 있습니다.
이렇게 된다면 모든 글이 하나의 쿠키 제한시간에 묶이기 때문에 쿠키의 수명이 다하기 1초전에 조회한 글이라면 1초 후에 쿠키가 수명을 다하면 다시 조회가 가능하다는 단점이 있습니다.
하지만 저렇게 1초의 타이밍으로 조회를 두번해도 결국 쿠키의 수명시간을 또 기다려야하기 때문에 조회수 중복증가를 충분히 지연할 수 있다고 생각합니다.
현재는 이것이 최선의 방법이라 생각하지만 더 효율적인 방법을 찾아봐야겠습니다.
댓글로 의견도 환영입니다!!