간단한 AJAX 코드
- 비동기 자바스크립트와 XML이라는 뜻으로 자바스크립트를 통해 서버에 비동기로 요청하는 것
- XML이 붙었지만, JSON을 사용해도 무관(현재는 JSON 사용하여 통신하는 경우가 많음)
클라이언트 코드
HTML 페이지 내에 XHR을 사용하여 서버로 AJAX 요청하는 코드
<html>
<head>
<title>AJAX 공부</title>
<meta charset="utf-8">
</head>
<body>
<h1>AJAX</h1>
<strong>resources/static 폴더</strong>에 추가된 ajaxStudy.html
<script>
function onReadyStateChange(event){
if (ajaxRequest.readyState === XMLHttpRequest.DONE) {
if(ajaxRequest.status === 200){
console.log(ajaxRequest.responseText);
}
}else{
console.error('request failed..');
console.log(ajaxRequest.readyState);
}
}
const ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = onReadyStateChange;
ajaxRequest.open('GET','/get-with-no-parameter');
ajaxRequest.send();
</script>
</body>
</html>
- onReadyStateChange()라는 함수 선언
- ajaxRequest.readyState가 DONE or 4가 되면 true, 아니면 false 에러로그 찍음
- XHR 객체는 UNSENT -> OPENED -> HEADERS_RECEIVED -> LOADING -> DONE의 순서로 총 4번의 변화
- UNSENT : 0 : XHR 객체가 생성된 후 open()함수를 호출하지 않은 상태
- OPENED : 1 : open() 함수가 호출된 상태
- HEADERS_RECEIVED : 2 : send() 함수가 호출된 상태 또는 HTTP 응답 헤더와 상태 코드까지만 사용할 수 있는 상태
- LOADING : 3 : HTTP 응답의 body를 다운로드하고 있는 상태
- DONE : 4 : XHR 객체의 AJAX 요청과 응답이 모두 완료된 상태
- ajaxRequest.status가 200(요청을 성공 의미)이면 true -> 응답받아 온 ajaxRequst.responseText를 로그에 찍음
- ajaxRequest.readyState가 DONE or 4가 되면 true, 아니면 false 에러로그 찍음
- ajaxRequest 상수에 XHR(XMLHttpReques) 객체 생성하여 저장
- ajaxRequest의 readystate가 변경되는 이벤트로, readystate가 변경될 때 onReadyStateChange()가 호출되도록 이벤트 핸들러로 등록
- 이벤트 핸들러(event handler) : 특정 이벤트 발생시 호출되는 함수
- onReadyStateChange()를 ajaxRequest.onreadystatechange의 이벤트 핸들러로 등록했다고 표현
- 이벤트 핸들링을 위한 필드에 onreadystatechage, onabort, onerror, onload, ontimeout 등이 있음
- ajaxRequest의 readystate가 변경되는 이벤트로, readystate가 변경될 때 onReadyStateChange()가 호출되도록 이벤트 핸들러로 등록
-
-
- 이벤트(event) : 애플리케이션상에서 발생할 수 있는 어떤 사건
- open() 함수는 XHR 객체의 요청을 초기화 : GET 메서드로 /get-with-no-parameter라는 경로로 요청하는 AJAX 요청을 초기화(요청을 준비)
- send() 함수는 실행될 때 AJAX 요청이 날아감 : AJAX 요청을 하는 즉시 반환되고, 응답은 send()함수와 무관
- 응답이 오는 이유는 onReadyStateChange()에서 처리(ajaxRequest의 readystate가 변경되면서 이벤트 핸들러가 실행)
-
서버 코드
AJAX요청에 대한 간단한 응답을 하는 컨트롤러 코드
package kr.co.ajaxStudy;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class NoParameterAjaxRestController {
@RequestMapping("/get-with-no-parameter")
public String getWithNoParameter() {
return "파라미터가 없는 GET 요청";
}
}
JSON을 주고받는 AJAX
한줄평 서비스 만들기
- 한줄평 서비스 정의
- 한줄평은 작성자와 내용으로 구성한다.
- 한줄평은 등록하는 기능과 현재 등록된 모든 한줄평을 조회하는 기능만 존재한다.
- 한줄평 등록과, 한줄평 조회하는 기능은 새로고침 없이 AJAX로 동작한다.
- 한줄평, 기능 경로 정의
- 한줄평
{
"name":"이가네",
"comment":"맛있어요!"
} - 기능 HTTP 메서드와 API 경로 정의
- POST 메서드, /review : 한줄평 등록
- GET 메서드, /reviews : 한줄평 목록 조회
- 한줄평
- 코드 작성
API 코드
public class Review {
public String name;
public String comment;
}
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class ReviewAjaxRestController {
private List<Review> reviews = new ArrayList<>();
@RequestMapping(method = RequestMethod.POST, path = "/review")
public String registerReview(@RequestBody Review review){
reviews.add(review);
return "registered";
}
@RequestMapping(method = RequestMethod.GET, path = "/reviews")
public List<Review> getReviews(){
return reviews;
}
}
- Jackson 라이브러리
- 컨트롤러에서는 List<Review>에 담긴 데이터를 JSON 배열로 반환(라이브러리가 없을 시 JSON 문자열과 자바 인스턴스 사이의 변환 코드 작성해야 함)
- 스프링 프레임워크의 메시지 컨버터가 등록되어 있어 자동변환 됨
클라이언트 코드
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<form onsubmit="return addReviewRequest();">
<label>이름 : </label><input type="text" name="name"><br>
<label>한줄평 : </label><input type="text" name="comment"><br>
<input type="submit"><br>
</form>
<button onclick="getReviewListRequest();">한줄평 보기</button>
<ol id="review-list">
<!-- 한줄평 목록 -->
</ol>
<script>
function addReviewRequest() {
const name = document.querySelector('input[name=name]').value;
const comment = document.querySelector('input[name=comment]').value;
const requestObject = {name:name, comment:comment};
const requestJson = JSON.stringify(requestObject);
function onReadyStateChange(event) {
const currentAjaxRequest = event.currentTarget;
if(currentAjaxRequest.readyState === XMLHttpRequest.DONE) {
if(currentAjaxRequest.status === 200) {
alert("한줄평이 등록되었습니다.")
}else{
console.error('request failed');
}
}
}
const ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = onReadyStateChange;
ajaxRequest.open('POST', '/review');
ajaxRequest.setRequestHeader('Content-Type','application/json');
ajaxRequest.send(requestJson);
return false;
}
function getReviewListRequest(){
function onReadyStateChange(event) {
const currentAjaxRequest = event.currentTarget;
if(currentAjaxRequest.readyState === XMLHttpRequest.DONE) {
if(currentAjaxRequest.status === 200) {
const reviewListDom = document.querySelector('#review-list');
reviewListDom.innerHTML = '';
const reviews = JSON.parse(currentAjaxRequest.responseText);
reviews.forEach(review =>{
const liNode = document.createElement('li');
const textNode = document.createTextNode(review.name + ' : ' + review.comment);
liNode.appendChild(textNode);
reviewListDom.appendChild(liNode);
});
}else{
console.error('request failed');
}
}
}
const ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = onReadyStateChange;
ajaxRequest.open('GET', '/reviews');
ajaxRequest.send();
}
</script>
</body>
</html>>
- 한줄평 작성 : addReviewRequest()
- input 태그에서 가져온 name과 comment로 requestObject라는 객체를 생성
- JSON.stringify() : 자바스크립트 객체(Object)를 JSON 문자열로 바꿔 주는 함수
- JSON은 자바스크립트의 객체 문법과 유사하지만 같은 것은 아니기 때문에 바꿔 줘야 함
- 새로운 자원(resource) 생성할 때 약속
- POST 요청 : controller 코드에 POST로 등록 해놓았기 때문
- Contet-Type application/json : JSON이 포함된 요청을 보낼때 헤더를 application/json으로 보내야 함
- ajaxRequest.send()에 JSON 문자열을 인자로 보내도록 정의 되어 있음
- 한줄평 조회 : getReviewListRequest()
- JSON.parse() : JSON 문자열을 자바스크립트의 객체로 변경하는 함수
결과 화면
직렬화와 역직렬화
직렬화(serialize)
- 메모리상 존재하는 인스턴스를 바이너리 형태나 문자열로 만드는 것
- 한줄평 작성 기능
- 웹 브라우저 : JSON.stringify()로 직렬화 - 자바스크립 Object => JSON
- 한줄평 보기 기능
- 스프링부트 애플리케이션 : Jackson 컨버터에 의해 직렬화 - 자바 메모리에 저장된 Review 인스터스들 => JSON
역직렬화(deserialize)
- 직렬화의 반대의 과정, JSON 포맷등을 메모리상 존재하는 인스턴스로 만드는 것
- 한줄평 작성 기능
- 스프링부트 애플리케이션 : Jackson 컨버터에 의해 역직렬화 - JSON => 자바 인스턴스 역질렬화
- 한줄평 보기 기능
- 웹 브라우저 : JSON.parsef로 역직렬화 - JSON => 자바스크립트 Object
동기, 비동기, 블로킹, 논블로킹
동기와 비동기
동기(Synchronous) : 작업을 요청하는 쪽과 작업을 처리하는 쪽이 서로를 인식하고 상태를 동기화하는 것
비동기(Asynchronous) : 작업을 요청하는 쪽과 작업을 처리하는 쪽이 서로를 인식하지 않으며, 상태 역시 동기화하지 않는 것
동기, 비동기는 작업 요청하는 쪽과, 작업을 처리하는 쪽 두 주체 사이의 관계를 이야기 하는 용어
- 동기는 작업을 요청하는 쪽이 작업이 처리가 완료 되기 전까지 대기하게 된다.
- ajaxRequest.send() 코드 실행 후 서버로 요청했던 것을 인식하지 않고, 핸들러로 등록된 onReadyStateChange가 XHR 객체의 readyState가 변경되는 이벤트가 발생할 때 핸들러가 실행될 뿐이다.
- AJAX 요청을 던지는 자바스크립트 코드는 서버의 상태에 관심이 없고, 서버의 상태를 받아 처리하는 것은 onReadyStateChange 이벤트 핸들러이다.
- 따라서 AJAX 요청을 던지는 자바스크립트 코드와 서버의 상태가 서로 비동기적이라고 이야기 할 수 있다.
블로킹과 논블로킹
블로킹(blocking) : 동기시에 작업을 요청하는 쪽은 대기상태가 되는데, 동기화를 위해 기다리고 있는 상태를 의미
논블로킹(non-blocking) : 작업을 요청 후 우선 다른 일을 진행하는 상태를 의미, 작업 완료에 대해 신경쓰지 않고 실행이 멈추지 않는 것을 의미
블로킹, 논블로킹은 작업을 요청하는 쪽에서 어떻게 동작하는지를 표현하는 용어로, 요청 후 요청하는 쪽이 대기하거나 대기하지 않는 행위 자체
'프로그래밍언어 > JavaScript' 카테고리의 다른 글
[JavaScript] JSON(JavaScript Object Notation) (0) | 2025.03.11 |
---|---|
[JavaScript] JS의 window객체 (0) | 2022.03.20 |
[JavaScript] 문서 객체 모델(DOM) (0) | 2022.03.16 |
[JavaScript] JS의 대화상자 (0) | 2022.03.14 |
[JavaScript] 이벤트 연습 (0) | 2021.09.07 |