좋아요 기능

Let's Just Go·2022년 8월 18일
0

Spring

목록 보기
25/26

Spring

Board Like

  • 좋아요는 게시글이 없으면 존재하지 않는 기능이며 반드시 게시글이 필요함으로 종속관계
  • 좋아요 테이블은 반드시 게시글의 번호와 좋아요를 누른 사람이 누구인지 식별할 수 있는 정보들이 포함되어야 함

Table

  • table
    • 좋아요를 누르기 위해서 필요한 정보가 들어있는 table 생성

      CREATE TABLE snslike(
          bno NUMBER(10,0) NOT NULL, 
          userID VARCHAR2(50) NOT NULL, 
          lno NUMBER primary key
      );
      
      CREATE SEQUENCE snslike_seq 
          START WITH 1
          INCREMENT BY 1
          MAXVALUE 10000
          NOCYCLE 
          NOCACHE;

VO

  • VO
    • 정보를 저장할 수 있는 VO객체 생성

      package com.spring.myweb.command;
      
      import lombok.Getter;
      import lombok.Setter;
      import lombok.ToString;
      
      @Getter
      @Setter
      @ToString
      public class SnsLikeVO {
      	
      	/*
      	 CREATE TABLE snslike(
      	    bno NUMBER(10,0) NOT NULL, 
      	    userID VARCHAR2(50) NOT NULL, 
      	    lno NUMBER primary key
      		);
      
      	CREATE SEQUENCE snslike_seq 
      	    START WITH 1
      	    INCREMENT BY 1
      	    MAXVALUE 10000
      	    NOCYCLE 
      	    NOCACHE;
      	 */
      	
      	private int bno; 
      	private String userId;
      	private int lno;
      
      }

