국비 91 - 조회수-쿠키 사용(스프링)

냐아암·2023년 8월 23일
0

국비

목록 보기
106/114

비회원, 작성자가 본인이 아닌 글의 회원은 하루에 한 번 조회수를 1 증가할 수 있다.

🔑 게시글 상세조회를 할 때 조회수가 증가됨
-> 쿠키에 접속한 게시글의 번호를 저장해 하루에 한 번 증가하게 만듦

Controller

// 게시글 상세 조회
	@GetMapping("/{boardCode}/{boardNo}")
	public String boardDetail(@PathVariable("boardCode") int boardCode
								, @PathVariable("boardNo") int boardNo
								, Model model /*데이터 전달용 객체*/
								, RedirectAttributes ra /*리다이렉트 시 데이터 전달용 객체*/
								, @SessionAttribute(value="loginMember", required=false) Member loginMember
									// 세션에서 로그인 멤버를 얻어오는데 없으면 null, 있으면 회원 정보 저장
								
								// 쿠키를 이용한 조회수 증가에서 사용 
								, HttpServletRequest req
								, HttpServletResponse resp
								) throws ParseException {
		Map<String, Object> map = new HashMap<String, Object>();
		
		map.put("boardCode", boardCode);
		map.put("boardNo", boardNo);
		
		// 게시글 상세 조회 서비스 호출
		Board board = service.selectBoard(map);
		
		String path = null;
		
		if(board != null) { // 조회 결과가 있을 경우
			
			// ---------------------------------------------
			// 현재 로그인 상태인 경우
			// 로그인 한 회원이 해당 게시글에 좋아요를 눌렀는지 확인
			
			
			if(loginMember != null) { // 로그인 상태인 경우
				// 회원번호를 map에 추가
				// map(boardCode, boardNo, memberNo)
				map.put("memberNo", loginMember.getMemberNo());
				
				// 좋아요 여부 확인 서비스 호출
				int result = service.boardLikeCheck(map);
				
				// 좋아요를 누른 적이 있을 경우
				if(result>0) model.addAttribute("likeCheck", "on");
				
			}
			
			// ---------------------------------------------
			
			// 쿠키를 이용한 조회수 증가 처리
			// 1) 비회원 또는 로그인한 회원의 글이 아닌 경우
			if(loginMember == null ||  // 비회원도 그냥 조회수 증가하게 할게요
					loginMember.getMemberNo() != board.getMemberNo()
					) {
				// 2) 쿠키 얻어오기
				Cookie c = null;
				
				// 요청에 담겨있는 모든 쿠키 얻어오기
				Cookie[] cookies = req.getCookies();

🔑 "readBoard"라는 쿠키가 존재한다면 그 쿠키를 c에 대입

  • c에 현재 게시판 번호가 없다면 게시판 번호를 쿠키에 추가 -> DB에서 조회수 증가 -> 조회수 동기화 -> 쿠키 수명 지정
  • c에 현재 게시판 번호가 있다면 그대로 조회수 관련 메소드 종료

🔑 "readBoard"라는 쿠키가 존재하지 않는다면 -> 쿠키 생성(게시판 번호가 value) -> DB에서 조회수 증가 -> 조회수 동기화 -> 쿠키 수명 지정

				
				if(cookies != null) { // 쿠키가 존재할 경우
					
					// 쿠키 중 "readBoardNo"라는 쿠키를 찾아 c에 대입
					for( Cookie cookie : cookies) {
						if(cookie.getName().equals("readBoardNo")) {
							c = cookie;
							
							break;
						}
					}
				}
				
				
				int result = 0;
				
				// 3) 기존 쿠키가 없거나(c==null)
				//	  존재는 하나, 현재 게시글 번호가 쿠키에 저장되지 않은 경우(오늘 해당 게시글 본 적 없음)
				if(c == null) {
					
					// 쿠키가 존재 X -> 하나 새로 생성
					c = new Cookie("readBoardNo", "|" + boardNo + "|");
					
					// 조회수 증가하는 서비스 호출
					result = service.updateReadCount(boardNo);
					
				} else {
					
					// 현재 게시글 번호가 쿠키에 있는지 확인
					
					// Cookie.getValue() : 쿠키에 저장된 모든 값을 읽어옴
					//					-> String으로 반환
					
					// String.indexOf("문자열")
					// : 찾는 문자열이 몇 번 인덱스에 존재하는지를 반환
					//	 단, 없으면 -1 반환
					if(c.getValue().indexOf("|" + boardNo + "|") == -1) {
						
						// 쿠키에 현재 게시글 번호가 없다면
						
						// 기존 값에 게시글 번호 추가해서 다시 세팅
						c.setValue(c.getValue() + "|" + boardNo + "|");
						
						// 조회수 증가 서비스 호출
						result = service.updateReadCount(boardNo);
						
					}
					
				} // 3) 종료
				
				// 4) 조회수 증가 성공 시 
				//	  쿠키가 적용되는 경로, 수명(당일 23시 59분 59초) 지정
				if(result>0) {
					
					// 조회된 board의 조회수와 DB의 조회수를 동기화
					board.setReadCount(board.getReadCount() + 1);
					
					c.setPath("/"); // "/" 이하 경로 요청 시 쿠키 서버로 전달
					
					// 수명 지정
					Calendar cal = Calendar.getInstance(); // 싱글톤 패턴
					cal.add(cal.DATE , 1);
					
					// 날짜 표기법 변경 객체(DB의 TO_CAHR()과 비슷)
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
					
					// java.util.Date
					Date a = new Date(); // 현재 시간
					
					Date temp = new Date(cal.getTimeInMillis()); // 내일(24시간 후)
					// 내일 시간이 2023-08-24 12:17:40
					
					Date b = sdf.parse(sdf.format(temp)); // 내일 0시 0분 0초
					
					// 내일 0시 0분 0초 - 현재 시간 
					long diff = (b.getTime() - a.getTime()) / 1000;
					// 내일 0시 0분 0초까지 남은 시간 반환
					
					c.setMaxAge((int)diff); // 수명 설정
					
					resp.addCookie(c); // 응답 객체를 이용해서 클라이언트에게 전달
					
				}
			}
			
			model.addAttribute("board",board);
			path = "board/boardDetail";
			
		} else {
			path ="redirect:/board/" + boardCode; // 게시판 첫 페이지로 리다이렉트
			ra.addFlashAttribute("message", "존재하지 않는 게시글입니다.");
		}
		
		return path;
	}
	
	@PostMapping("/like")
	@ResponseBody // 반환되는 값이 비동기 요청한 곳으로 돌아가게 함
	public int like(@RequestBody Map<String, Integer> paramMap) {
		
		// System.out.println(paramMap);
		
		return service.like(paramMap);
	}
profile
개발 일지

0개의 댓글