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와 중복되는지 체크함