ㅁ ajax를 이용한 비동기식 요청
- (1) 요청시 값을 전달하고, 문자열 데이터로 응답하기
- (2) 요청시 값을 전달하고, 여러개의 응답데이터를 JSON객체 이용해서 응답하기
- (3) 조회 요청 후 조회된 데이터가 vo객체라는 가정하에 응답하기
- (4) 조회 요청 후 조회된 데이터가 List라는 가정하에 응답하기
ㅁ 새로운 프로젝트를 만들지는 않고, webApp폴더에서 그대로 진행한다.
- webApp/src/main/webapp에 ajax_index.jsp를 만든다.
- 에이잭스라고 많이들 부른다.
- 서버를 키고 url에 위와 같이 요청해서 이 페이지가 잘 뜨는지 먼저 확인한다.
ㅁ 이때까지 한 요청과 응답은 다 동기식 방식으로 구현했었다.
<%--
* 동기식 방식
1. 페이지 전체가 응답되는 방식 (포워딩시 jsp로 이동==jsp전체구문이 응답)
ㄴ 응답페이지가 전체 로드되면서 보여짐
ㄴ 페이지 깜박거림 발생, 스크롤 상단으로 올라감
2. 사용자의 요청 처리 후 그에 해당하는 응답페이지가 돌아와야만 이어서 요청 가능
ㄴ 요청 처리까지 시간이 지연되면 무작정 계속 기다려야됨
ㄴ A 요청 ==> A 응답페이지 ==> B요청 ==> B 응답페이지
3. 동기식 방식 경우
1) a
2) form submit
3) location.href
4) redirect
즉, 요청 후 다른 페이지로 이동하는 경우는 동기식으로 진행
* 비동기식 방식
1. 응답데이터만 응답되는 방식
ㄴ 페이지 자체가 응답되지 않음 (다른 페이지로 이동되는 개념이 아님)
ㄴ 현재 페이지가 유지되어있음
ㄴ 페이지 깜박거림 없음, 스크롤 상단으로 올라가지 않음
2. 현재페이지를 그대로 유지하면서 필요한 요청을 보낼 수 있음
ㄴ A 요청 ==> A 응답데이터 돌아옴
B 요청 ==> B 응답데이터 돌아옴
3. 돌려받은 응답데이터로 화면 내의 특정 영역만 리로드 시킬 수 있음
즉, 요청 후에도 현재 페이지를 그대로 유지시키고자 할 때 비동기식으로 진행
ex) 아이디 중복체크, 찜하기/해제하기, 댓글, 추천, 무한스크롤링(페이징 대체) 등등...
* AJAX
1. Asynchronous JavaScript And XML
2. 비동기식 요청 기술
3. 서버로부터 데이터를 가져와서 전체 페이지를 새로 고치지 않고 일부 영역만 리로드 할 수 있음
4. 구현방식 : JavaScript 방식 / jQuery 방식 (코드 간결 사용 쉬움)
* jQuery 방식으로 AJAX 통신
1. $.ajax() 호출시 통신에 필요한 정보들을 객체에 정의해서 전달
2. 사용법
$.ajax({
속성: 속성값,
속성: 속성값,
...
})
3. 주요 속성
1) url : 요청할 url (유일한 필수 속성이다)
2) type | method : 요청전송방식 (get | post)
3) data : 요청시 전달할 데이터
4) success : ajax 통신 성공시 실행할 함수 정의
5) error : ajax 통신 실패시 실행할 함수 정의
6) complete : ajax 통신 성공여부와 상관 없이 실행할 함수 정의
7) async : 비동기 처리 방식 설정 여부 (기본값 true)
ajax 요청을 연달아서 실행해야될 때
순차적으로 실행시키고자 할 경우 async를 false로 지정
4. 부수적인 속성
1) contentType : request의 데이터 인코딩 방식 정의(보내는 측의 데이터 인코딩)
2) dataType : 서버에서 response로 오는 데이터의 데이터 형 설정, 값이 없다면 스마트하게 판단함
ㄴ xml - 트리 형태의 데이터 구조
ㄴ json - 맵 형식의 데이터 구조(일반적인 데이터 구조)
ㄴ script- javascript 및 일반 String 형태 데이터
ㄴ html - html 태그 자체를 return 하는 방식
ㄴ text - String 데이터
3) accept : 파라미터의 타입을 설정(사용자 특화 된 파라미터 타입 설정 가능)
4) beforeSend : ajax 요청을 하기 전 실행되는 이벤트 callback 함수(데이터 가공 및 header 관련 설정)
5) cache : 요청 및 결과값을 scope에서 갖고 있지 않도록 하는 것 (기본값 true)
6) contents : JQuery에서 response의 데이터를 파싱하는 방식 정의
7) context : ajax 메소드 내 모든 영역에서 파싱 방식 정의
8) crossDomain : 타 도메인 호출 가능 여부 설정(기본값 false)
9) dataFilter : response를 받았을 때 정상적인 값을 return 할 수 있도록 데이터와 데이터 타입 설정
10) global : 기본 이벤트 사용 여부(ajaxStart, ajaxStop)(버퍼링 같이 시작과 끝을 나타낼 때, 선처리 작업)
11) password : 서버에 접속 권한(비밀번호)이 필요한 경우
12) processData : 서버로 보내는 값에 대한 형태 설정 여부(기본 데이터를 원하는 경우 false설정)
13) timeout : 서버 요청 시 응답 대기 시간(milisecond)
--%>
- 동기식 방식에서는 요청을 하고 그에 맞는 응답 페이지로 항상 이동을 했었다.
- 비동기식 방식은 페이지 자체가 응답되지 않음. 다른 페이지로 이동되는 개념이 아님.
현재 페이지가 유지되어있음. 돌려받은 응답데이터로 화면 내의 특정 영역만 리로드 시킬 수 있음
- 비동기식 방식(ajax)으로 무한 스크롤링을 할 수도 있다. 페이징 처리를 대체한다.
스크롤이 바닥에 닿는 순간 다른 페이지로 넘어가지 않고 데이터를 조회해서 그 페이지에 그대로 뿌려준다.
- ajax는 기본적으로 자바스크립트 기술이다. jQuery로도 구현 가능하다.
- jQuery 방식으로 배운다.
자바스크립트 방식은 브라우저에 따라서 호환성 체크를 해야해서 구문이 좀 복잡하다.
- jQuery에서 제공하는 $.ajax()라는 메소드가 있다.
$.ajax() 메소드 호출시 통신에 필요한 정보들을 "객체에 정의"해서 전달하면 된다.
- 통신에 성공한 경우, 즉 요청에 성공했을 때 돌아오는 응답 데이터가 있다.
그 응답 데이터를 가지고 실행시킬 함수를 정의해둘 수가 있다. (success)
통신이 성공하면 success에 정의되어 있는 함수가 자동으로 실행된다.
- 통신에 실패한 경우는 실행할 서블릿을 찾지 못해서 404에러가 뜨거나, 자바 코드 문제면 500에러가 뜬다.
실패시 실행할 내용이 있다면 error라는 function으로 정의하면 된다.
- async는 비동기 처리 방식 설정 여부를 결정한다.
비동기 방식으로 할건지 동기식 방식으로 처리할 건지 정의하는 속성이다. 생략시 기본값 (true = 비동기)
- async는 여러개의 ajax 요청을 연달아서 실행할 때 쓴다.
기본적으로 ajax 요청들은 순차적으로 실행되지 않는다.
비동기식의 특징은 요청을 보내고 응답 데이터가 언제 돌아올지 모른다. 그래서 다음 요청들도 바로 실행해버린다.
- 첫번째 요청으로 돌아오는 응답 데이터를 가지고, 두번째 요청을 순차적으로 보내야 하는 상황이 있다.
그럴 때는 첫번째 요청을 동기식으로 진행해야 한다. (async를 false로 지정)
- 주요 속성 가지고 거진 다 구현 가능하다.
ㅁ 기존에 했던 동기식 방식 요청
- 아래는 ajax_index.jsp다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>AJAX</h1>
<h2>기존에 했던 동기식 방식으로 요청해보기</h2>
<h3>1. form submit으로 url 요청</h3>
<form action="/web/test1.do" method="get">
<input type="text" name="input">
<button type="submit">요청</button>
</form>
<h3>2. a로 url 요청</h3>
<a href="/web/test1.do?input=홍길동">요청</a>
- header.jsp를 include하지 않아서 context path를 직접 써줘야 한다.
- ajax를 jQuery 방식으로 사용할 예정이라 jQuery 라이브러리가 연동되어 있어야 한다.
header.jsp를 include하지 않으므로 header에 따로 써줘야 한다.
- 동기식 방식으로 요청을 보내면 흰 페이지가 뜬다. 현재 별도로 특정 jsp로 포워딩하고 있지 않아서 흰 페이지가 보여진다.
동기식 방식으로 요청하면 응답 페이지를 반드시 돌려줘야 한다.
요청을 하면 현재 페이지에 있지 않고 다른 페이지로 이동되려 하는게 동기식 방식의 특징이다.
- 비동기식 방식으로 요청을 보내면 다른 페이지로 이동되지 않고 그 페이지가 계속 보여진다.
ㅁ ajax를 이용한 비동기식 방식 요청 - (1) 요청시 값을 전달하고, 문자열 데이터로 응답하기
- 아래는 ajax_index.jsp다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>AJAX</h1>
<h2>기존에 했던 동기식 방식으로 요청해보기</h2>
<h3>1. form submit으로 url 요청</h3>
<form action="/web/test1.do" method="get">
<input type="text" name="input">
<button type="submit">요청</button>
</form>
<h3>2. a로 url 요청</h3>
<a href="/web/test1.do?input=홍길동">요청</a>
<hr>
<h2>AJAX 이용해서 비동기식 방식으로 요청해보기</h2>
<h3>1. 요청시 값 전달 및 문자열 응답데이터 응답하기</h3>
입력: <input type="text" id="input1">
<button onclick="fnAjaxTest1();">요청</button>
<br>
응답 - <span id="output1">현재응답없음</span>
<script>
function fnAjaxTest1() {
$.ajax({
url: '/web/test1.do',
//data: 'input=' + $('#input1').val() <- 문자열. 쿼리 스트링 방식
data: {input: $('#input1').val()}, // <- 자바스크립트의 객체 방식
success: function(res) { // 매개변수에 돌아오는 응답데이터 담김
console.log('ajax 통신 성공');
console.log(res);
$('#output1').text(res);
},
error: function() {
console.log('ajax 통신 실패');
},
complete: function() {
console.log('ajax 통신 성공여부와 상관없이 무조건 출력');
}
})
}
</script>
<br>
(1) 요청시 값을 전달하고 , 문자열 데이터로 응답하기
- 사용자에게 값을 입력받아서 요청시 전달한다. form-submit 방식은 동기식 방식이다.
- 별도로 jQuery 구문을 이용해서 요청한다.
- 버튼을 클릭하면 fnAjaxTest1() 함수가 실행되게끔 한다.
- $.ajax() 메소드를 호출하면서 중괄호 블럭으로 감싼 객체를 전달하면서 호출한다.
- url은 필수 속성이다.
- 사용자가 텍스트 상자에 작성한 값을 같이 넘기고 싶으면, data 속성의 값으로 요청시 전달값을 작성한다.
이때 쿼리 스트링 방식으로 써도 되고 객체 형식으로 써도 된다.
- success 속성을 이용해서 ajax 통신이 성공했을 때 실행할 내용을 미리 정의해둘 수 있다.
- success라는 속성의 값으로는 function 자료형(=함수 자료형, =함수)을 써야 한다.
어딘가에 대입되는, 전달되는 function은 익명함수를 써야 한다. 익명함수 대신 화살표 함수를 쓸 수도 있다.
- 비동기식 방식 요청은 눌러도 흰 화면이 뜨지 않는다. 다른 페이지로 이동하려 하지 않고 현재 페이지 그대로다.
ㅁ webApp/src/main/java의 com.br.web.ajax.controller 패키지에 AjaxController1이라는 서블릿 클래스를 만든다.
package com.br.web.ajax.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class AjaxController1
*/
@WebServlet("/test1.do")
public class AjaxController1 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public AjaxController1() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String str = request.getParameter("input");
System.out.println("요청시 전달된 파라미터: " + str);
// 1. 요청처리 (db에 sql문 실행)
// 2. 요청처리 다 됏다는 가정하에 "응답데이터" 응답 (응답 페이지 x)
String responseData = "입력된값: " + str + ", 길이: " + str.length();
// 응답데이터 돌려주는 구문
response.setContentType("text/html; charset=UTF-8"); // 한글이 포함된 문자열 돌려줄때
response.getWriter().print(responseData);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
- ajax 요청은 현재 그 페이지에 계속 머물러 있기 때문에 절대 jsp로 포워딩하면 안 된다.
- 현재 페이지가 계속 떠있기 때문에 오로지 응답 데이터만 돌려주면 된다.
- 현재 ajax 요청을 보냈던 곳으로 응답 데이터를 돌려준다. 그때 사용하는 객체가 response 객체다.
- response 객체를 이용해서 요청을 보낸 클라이언트에게 응답할 수 있었다.
- response.setContentType("text/html; charset=UTF-8");
단순한 문자열 데이터를 돌려줄 때는 text/html;
한글이 포함된 문자열 데이터라면 charset=UTF-8
- response.getWriter().print(responseData);
content type을 지정하고 응답 데이터를 돌려준다.
응답 데이터를 돌려줄 때는 통로가 필요하다.
response.getWriter()를 호출하면 PrintWriter 객체를 반환한다.
그리고 print 메소드로 응답 데이터를 출력하면 된다.
- 이렇게 전송된 응답 데이터는 통신 성공시 자동으로 실행되는 function의 매개변수 자리에 응답 데이터가 전달된다.
- 응답 데이터를 받고자 한다면 success 속성값의 function에 매개변수를 하나 둬야 한다.
response 데이터니까 res라는 이름으로 뒀다. 이름은 마음대로다.
ㅁ 비동기식 방식으로 요청 보내보기
- 통신이 성공하면 success 속성의 function이 자동으로 실행되고, complete 속성의 function도 실행된다.
- 응답 데이터 문자열이 화면에 보여진다.
- 비동기식 방식은 요청을 보내도 현재 페이지가 계속 유지된다.
- 텍스트 상자도 초기화되지 않는다. 초기화하고 싶다면 텍스트 상자의 value 값을 빈 문자열로 줘야 한다.
ㅁ 개발자 도구(f12)의 Network 탭
- 요청을 보내면 어떤 요청이 이루어졌는지, 요청시 전달값은 뭔지, 돌아오는 응답 데이터는 뭔지 다 볼 수 있다.
- 요청 상태도 볼 수 있다. 200이 성공이다.
- 클릭하면 상세 내용을 볼 수 있다.
- get 방식 요청이라 url 뒤에 요청시 전달값이 보여진다.
- Payload 탭에서 요청시 전달값을 볼 수 있다.
- response 탭에서 돌아온 응답 데이터를 볼 수 있다. 지금은 단순한 문자열이다.
ㅁ ajax를 이용한 비동기식 방식 요청 - (2) 요청시 값을 전달하고, 여러개의 응답데이터를 JSON객체 이용해서 응답하기
- 아래는 ajax_index.jsp다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>AJAX</h1>
<h2>기존에 했던 동기식 방식으로 요청해보기</h2>
<h3>1. form submit으로 url 요청</h3>
<form action="/web/test1.do" method="get">
<input type="text" name="input">
<button type="submit">요청</button>
</form>
<h3>2. a로 url 요청</h3>
<a href="/web/test1.do?input=홍길동">요청</a>
<hr>
<h2>AJAX 이용해서 비동기식 방식으로 요청해보기</h2>
<h3>1. 요청시 값 전달 및 문자열 응답데이터 응답하기</h3>
입력: <input type="text" id="input1">
<button onclick="fnAjaxTest1();">요청</button>
<br>
응답 - <span id="output1">현재응답없음</span>
<script>
function fnAjaxTest1() {
$.ajax({
url: '/web/test1.do',
//data: 'input=' + $('#input1').val()
data: {input: $('#input1').val()},
success: function(res) { // 매개변수에 돌아오는 응답데이터 담김
console.log('ajax 통신 성공');
console.log(res);
$('#output1').text(res);
},
error: function() {
console.log('ajax 통신 실패');
},
complete: function() {
console.log('ajax 통신 성공여부와 상관없이 무조건 출력');
}
})
}
</script>
<br>
<h3>2. 요청시 값 전달 및 여러개의 응답데이터를 JSON객체 이용해서 응답하기</h3>
이름: <input type="text" id="input2_1"> <br>
나이: <input type="number" id="input2_2"> <br><br>
<button onclick="fnAjaxTest2_1();">JSONArray 활용</button>
<ul id="output2_1"></ul> // 응답데이터 가지고 콘솔뿐 아니라 화면에도 출력하기
<script>
function fnAjaxTest2_1() {
$.ajax({
url: '/web/test2.do',
data: {
name: $('#input2_1').val(),
age : $('#input2_2').val(),
flag: 'array'
},
success: function(res) {
console.log(res); // ['강개순', 21]
let liEl = '';
for(let data of res){
liEl += '<li>' + data + '</li>';
}
$('#output2_1').html(liEl); // html 태그까지 반영시키려면 text대신 html 메소드
},
error: function() {
console.log('ajax2_1 통신 실패');
}
})
}
</script>
<button onclick="fnAjaxTest2_2();">JSONObject 활용</button>
<ul id="output2_2"></ul>
<script>
function fnAjaxTest2_2() {
$.ajax({ // 요청시 넘길 값은 문자열 방식, 객체 방식 다 가능.
url: '/web/test2.do',
data: {
name: $('#input2_1').val(),
age : $('#input2_2').val(),
flag: 'object'
},
success: function(res) {
console.log(res); // {name: '홍길동', age: 10}
let liEl = '<li>' + res.name + '</li>'
+ '<li>' + res.age + '</li>';
$('#output2_2').html(liEl);
},
error: function(){
console.log('ajax2_2 통신 실패');
}
})
}
</script>
- form-submit으로 진행하지 않기 때문에 input 요소들에 name 속성으로 key값을 줄 필요가 없다.
- 객체 방식으로 요청시 전달값을 data 속성에 작성한다.
- $.ajax()랑 success는 항상 쓴다. error도 현재 실패했는지 파악하기 위해 써준다.
ㅁ webApp/src/main/java의 com.br.web.ajax.controller 패키지에 AjaxController2라는 서블릿 클래스를 만든다.
package com.br.web.ajax.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
/**
* Servlet implementation class AjaxController2
*/
@WebServlet("/test2.do")
public class AjaxController2 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public AjaxController2() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String flag = request.getParameter("flag");
// 요청처리 다 됐다는 가정하에
// 다수의 응답데이터 돌려주기
if(flag.equals("array")) {
// JSONArray 활용해서 응답 연습
JSONArray jArr = new JSONArray(); // []
jArr.add(name); // ["홍길동"]
jArr.add(age); // ["홍길동", 21]
response.setContentType("application/json; charset=UTF-8"); // JSON 데이터를 응답할때
response.getWriter().print(jArr);
}else {
// JSONObject 활용해서 응답 연습
JSONObject jObj = new JSONObject(); // {}
jObj.put("name", name); // {"name": "홍길동"}
jObj.put("age" , age); // {"name": "홍길동", "age": 21}
response.setContentType("application/json; charset=UTF-8");
response.getWriter().print(jObj);
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
※ 잘못된 방법
- 출력되는 데이터가 하나의 문자열로 연이어져있음 (따로 추출하기 어려움 - 강개순36)
- response.setContentType("text/html; charset=UTF-8");
- response.getWriter().print(name);
- response.getWriter().print(age);
- 여러개의 응답 데이터를 각각 출력하고,
success: function(res) { console.log(res); }를 하면 하나의 문자열로 보여진다.
매개변수 res에 하나의 문자열로 담긴다.
- 다수의 데이터를 응답할 때 주로 사용되는게 JSON이다.
※ JSON
- JavaScript Object Notation
- 자바스크립트 객체 표기법 중의 하나
- ajax 통신시 데이터 전송에 자주 사용되는 포맷형식 중 하나
- json 라이브러리 필요 (https://code.google.com/archive/p/json-simple/downloads)
(JSON 라이브러리에서 제공하는 클래스 필요)
- 종류
1) JSONArray : 자바스크립트에서의 배열 형태로 제작가능 ㄴ [value, value, value, ..]
2) JSONObject : 자바스크립트에서의 일반 객체 형태로 제작가능 ㄴ {key: value, key: value, ..}
※ JSON(JavaScript Object Notation)
- 데이터를 저장하고 전송할 때 사용되는 가벼운 텍스트 기반의 데이터 교환 형식입니다.
- 주로 키-값 쌍으로 데이터를 표현하며, 사람이 읽기 쉽고 기계가 해석하기 쉬운 구조를 가지고 있습니다.
- JSON은 웹 애플리케이션에서 서버와 클라이언트 간의 데이터 전송에 많이 사용됩니다.
- jar 파일은 클래스들의 압축 형태다.
- 제일 상단의 jar 파일을 다운받아서 src/main/webapp/WEB-INF-lib에 둔다.
- 프로젝트 클린한다.
- import org.json.simple.JSONArray;
- import org.json.simple.JSONObject;
- response.setContentType("application/json; charset=UTF-8");
돌려줄 응답 데이터는 단순한 문자 데이터가 아니고 json이다.
- JSONArray나 JSONObject를 돌려줄 때는 반드시 application/json;을 써준다.
- 응답 데이터에 담기는 데이터에 한글이 있을 수 있으니 charset=UTF-8도 써준다.
- 잘못된 방법으로는 '강개순21' 이렇게 콘솔에 출력됐었다.
- 자바스크립트에서의 배열의 형태로 보여진다.
0번 인덱스에 이름이, 1번 인덱스에 나이가 담겨있다.
- 화면 깜빡거림없이 현재 페이지의 일부 영역에 배열 요소의 개수만큼 li 요소가 만들어진다.
ㅁ ajax를 이용한 비동기식 방식 요청 - (3) 조회 요청 후 조회된 데이터가 vo객체라는 가정하에 응답하기
- 아래는 ajax_index.jsp다.
ㅁ ajax를 이용한 비동기식 방식 요청 - (4) 조회 요청 후 조회된 데이터가 List라는 가정하에 응답하기
- 아래는 ajax_index.jsp다.