🚨 이슈 상황
게시글을 조회했을 때 조회수가 증가해야하는 데, 새로고침을 해도 조회수가 계속 증가하는 문제가 생겼다.
이를 보완하기 위해 찾아보다가 쿠키로 적용 시킨 방법이다.
🔎 개선 방안
💡 IP
- 장점
- 조작이 불가능하다(해킹하지않는한)
- 단점
- IP는 장소에 따라 유동적으로 변할 수 있는 문제점이 있다.
- MAC 주소와 같은 유저라도 다른 기기라면 다른 유저로 식별하게 된다.
- IP와 MAC 주소는 값이 길기 때문에 수많은 유저와 수많은 게시글과 날짜를 함께 저장하기에 문제가 있다.
💡 세션
- 세션의 특징으로는 사용자 정보를 서버에서 관리하는 것입니다.
- 장점
- 사용자 정보를 서버에 둔다는 뜻은 쿠키보다 보안에 좋다.
- 저장데이터에 제한이 없다.(서버 성능에 따라 다름)
- 단점
- 서버에 데이터를 저장한다는 것은 서버의 리소스를 사용하는 것이기 때문에 세션 양이 많아진다면 서버에 부하가 커집니다. 따라서, 비용, 성능과 직결될 수 있는 문제가 발생 가능합니다.
💡 쿠키
- 쿠키의 특징으로는 웹사이트에 접속할 때 생성되는 정보를 담은 임시 파일입니다.
- 쿠키의 데이터 형태는 Key 와 Value 로 구성되어있고 String 형태로 이루어져 있습니다.
- 장점
- 서버의 공간이 절약 가능합니다. 따라서, 서버의 비용, 성능 개선에 도움이 됩니다.
- 단점
- 개인의 정보가 기록된다면 사생활을 침해할 소지가 있습니다.
- 서버가 가지고 있는 것이 아니라 사용자에게 저장되기 때문에, 임의로 고치거나 지우는 것이 가능하고, 가로채기도 쉬워 보안에 취약합니다.
📌적용
👉 기존 조회수 +1 코드
BoardService.java
// 조회
public BoardResponseDto getPostById(Long id, HttpServletRequest request, HttpServletResponse response) {
Board entity = postsRepository.findById(id).orElseThrow(IllegalArgumentException::new);
updateView(id);
return new BoardResponseDto(entity);
}
// 조회수 ++
public int updateView(Long id) {
return postsRepository.updateView(id);
}
이렇게 코드를 작성하여 게시글이 조회될 때마다 증가가 가능하지만 같은 사용자에 한해서도 무한정 조회수가 증가 할 수 있게 됩니다. 그래서 조회 수 중복 count를 어떻게 방지할 수 있을지 고민해보았습니다.
✨ 쿠키로 구현한 이유?
- 쿠키의 단점은 보안 이슈인데 조회수는 개인정보를 넣지 않고 단순 조회수 증가로직에만 사용할 것이기 때문에 문제가 되지 않을 것이다라고 생각하였다.
👉 코드 작성
BoardService.java
// 조회
public BoardResponseDto getPostById(Long id, HttpServletRequest request, HttpServletResponse response) {
Board entity = postsRepository.findById(id).orElseThrow(IllegalArgumentException::new);
// 조회 수 중복 방지
Cookie oldCookie = null;
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for(Cookie cookie : cookies) {
if(cookie.getName().equals("postView")) {
oldCookie = cookie;
}
}
}
if(oldCookie != null) {
if(!oldCookie.getValue().contains("[" + id.toString()+ "]")) {
updateView(id);
oldCookie.setValue(oldCookie.getValue() + "_[" + id + "]");
oldCookie.setPath("/");
oldCookie.setMaxAge(60*60*24);
response.addCookie(oldCookie);
}
} else {
updateView(id);
Cookie newCookie = new Cookie("postView", "[" + id + "]");
newCookie.setPath("/");
newCookie.setMaxAge(60*60*24);
response.addCookie(newCookie);
System.out.println(newCookie);
}
return new BoardResponseDto(entity);
}
- 클라이언트로 요청이 들어온다.
- 요청에 Cookie가 없고 글을 조회한다면 [게시글ID]의 값을 추가하여 Cookie생성 (기간은 하루로 설정)
- 요청에 Cookie가 있고 글을 조회한 기록이 있다면 pass 없다면 Cookie에 [게시글ID] 붙이기
👉 결과 확인
게시글에 대한 조회수는 중복으로 올라가지 않는 것으로 확인된다.
🚨 문제점
- 1번 글을 읽는다. -> 쿠키 상태 : [1] (age 하루인 상태)
- 하루가 지나기전에 다른 글을 읽는다. -> [1]_[2] (다시 age가 하루로 바뀜)
위와 같은 상황이 반복된다면 하루 이틀 일주일이 지나더라도 1번 글을 조회할 때 조회수가 count가 되지 않는 문제가 발생하게 됩니다.
이 문제를 해결하기 위해서는 위에서 작성했던 코드처럼 작성하는 것이 아니라 게시글 각각 cookie를 생성하는 방법을 생각 해볼 수 있었습니다.
하지만 이것 또한 문제가 발생한다. 클라이언트에는 쿠기의 저장용량, 저장개수가 한정되어있기 때문이다.
보통 아래에 적혀있는 것이 표준안 이라고 한다.
- 총 300개
- 하나의 도메인당 20개
- 하나의 쿠키당 4kb(=4096byte)
게시글마다 cookie를 생성하게 된다면 21개 이상의 글을 조회하는 순간 쿠키가 생성되지 않게된다.
⭐ Cookie 문제점 개선 방안
요즘 사용자들이 쿠키를 많이 차단하는 추세이고 동시성 이슈를 해결할 수 있는 Redis 로도 개선이 가능하다고 한다.
Redis 를 적용해서 개선 후 이후에 다시 포스팅 해보기로 하자.
'🎨 Programming > Spring Boot' 카테고리의 다른 글
[Spring Boot 입문] View 환경설정 (0) | 2022.01.25 |
---|---|
[Spring Boot 입문] 프로젝트 생성 (Feat. IntelliJ) (0) | 2022.01.24 |