본문 바로가기

Spring

SPRING (08.26) - 좋아요 ajax 적용

<!-- 좋아요 싫어요  -->

<script>

<!-- 좋아요 싫어요 버튼	-->

	function checkRP() {

		var goodReaction = $('#likeCount'); 

		var badReaction = $('#DislikeCount');

		
		localStorage.setItem("goodReaction", goodReaction);

		localStorage.setItem("badReaction", badReaction);

		
		if (isAlreadyAddGoodRp == true) {

			$('#likeButton').toggleClass('btn-outline');

		} else if (isAlreadyAddBadRp == true) {

			$('#DislikeButton').toggleClass('btn-outline');

		} else {

			return;

		}

	}



	function doGoodReaction(articleId) {

		$.ajax({

			url : '/user/reactionPoint/doGoodReaction',

			type : 'POST',

			data : {

				relTypeCode : 'article',

				relId : articleId

			},

			dataType : 'json',

			success : function(data) {
				console.log(data);

				console.log('data.resultCode: ' + data.resultCode);
				if (data.resultCode.startsWith('S-')) {

					var likeButton = $('#likeButton');

					var likeCount = $('#likeCount');

					var DislikeButton = $('#DislikeButton');

					var DislikeCount = $('#DislikeCount');

					//return ResultData.from("S-1", "좋아요 취소");
					if (data.resultCode == 'S-2') {

						likeButton.toggleClass('btn-outline'); 

						likeCount.text(parseInt(likeCount.text()) -1);
						console.log(data.resultCode);

						console.log(1);

						console.log('likeCount.text() : ' + likeCount.text());

						console.log('DislikeCount.text() : ' + DislikeCount.text());
                        
					//return ResultData.from("S-2", "싫어요 했었음");	

					} else if (data.resultCode == 'S-3') {

						console.log(data.resultCode);

						DislikeButton.toggleClass('btn-outline');

						DislikeCount.text(parseInt(DislikeCount.text()) - 1); 
                        
						console.log('likeCount.text() : ' + likeCount.text());

						console.log('DislikeCount.text() : ' + DislikeCount.text());

						likeButton.toggleClass('btn-outline');

						likeCount.text(parseInt(likeCount.text()) + 1);


						console.log(2);

						console.log('likeCount.text() : ' + likeCount.text());

						console.log('DislikeCount.text() : ' + DislikeCount.text());

					} else {

						likeButton.toggleClass('btn-outline');

						likeCount.text(parseInt(likeCount.text()) + 1);

						console.log(3);

						console.log('likeCount.text() : ' + likeCount.text());

						console.log('DislikeCount.text() : ' + DislikeCount.text());

					}

				} else {

					alert(data.msg);

				}

			},

			error : function(jqXHR, textStatus, errorThrown) {

				alert('좋아요 오류 발생 : ' + textStatus);

			}



		});

	}
    
	$(function() {

		checkRP();

	});

</script>

.
.

				<tr>

					<th style="text-align: center;">Dislike</th>

					<td id="DislikeCount" style="text-align: center;">${article.badReactionPoint}</td>

				</tr>

				<tr>

					<th style="text-align: center;">LIKE / Dislike / ${usersReaction }</th>

					<td style="text-align: center;">



						<button id="likeButton" class="btn btn-outline btn-success" onclick="doGoodReaction(${param.id})">👍 LIKE

							<span id="likeCount">${article.goodReactionPoint}</span></button>

						<button id="DislikeButton" class="btn btn-outline btn-error" onclick="doBadReaction(${param.id})">👎

							DISLIKE <span id="DislikeCount" >${article.badReactionPoint}</span></button>

	
						<%-- 						<a href="/usr/reactionPoint/doGoodReaction?relTypeCode=article&relId=${param.id }&replaceUri=${rq.currentUri}" --%>

						<%-- 							class="btn btn-outline btn-success">👍 LIKE ${article.goodReactionPoint}</a> --%>

						<%-- 						<a href="/usr/reactionPoint/doBadReaction?relTypeCode=article&relId=${param.id }&replaceUri=${rq.currentUri}" --%>

						<%-- 							class="btn btn-outline btn-error">👎 DISLIKE ${article.badReactionPoint}</a> --%>

					</td>

				</tr>
.
.
.

 

위 코드 실행 시 오류발생

위 코드 실행시 오류가 나는데, 문제는

  1. 좋아요, 싫어요 버튼의 숫자 X
  2. 싫어요를 눌러도 싫어요 대신 좋아요가 증가
  3. 새로고침 시 기존 sql에 테스트 데이터로 남겨둔 값으로 되돌아옴 (리셋 처럼)
  4. 로그인한 회원은 좋아요 한번 밖에 하지 못하는데 무한으로 좋아요 가능( 좋아요 2번 눌렀을 경우 취소가 되어야 하는데 그 부분이 작동하지 않는 것 같음)
