본문 바로가기

SpringBoot

SpringBoot(35) - Ajax 예제4(추천수 Counting / 아이디 중복 확인 기능 구현)

728x90
반응형

1) SpringBoot

    1-1) Ajax 예제4

      1-1-1) 추천수 Counting / 아이디 중복 확인 기능 구현

 

 

 

 

 

1) SpringBoot

1-1) Ajax 예제4

1-1-1) 추천수 Counting / 아이디 중복 확인 기능 구현

(1) [src/main/resources] - [templates] 안에 home.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>test_ajax</title>
</head>
<body>
	<h1>[ Ajax 예제 ]</h1>
	
	<p>
		<a href="ajax1">Ajax 테스트 페이지 1</a>
	</p>
	<p>
		<a href="ajax2">Ajax 테스트 페이지 2</a>
	</p>
	<p>
		<a href="like">추천 테스트</a>
	</p>
	<p>
		<a href="idDuplicate">ID 중복확인 테스트</a>
	</p>
	
</body>
</html>

 

 

(2) [src/main/resources] - [templates] 안에 like.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>test_ajax</title>
	<script src="/js/jquery-3.7.1.min.js"></script>
	<script>
		$(document).ready(function() {
			// ID가 "bt"인 버튼을 클릭하면 num 속성의 값을 읽어서 ajax() 함수로 보낸다.
			$("#bt").click(function() {
				let num = $("#bt").attr("data-num");
				// let num = $(this).data("num");  --> 위의 코드와 동일한 동작을 수행함(이렇게 써도 됨)
				
				$.ajax({
					url: "like",
					type: "post",
					data: {num : num},     // 추천할 글 번호를 1로 테스트
					dataType: "text",
					success: function(cnt) {
						$("#view").html(cnt);
					},
					error: function(e) {
						alert("저장 실패");
					}
				});
			});
			
		});
	</script>
</head>
<body>
	<h1>[ 추천 테스트 ]</h1>
	
	<p><button id="bt" data-num="1">추천</button></p>
	<div id="view">0</div>
</body>
</html>

 

 

(3) [src/main/resources] - [templates] 안에 IdDuplicate.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>test_ajax</title>
	<script src="/js/jquery-3.7.1.min.js"></script>
	<script>
		$(document).ready(function() {
			// id가 "id"인 입력란의 keyup 이벤트 처리 --> 입력한 내용 읽어옴
			$("#id").keyup(function() {
				// 읽어온 문자열을 id가 "msg"인 객체에 출력
				let id = $(this).val();
				
				if (id.length < 3 || id.length > 10) {
					// id가 msg인 곳에 메시지 출력
					$("#msg").html("ID는 3 ~ 10 글자로 입력해주시기 바랍니다.");
					// 글자색은 빨간색으로
					$("#msg").css("color", "red");
					// 가입 버튼은 비활성화함
					$("#submitButton").attr("disabled", true);
					
					return;    // 함수를 종료시키기 위해 return을 추가함!
				}
				
				$.ajax({
					// 입력한 아이디를 서버로 보냄
					// DB에 이미 저장된 아이디이면 true, 없으면 false를 리턴받음
					// true이면 id가 "msg"인 곳에 "이미 사용중인 아이디입니다."를 빨간 글자로, 가입버튼 비활성화함
					// false이면 "사용가능한 아이디입니다."를 파란 글자로, 가입버튼 활성화함.
					url: "idDuplicate",
					type: "post",
					data: {id : id},
					dataType: "json",    // 이 부분을 "text" 타입으로 받을 경우, boolean 타입이 아닌 String 타입으로 인식해버리기 때문에 반드시 "json" 타입으로 데이터 타입을 지정해야 한다.
					success: function(idCheckResult) {
						if (idCheckResult) {
							$("#msg").html("이미 사용중인 아이디입니다.");
							$("#msg").css("color", "red");
							$("#submitButton").attr("disabled", true);
						} else {
							$("#msg").html("사용가능한 아이디입니다.");
							$("#msg").css("color", "blue");
							$("#submitButton").attr("disabled", false);
						}
					},
					error: function(e) {
						alert("저장 실패");
					}
				});
				
			});
		});
	</script>
</head>
<body>
	<h1>[ 아이디 중복 확인 테스트 ]</h1>
	
	<form>
		<p>
			ID <input type="text" id="id"> <span id="msg"></span>
		</p>
		<p><button type="submit" id="submitButton">가입</button></p>
	</form>
</body>
</html>

 

 

(4) [src/main/java] - [net.datasa.test_ajax.domain.entity] 안에 BoardEntity.java 파일 생성 후 아래와 같이 작성

package net.datasa.test_ajax.domain.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 게시글 entity
 * */
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="ajax_board")
public class BoardEntity {
	@Id
	@Column(name="num")
	private Integer num;
	
