[Spring] 검사 기능 만들기
회원가입 시 아이디, 이메일 등 중복검사를 위한 기능을 구현하기 전에 이런 기능을 구현할 수 있는 AJAX에 대해 간단히 알아보자.
AJAX는 ‘Asynchronous JavaScript And XML’의 약자로, 말 그대로 JavaScript와 XML 형식을 이용한 비동기적 정보 교환 기법이다.
js 코드로 서버에 요청 / 응답을 할 수 있다.
새로고침 시 전체 페이지를 새로 가져오는 것이 아니라, 전체 페이지 중 일부만 가져오는 것이 가능하다.

이미지 하단의 뉴스 더보기 버튼이 여기에 해당하며, 누르면 뉴스 영역만 서버에 요청한다.
과거에는 다른 방법으로 ajax를 사용했으나, jquery 점유율이 높아지며 주로 jquery를 이용해 실행한다.
그럼 회원가입 시 아이디, 이메일 등의 간단한 중복검사는 어떻게 하는지 코드를 통해 알아보자.
1. View

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ko">
<head>
<meta charset="utf-8">
<title>bookmark</title>
<!-- bootstrap -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
</head>
<body>
<div id="wrap" class="container">
<h1>add bookmark</h1>
<div class="form-group">
<label>name</label>
<input type="text" id="name" class="form-control">
</div>
<div class="form-group">
<label>url</label>
<div class="d-flex">
<input type="text" id="url" class="form-control" placeholder="http:// or https://">
<input type="button" id="checkBtn" class="btn btn-primary ml-3" value="중복확인">
</div>
<small id="statusArea"></small>
</div>
<input type="button" id="addBtn" class="btn btn-success w-100" value="추가">
</div>
<script>
$(function () {
$("#checkBtn").on("click", function () {
$("#statusArea").empty();
let url = $("#url").val().trim();
if (!url) {
$("#statusArea").append('<span class="text-danger">url을 입력하세요.</span>')
}
$.ajax({
url:"/bookmark/duplicate"
, data:{"url":url}
,success:function(data) {
if (data.is_duplicate) {
$("#statusArea").append('<span class="text-danger">중복된 url입니다.</span>')
}
}
, error:function(error) {
}
});
});
$("#addBtn").on("click", function () {
let name = $("#name").val().trim();
let url = $("#url").val().trim();
if (!name) {
alert("이름을 입력하세요.")
return;
}
if (!url) {
alert("주소를 입력하세요.")
return;
}
if (!(url.startsWith("http://") && url.startsWith("https://"))) {
alert("양식에 맞춰서 입력하세요.")
return;
}
console.log(name);
console.log(url);
if ($("#statusArea").children().length<1) {
$.ajax({
type:"post"
,url:"/bookmark/add"
,data:{"name":name, "url":url}
,success:function(data) {
if (data == "success") {
location.href="/bookmark/list"
}
}
,error:function(error,xhr,status) {
alert("입력에 실패했습니다.")
}
});
}
});
});
</script>
</body>
</html>
비어있거나 중복확인 버튼을 눌러 중복일 경우 출력되는 메시지가 없을 경우 저장하도록 if ($("#statusArea").children().length<1) 조건문을 추가하였다.
그러나 문제는 중복확인을 한 번도 하지 않을 경우(이 또한 문구가 뜨지 않으므로)에도 저장이 된다는 것이었다.
(처음에는 $.ajax 안에 코드를 넣고 ‘이게 왜 되는 거지?’ 했던…. success 내부에 들어가는 것과 관계없이 ajax로 들어가는 순간 저장. success는 그냥 성공 시 출력을 담당한다 라고 생각하면 될듯함)
$(function () {
let isChecked = false;
$("#checkBtn").on("click", function () {
$("#statusArea").empty();
let url = $("#url").val().trim();
if (!url) {
$("#statusArea").append('<span class="text-danger">url을 입력하세요.</span>')
}
$.ajax({
url:"/lesson06/bookmark-duplicate"
, data:{"url":url}
, success:function(data) {
if (data.is_duplicate) {
$("#statusArea").append('<span class="text-danger">중복된 url입니다.</span>')
} else {
$("#statusArea").append('<span class="text-success">사용가능한 url입니다.</span>')
isChecked = true;
}
}
, error:function(error) {
alert("false")
}
});
});
$("#addBtn").on("click", function () {
let name = $("#name").val().trim();
let url = $("#url").val().trim();
if (!name) {
alert("이름을 입력하세요.")
return;
}
if (!url) {
alert("주소를 입력하세요.")
return;
}
if (!url.startsWith("http://") && !url.startsWith("https://")) {
alert("양식에 맞춰서 입력하세요.")
return;
}
console.log(name);
console.log(url);
if (isChecked) {
$.ajax({
type:"post"
,url:"/lesson06/bookmark-add"
,data:{"name":name, "url":url}
,success:function(data) {
if (data == "success") {
location.href="/lesson06/bookmark-list"
}
}
,error:function(error,xhr,status) {
alert("입력에 실패했습니다.")
}
})
} else {
alert("중복확인이 필요합니다.")
return;
}
});
});
그래서 isChecked라는 flag 변수를 사용했다. (현업에서도 이렇게 사용하는지는 모름….)
2. AJAX에서 자주 사용하는 설정값
ajax를 사용하기 위해서는 필수로 알아야 할 설정값들이 있다.
| 구분 | 정의 | 값 |
|---|---|---|
| url | ajax 요청을 보낼 URL | - |
| type | HTTP 요청 방식 (기본값:get`) | get, post, delete, put |
| dataType | 서버로부터 응답받을 데이터 타입. 생략 시 jQuery가 MIME 타입을 보고 자동 결정 | xml, html, json, script, jsonp, text |
| contentType | 전송 시 데이터의 콘텐츠 타입 지정 (기본값: application/x-www-form-urlencoded; charset=UTF-8) |
application/json 등 |
| timeout | 요청 제한 시간 (ms 단위). 초과 시 실패 처리됨 | 숫자 (ex: 3000) |
| data | 서버로 전송할 데이터. Object, String, Array 등 사용 가능. Object일 경우 key-value 구조를 따르며, 값이 배열이면 자동 직렬화됨 |
{name: “홍길동”, age: 20} 등 |
| beforeSend | 요청이 전송되기 전에 실행되는 콜백 함수. false를 반환하거나 jqXHR.abort()를 호출하면 요청이 취소됨 |
function(xhr) { … } |
| success | 통신이 성공했을 때 실행되는 콜백 함수 | function(response) { … } |
| error | 통신이 실패했을 때 실행되는 콜백 함수 (단, jsonp 또는 cross-domain 요청은 해당 안 될 수 있음) |
function(xhr, status, error) { … } |
| complete | success 또는 error 후 항상 호출되는 콜백 함수 |
function(xhr, status) { … } |
3. Controller
@RequestMapping("/bookmark")
@Controller
public class Controller {
@Autowired
private BookmarkBO bookmarkBO;
@GetMapping("/view")
public String view() {
return "addBookmark";
}
@PostMapping("/add")
@ResponseBody
public String add(
@RequestParam("name") String name,
@RequestParam("url") String url) {
bookmarkBO.setBookmark(name,url);
return "success";
}
@GetMapping("/list")
public String list(Model model) {
List<Bookmark> bookmark = bookmarkBO.getBookmark();
model.addAttribute("bookmark", bookmark);
return "bookmarkList";
}
@ResponseBody
@GetMapping("/duplicate")
public Map<String, Object> isDuplicate(
@RequestParam("url") String url) {
boolean isDuplicate = bookmarkBO.isDuplicate(url);
Map<String, Object> result = new HashMap<>();
result.put("is_duplicate", isDuplicate);
return result;
}
}
Leave a comment