이번 포스팅에서는 Ajax에 대해 알아보고 XMLHttpRequest를 이용해서 Ajax를 사용해보고자 한다.
< 목차 >
- Ajax
- XMLHttpRequest
1. Ajax
Ajax는 Asynchronous JavaScript and XML의 약자로 JavaScript와 XML을 이용한 비동기적 정보교환 기법이다. Ajax를 사용해서 통신을 하게 될 경우 URL이 바뀌지 않고도 서버에 요청을 보낼 수 있게 된다.
지금까지의 방식은 URL을 통해 서버에 요청을 보내면 서버쪽에서 해당 요청에 대한 응답을 건내주는 방식이었다. Ajax는 이와는 다르게 브라우저의 JavaScript에 있는 특정 함수를 사용해서 URL 없이도 서버에 요청을 보낼 수 있는 방식이다. URL을 통해 서버에 요청을 보내는 방식에서는 서버가 브라우저에게 화면을 랜더하기 위한 모든 내용들을 건내주고 있었다. 하지만 Ajax 통신을 하게 되면 서버로부터 전체 내용을 받지 않고 기본적으로 데이터만을 받게 된다. (Ajax를 사용하는 통신은 데이터만을 전달한다.)
Ajax 통신을 통해서 서버와 브라우저가 내용을 주고 받을 때 데이터만을 건내주게 되는데 이 때 전달되는 데이터의 형태가 과거에는 XML 형태로 존재했었다. 하지만 최근에는 XML이 사용되지 않고 JSON 형태로 데이터를 주고받는다. Ajax라는 이름은 XML에서 유래되었지만 실제 기술 구현에 있어서는 JSON을 사용하고 있는 실정이기에 헷갈리지 않길 바란다.
이렇게 Ajax를 이용해 통신을 하다보면 백엔드 입장에서는 브라우저로부터 요청이 들어왔을 때 해당 요청이 URL을 통한 요청인지 아니면 Ajax를 사용한 JavaScript 코드 형태의 요청인지 구분하기가 애매모호해지는 현상이 발생할 수 있다. URL 요청에 대한 라우터와 Ajax 통신에 대한 라우터를 각각 따로 만들어서 관리해주어야만 하기 때문에 백엔드를 만들 때 흔히들 이야기하는 프론트서버와 백엔드서버로 나누어서 작업을 하게 된다. html만을 만들어주는 서버가 프론트서버, 데이터 전달만을 담당하고 있는 서버가 백엔드서버가 되는 것이다.
2. XMLHttpRequest
이제 코드를 살펴보면서 Ajax를 어떻게 구현하는지 알아보도록 하자. Ajax를 사용해 만들어 볼 기능은 회원가입을 할 때 흔히 나오게 되는 아이디 중복체크 기능이다. 메인 실행 파일인 server.js 파일 , 회원가입 페이지를 구성하는 join.html 파일 , Ajax 기능이 구현되어 있는 idCheck.js 파일 , 회원정보가 담겨있는 user.js 파일은 각각 다음과 같다.
우선 회원가입 페이지를 구성하는 join.html을 살펴보자.
<form method="post" action="/join">
<input type="text" name="userid" id="userid">
<input type="button" id="idcheck_btn" value="중복체크">
<div id="msg">
</div>
</form>
<form>엘리먼트 안에 "submit"버튼 없이 중복체크 버튼만을 생성해서 중복체크 버튼을 클릭했을 때 url이 바뀌지 않고도 해당 기능이 구현되게끔 하고자 한다.
브라우저의 JavaScript 파일 안에서 new XMLHttpRequest( )를 사용해 Ajax 기능을 구현하였다. 우선 XMLHttpRequest( ) 함수를 이용해 xhr 객체를 생성해준다.
const xhr = new XMLHttpRequest()
xhr 객체가 가지고 있는 메소드 함수를 이용해 중복체크 버튼을 클릭했을 때 서버쪽으로 요청을 보낼 수 있도록 하는 JavaScript 코드를 아래와 같이 작성해준다.
const data = JSON.stringify({userid: userid.value})
xhr.open('POST', '/idcheck', true)
xhr.setRequestHeader('Content-type', 'application/json')
xhr.send(data)
xhr.open( ) 메소드를 통해 Request Method와 URL을 지정해 줄 수 있다. 첫번째 인자값으로 request method, 두번째 인자값으로 url을 넣어준다. xhr.setRequestHeader( ) 메소드를 통해서는 HTTP 패킷의 Request Headers(요청 헤더)를 조작할 수 있다. 요청헤더에 들어가는 내용 중 "Content-type"을 "application/json"으로 하였다. 마지막으로 서버쪽에 전달할 데이터를 xhr.send( ) 메소드의 인자값으로 넣어준다.
Ajax 통신을 할 때는 JSON 데이터 포맷을 이용하므로 data 라는 변수 안에는 사용자가 input 박스 안에 입력한 내용을 JSON 형태로 넣어준다. 이 때 반드시 JSON.stringify( )를 통해 string 형태로 변환해서 전달해줘야 한다.
"/idcheck" 경로를 통해 POST 방식으로 서버에 데이터를 전달하면 백엔드 서버는 해당 요청에 대한 응답을 주게 된다. server.js 파일 안에 있는 라우터를 살펴보면서 어떤식으로 요청을 처리하고 응답을 보내는지 알아보자.
// server.js 파일
app.post('/idcheck', (req, res)=>{
const {userid} = req.body
const [ item ] = user.filter(v => v.userid == userid)
let result = 1
if (item != undefined) result = 0
// 가입가능 1 , 가입불가능 0
const response = {
result
}
res.send(JSON.stringify(response))
})
user.js 파일 안에 중복되는 아이디값이 있으면 result 변수에 0이 할당되고 중복되는 아이디값이 없어서 회원가입이 가능하다면 result 변수에 1이 할당되도록 하였다. 중요한 점은 response 라는 객체를 생성해서 해당 객체 안에 result 값을 넣고 res.send( )를 통해 브라우저에게 전달한다는 것이다. 서버는 브라우저에게 응답을 주면서 JSON 포맷으로 만들어진 데이터를 전달하였다. 여기서도 마찬가지로 JSON.stringify( )를 사용해서 string으로 변환해준 후에 전달해야 함을 명심하자.
브라우저가 서버로부터 응답을 받기까지의 일련의 과정들이 진행되면서 xhr 객체 안에 있는 onreadystatechange 속성값 안의 콜백함수가 실행되는데 해당 부분은 다음과 같다.
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
try {
// 가입가능 1 , 가입불가능 0
const {result} = JSON.parse(xhr.response)
if (result === 0) throw new Error('아이디가 중복되었습니다.')
msg.innerHTML = '사용 가능한 아이디입니다.'
msg.style.color = 'green'
} catch(err) {
// 가입불가능
msg.innerHTML = '중복된 아이디입니다.'
msg.style.color = 'red'
}
}
}
xhr.readyState 속성값이 4 이고 xhr.status 값이 200 일 때 try { } catch { } 구문을 사용해서 브라우저의 JavaScript가 적절한 처리를 하게끔 하였다. xhr.response 속성값 안에는 서버로 부터 응답 받은 데이터가 담겨있는데 서버에서 string 형태로 데이터를 전달했으므로 JSON.parse(xhr.response)를 통해 원래의 JSON 포맷으로 되돌려 주었다. 그리고 result 값에 따라 각각 알맞은 처리를 진행해 주었다.
추가로 readyState 속성에 대해 조금 더 살펴보자면 xhr.readyState 속성은 Ajax 통신의 상태값을 가지고 있는 속성이다. onreadystatechange 안의 콜백함수는 총 세번 실행되는데 이는 Ajax 통신의 상태와 관련있다.
브라우저에서 서버로 데이터를 보낼 때 한 번, 서버에서 브라우저에게 응답을 주려고 할 때 한 번, 그리고 브라우저에 데이터가 도착해서 모든게 완료가 됐을 때 한 번 실행된다. 진행되는 과정의 단위마다 콜백함수가 실행된다고 생각하면 될 것이다. 이때 2, 3, 4 와 같은 숫자로 상태값을 줘서 Ajax 통신의 상태를 표현하는데 xhr.readyState 속성을 통해 이 상태값을 살펴볼 수 있다. 위의 코드에서는 xhr.readyState == 4 일 때, 즉 완벽하게 응답을 받고 완료가 되었을 때 try { } 구문이 실행되도록 한 것이다. 그리고 이러한 방식으로 콜백함수가 세번 실행된다는 사실을 알고 있다면 다음과 같은 방법으로 로딩창을 구현해 볼 수도 있다.
xhr.onreadystatechange = () => {
switch(xhr.readyState) { // 숫자는 ajax의 상태값을 나타냄
case 2:
// HEADERS_RECEIVED
break;
case 3:
// LOADING
break;
case 4:
// DONE
break;
}
}
다음은 위의 코드들로 만들어진 아이디 중복체크 기능 시현 영상이다.
그리고 다음은 idCheck.js 파일의 전체 코드이다.
const userid = document.querySelector('#userid')
const btn = document.querySelector('#idcheck_btn')
const msg = document.querySelector('#msg')
btn.addEventListener('click', clickHandler)
function clickHandler() {
const data = JSON.stringify({userid: userid.value}) //JSON을 스트링으로 변환
// Ajax
const xhr = new XMLHttpRequest()
// Request method , URL 지정
xhr.open('POST', '/idcheck', true) // 첫번째 인자값은 request method, 두번째 인자값은 url
// Request Header(요청헤더) 조작
xhr.setRequestHeader('Content-type', 'application/json')
// Request Body에 데이터를 넣어서 보내기
xhr.send(data)
// xhr.send()에 의해 서버로 내용이 전달되고 응답을 건내받으면 아래의 콜백함수가 실행된다.
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
try {
// 가입가능 1 , 가입불가능 0
const {result} = JSON.parse(xhr.response)
if (result === 0) throw new Error('아이디가 중복되었습니다.')
msg.innerHTML = '사용 가능한 아이디입니다.'
msg.style.color = 'green'
} catch(err) {
// 가입불가능
msg.innerHTML = '중복된 아이디입니다.'
msg.style.color = 'red'
}
}
}
}
다음 포스팅에서는 XMLHttpRequest( ) 외에 JavaScript에서 지원하는 내장객체인 fetch , 외부라이브러리를 사용하는 axios를 이용해서 Ajax를 구현해보도록 하자.
'Node > Express' 카테고리의 다른 글
Node.js - express (16) CORS (0) | 2022.03.13 |
---|---|
Node.js - express (15) Ajax - fetch , axios (0) | 2022.03.07 |
Node.js - express (13) JWT 로그인 인증 (0) | 2022.03.05 |
Node.js - express (12) Buffer , Hash , JWT (0) | 2022.03.03 |
Node.js - express (11) express.json() (0) | 2022.02.15 |