	@Column(name="cnt", columnDefinition = "int default 0")
	private Integer cnt;
}

 

 

(5) [src/main/java] - [net.datasa.test_ajax.repository] 안에 BoardRepository.java 파일 생성 후 아래와 같이 작성

package net.datasa.test_ajax.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import net.datasa.test_ajax.domain.entity.BoardEntity;

/**
 * 게시판 repository
 * */
@Repository
public interface BoardRepository extends JpaRepository<BoardEntity, Integer> {

}

 

 

(6) [src/main/java] - [net.datasa.test_ajax.domain.entity] 안에 MemberEntity.java 파일 생성 후 아래와 같이 작성

package net.datasa.test_ajax.domain.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="ajax_member")
public class MemberEntity {
	@Id
	@Column(name="id")
	private String id;
	
	@Column(name="name", nullable = false)
	private String name;
}

 

 

(7) [src/main/java] - [net.datasa.test_ajax.repository] 안에 MemberRepository.java 파일 생성 후 아래와 같이 작성

package net.datasa.test_ajax.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import net.datasa.test_ajax.domain.entity.MemberEntity;

@Repository
public interface MemberRepository extends JpaRepository<MemberEntity, String> {

}

 

 

(8) [src/main/java] - [net.datasa.test_ajax.controller] 안에 Ajax3Controller.java 파일 생성 후 아래와 같이 작성

package net.datasa.test_ajax.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.test_ajax.service.AjaxService;

@Slf4j
@RequiredArgsConstructor
@Controller
public class Ajax3Controller {
	
	// 메모리에 객체를 미리 만들어 필요할 때 불러서 사용하기 위한 것이 "bean"이다!
	private final AjaxService ajaxService;
	
	// 추천 페이지로 이동
	@GetMapping("like")
	public String like() {
		return "like";
	}
	
	// 추천 처리
	@ResponseBody
	@PostMapping("like")
	public int like(@RequestParam("num") int num) {
		
		int cnt = ajaxService.like(num);
		
		log.debug("추천 처리된 값 : {}", cnt);
		
		return cnt;
	}
	
	// 아이디 중복 확인 페이지로 이동
	@GetMapping("idDuplicate")
	public String idDuplicate() {
		return "IdDuplicate";
	}
	
	// 아이디 중복 확인 처리
	@ResponseBody
	@PostMapping("idDuplicate")
	public boolean idDuplicate(@RequestParam("id") String id) {
		
		log.debug("입력한 아이디 값 : {}", id);
		
		boolean result = ajaxService.idDuplicate(id);
			
		log.debug("아이디 중복 확인한 결과값 : {}", result);
			
		return result;
	}
	
}

 

 

(9) [src/main/java] - [net.datasa.test_ajax.service] 안에 AjaxService.java 파일 생성 후 아래와 같이 작성

package net.datasa.test_ajax.service;

import org.springframework.stereotype.Service;

import jakarta.persistence.EntityNotFoundException;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.test_ajax.domain.entity.BoardEntity;
import net.datasa.test_ajax.repository.BoardRepository;
import net.datasa.test_ajax.repository.MemberRepository;

/**
 * 게시판 service
 * */
@Slf4j
@RequiredArgsConstructor
@Service
@Transactional
public class AjaxService {
	
	private final BoardRepository boardRepository;
	private final MemberRepository memberRepository;

	public int like(int num) {
		// 전달된 번호로 게시글 조회. 없으면 예외 발생시킴.
		BoardEntity boardEntity = boardRepository.findById(num)
				.orElseThrow(() -> new EntityNotFoundException("게시글이 없습니다."));
		
		// 있으면 현재 추천수 읽어서 +1하여 다시 저장.
		int likeCount = boardEntity.getCnt() + 1;
		
		// "@Transactional" annotation 덕분에 자동 commit이 되기 때문에
		// entity의 내용만 수정해주면 알아서 DB에 그 내용이 저장되도록 처리됨.
		// 그래서 바로 아래와 같이 entity의 내용(추천수)만 수정해주면 됨
		boardEntity.setCnt(likeCount);
		
		// 증가된 추천수를 return.
		return likeCount;
	}

	public boolean idDuplicate(String id) {
		boolean idDuplicateResult = memberRepository.existsById(id);
		
		return idDuplicateResult;
	}
	
	
}

 

 

(10) 결과 화면

첫 접속 화면

 

 

"추천 테스트" 화면

- "추천" 버튼 클릭 시 1씩 계속해서 증가함

- 해당 추천수는 증가시킬 때마다 그 결과가 DB에 저장됨

 

 

 

 

 

 

"ID 중복확인 테스트" 화면

- 입력한 아이디의 값을 "keyup" 이벤트를 통해 실시간으로 글자수 맞는지, 입력한 ID가 기존의 ID와 중복되는지 체크함