<button id="DislikeButton" class="btn btn-outline btn-error" onclick="doGoodReaction(${param.id})">👎
							DISLIKE ${article.badReactionPoint}</button>

 

여기서 bad가 doGoodReaction으로 설정되어있어서 계속 좋아요만 눌린 듯 -> badReaction으로 변경

 


 

data : {
				relTypeCode : 'article',
				relId : articleId
			},

 

실행할 때의 필요한 정보(url인 doGoodReaction에 들어갈 파라미터)

 

success : function(data) {

 

는 user/reactionPoint/doGoodReaction 실행되고 난 뒤의 결과값

 


 

if (data.resultCode == 'S-1') {

						likeButton.toggleClass('btn-outline');
						likeCount.text(parseInt(likeCount.text()) -1);

						console.log(data.resultCode);
						console.log(1);
						console.log('likeCount.text() : ' + likeCount.text());
						console.log('DislikeCount.text() : ' + DislikeCount.text());

 

toggleClass는 그 클래스를 제거하고, 클래스가 없으면 추가한다. 이 메서드는 주로 특정 이벤트(클릭)가 발생할 때 요소의 시각적 상태를 변경하는데 사용된다.

위의 코드에서는 버튼의 색깔을 채우거나, 지우거나 할 때

likeCount 즉, Like의 개수가 몇개인지

좋아요 버튼을 처음 누를 때와, 2번 눌렀을 때 resultCode가 뭐라고 들어오는지 확인 결과 S-1으로 넘어오는 것을 확인하였다.
resultCode를 각 문제에 대한 세세한 분류가 잘 안되어있이게 이런 문제가 발생한 것이다.

 


 

위 코드 해결 진행 과정

doGoodReaction -> doBadReaction으로 바꿔줌으로써
좋아요 클릭 후 싫어요 클릭하면 좋아요 취소 -1 되고, 싫어요 +1은 정상 작동 하나
좋아요 클릭 후 좋아요 계속 누르면 계속 좋아요 증가된다.

회원이 들어왔을때 한버튼을 계속 누르면 증가하지않고, 취소되도록만 만들면 될 듯, 그리고 버튼의 수가 같이 변하도록 만들어야 한다.

  1. 단순히 좋아요 취소를 다른 success code를 가지도록 변경해주기 (S-2), 싫어요 했었음을 (S-3)
    -> 시도해보았을때 실행되고 있는 것처럼 보인다. (되는건가..?)
  2. 똑같은 방법으로 badreaction에도 적용

// 되는 것처럼 보인다.

이제 문제는 새로고침 시 저장되지 않고, 돌아간다. 이 문제는 어떻게 해결해야할까?

로컬스토리지 사용해서 세션?에 저장해서 새로고침해도 리셋되지 않도록

-> 로컬스토리지 적용 후, 새로고침 하여도 초기화되지 않고 저장된 모습을 볼 수 있었다.

문제는 버튼 숫자가 변경이 되지않음.. 왜? -> id를 class로 변경해서 확인해보자
버튼숫자와, 행의 번호와 동일하게 변경되긴하지만, class로 변경하니 이상하게 숫자가 정상적으로 기입되지 않는다.. 뭐가 문제지

 

해결안됨 뭐야 도대체

 

id는 고유 식별자로 여러요소에 할당되지 않고, 한번만 활용 가능.. 분명 공부했던 부분인데.. 으아아 맞다..

이렇게 해서 좋아요, 싫어요 기능은 작동되는 것처럼 보인다.


 

다른 해결법✨

제시된 코드 DislikeCount.text(parseInt(DislikeCount.text()) - 1); 처럼, 현재 count 값을 텍스트로 가져와서 이를 정수로 변환한 후, 직접 -1을 계산하여 값을 다시 설정하는 방식이다. 즉, 자바스크립트에서 계산을 수행하고, 해당 값을 화면에 업데이트 하고 있다.

하지만 이렇게 할 필요가 없다. 왜냐하면 이미 controller, service, repository에서 데이터의 요청과 변경을 처리하고 있다. 그러니 따로 계산을 수행하지 않고, 서버에서 실시간으로 업데이트된 값을 가져와서 화면에 덮어쓰는 방식으로 처리하는 것이 더 효율적이다.

따라서 서버로부터 최신 데이터를 요청하고, 이를 화면에 반영하는 방식으로 구현하는 것이 더 적절해보인다!