Mapper

  • Mapper
    • 좋아요 기능을 구현하기 위해 해당 정보를 DB에서 가지고 올 수 있는 SQL문 작성

      <!-- 좋아요 검색  -->
      	<select id="searchLike" resultType="int">
      		SELECT COUNT(*) FROM snslike
      		WHERE bno = #{bno} AND userId = #{userId}
      	</select>
      	
      	<!-- 좋아요 등록  -->
      	<insert id="createLike">
      		INSERT INTO snslike(bno, userId, lno) 
      		VALUES(#{bno}, #{userId}, snslike_seq.NEXTVAL)
      	</insert>
      	
      	<!-- 좋아요 삭제  --> 
      	<delete id="deleteLike">
      		DELETE FROM snslike
      		WHERE bno = #{bno} AND userID = #{userId}	
      	</delete>

기능 구현 Code

  • 좋아요 기능 구현
    • Code

      $('#contentDiv').on('click', '#likeBtn', function(event) {
       				// 좋아요 버튼은 반복문을 돌면서 생기기 때문에 실제 존재하는 contetnDiv에서 이벤트 전파 방식 사용
       				
      			event.preventDefault();
       				console.log('좋아요 버튼 클릭');
       				
       				if (event.target.matches('img')){
       					$('#likeBtn').click();
       					return;
       				}
       				
       				const bno = $(this).attr('href');
       				// href에 묻혀져 있는 게시글 번호 가져옴 
       				const id = '${login.userId}';
       				// 현재 로그인 중인 아이디 
       				// session에서가져옴 
       				
       				if (id === ''){
       					alert('로그인한 사용자만 가능합니다.');
       					return;
       				}
       				
       				$.ajax({
       					type :'post',
       					url : '<c:url value="/snsBoard/like" />',
       					// url에 묻혀서 보낼 수 있음 
       					
       					contentType : 'application/json',
       					data : JSON.stringify({
       						'bno' : bno,
       						'userId' : id
       					}),
       					success : function(result){
       						if (result === 'like'){
       							// vanilla JS
       							
       							// 좋아요를 눌렀다면 스타일 변경 
      							event.target.firstChild.setAttribute('src', '${pageContext.request.contextPath}/img/like2.png'); 
      							// 이벤트가 발생한 곳의 html 삽입 
      							event.target.style.color = 'blue';
      							// 이벤트가 발생한 곳의 글자색을 바꿈 
      							
       							const $cnt = event.target.parentNode.previousElementSibling.children[1]; 
      							// 현재 이벤트가 발생한 곳의 부모노드의 형제 노드의 두번째 자식노드를 지목 
      							// console.log($cnt);
      							// 값을 가져오는 것을 확인 
      							$cnt.textContent = Number($cnt.textContent) + 1; 
       							// 기존의 html의 값을 숫자로 변환해서 하나 더 올려줌 
       							
       						}
       						else{
       							// vanilla JS
       							event.target.firstChild.setAttribute('src', '${pageContext.request.contextPath}/img/like1.png');
       							event.target.style.color = 'black';
       							// 이벤트가 발생항 곳의 html을 삽입하고 글자색을 변경 
       						
       							const $cnt = event.target.parentNode.previousElementSibling.children[1]; 
      							// 현재 이벤트가 발생한 곳의 부모노드의 형제 노드의 두번째 자식노드를 지목 
      							// console.log($cnt);
      							// 값을 가져오는 것을 확인 
      							$cnt.textContent = Number($cnt.textContent) -1; 
       							// 기존의 html의 값을 숫자로 변환해서 하나 더 빼
      
       							
       						}
       					},
       					error : function(){
       						alert('좋아요 기능에서 오류가 발생했습니다.');
       					}
       				}); // end ajax
       			}); // 좋아요 기능 끄읏~

    • 각 게시물의 좋아요 정보를 저장

      	let str ='';
      	let page = 1;
      	getListLike(true).done(getList);			
      	// getListLike함수에 promise를 사용해서 순서를 지목하고 해당 함수에 done을 작성하게 되면 
      	// getListLike()함수를 먼저 실행하고 getLis함수를 실행하라는 순서를 지목해줌 
      	
      	// 게시판에 들어온 회원의 종아요 게시물 목록을 받아오는 함수 
      	function getListLike(isReset){
      		let deferred = $.Deferred();
      		// jquery에서 제공하는 Deferred함수이며 함수들의 실행순서를 정할 수 있게 해줌 
      		
      		console.log('먼저 실행되어야 합니다.');
      		const userId = '${login.userId}';
      		
      		if(userId !== ''){
      			// 로그인을 한 사용자라면 
      			$.ajax({
      				type : 'post',
      				url : '<c:url value="/snsBoard/listLike" />',
      				data : userId,
      				contentType:'application/json',
      				
      				success : function(result){
      					console.log('result : ' + result); 
      					// 게시물 번호들
      					
      					if (isReset){
      						deferred.resolve(result, page, true);								
      					}
      					else {
      						deferred.resolve(result, page, false);
      					}	
      				}
      				
      				
      			}); // end ajax
      		}
      		else{
      			if (isReset){
      				deferred.resolve(null, page, true);								
      			}
      			else {
      				deferred.resolve(null, page, false);
      			}				
      		}
      		
      		return deferred.promise();
      		// 순서를 지목하기 위해 promise 사용
    • 비동기 통신은 실행되는 순서가 정해져 있지 않기 때문에 문제가 발생할 수 있음 그러므로 Deferred함수의 Promise라는 함수를 통해 순서를 부여

    • Deferred

      • 함수들의 실행순서를 정할 수 있게 해주며 비동기 통신에서 순서를 보장하기 위해 사용
      • Deferred.promise()함수를 반환
      • 먼저 실행하고자하는 함수.done(이후 실행하고자 하는 함수) 를 통해서 비동기 통신에 순서를 지목할 수 있음
    • 제약 조건 추가

    • 외래키(FK)를 참조할 때 참조하는 데이터가 삭제되는 경우 참조하고 있는 데이터도 함께 삭제 진행 (CASCADE)

      ALTER TABLE snslike ADD FOREIGN KEY(bno) 
      REFERENCES snsboard(bno)
      ON DELETE CASCADE;
      -- foreign key로 참조하는 데이터가 사라지면 참조를 하고 있는 데이터도 함께 삭제
      
      ALTER TABLE snslike ADD FOREIGN KEY(userId)
      REFERENCES USERS(userid)
      ON DELETE CASCADE;

Controller

  • Controller
    • Code

      // 좋아요 버튼 클릭 처리 
      	@PostMapping("/like")
      	@ResponseBody
      	public String likeConfirm(@RequestBody SnsLikeVO like) {
      		// JSON으로 값이 들어오기 때문에 @RequestBody와 커맨드 객체를 사용해서 JSON 타입을 객첼 변경 
      		System.out.println("/snsBoard/like : POST ");
      		System.out.println("좋아요 기능 값을 가져오는지 확인 : " + like);
      		
      		// 좋아요 버튼은 버튼이 하나임으로 버튼을 클릭 유무에 따라 좋아요 선택 및 취소를 뜻
      		
      		int result = service.searchLike(like);
      		// 좋아요를 눌렀다면 1이 오고 좋아요를 누르지 않았다면 0이 옴 
      		
      		if(result == 0) {
      			// 좋아요를 누르지 않았다면 해당 정보를 db에 저장 
      			service.createLike(like);
      			return "like";
      		}
      		else {
      			// 좋아요를 눌렀으므로 db에서 해당 값 삭제 
      			service.deleteLike(like);
      			return "delete";
      		}
      	}
      	
      	// 회원이 글 목록 진입시 좋아요 게시물 수 체크 
      	@PostMapping("/listLike")
      	@ResponseBody
      	public List<Integer> listLike(@RequestBody String userId){
      		System.out.println("/snsBoard/listLike : POST");
      		System.out.println("좋아요 게시물 체크 : " + userId);
      		
      		List<Integer> likeList = service.listLike(userId);
      		System.out.println(likeList);
      		return likeList;
      		
      	}
profile
안녕하세요! 공부한 내용을 기록하는 공간입니다.

0개의 댓글