Nodejs/Server

비동기 통신 - AJAX #1

Sila 2022. 3. 16. 00:03

지금까지 배운 서버와 사용자간의 요청, 응답을 위해서는 한 페이지를 통째로 다시 불러와야 하는 불편함이 있었다.

 

이를 해결하기 위해 나온 것이 ajax (Asynchronous JavaScript And XML) 이다.

 

ajax는 웹 페이지의 프론트와 백 엔드 요소를 분리한다. 

 

이후 간단한 요청, 응답을 주고받을 일이 생기면 JS를 실행해 서버에 (주로 백 엔드를 담당하는) 요청을 보내고,

 

응답을 받아와 정해진 형식 (HTML, CSS 설정)대로 렌더링해준다.

 

이를 코드를 작성해 구현하는 방법은 여러가지가 있지만 여기서는 axios (외부 라이브러리)를 사용하는 방법만을 다룬다.

 

 

만약 프론트와 백 엔드를 담당하는 서버가 나뉘어져 있다면

 

CORS (Cross Origin Resource Sharing)이 추가적으로 필요하다.

 

CORS는  한 서버에서의 요청이 다른 서버에 전달되고, 그 응답을 받아올 수 있도록 권한을 부여하는 것을 의미한다.

 

이 또한 외부 라이브러리를 사용하는 것이 편리하다.

 

여기서는 가장 간단한 예시를 하나 들어보고

 

다음 포스팅부터는 실제로 게시판이나 회원 가입 등의 기능을 만들 때 비동기통신이 어떤 방식으로 활용되는지

 

알아보도록 하자.

 

1. intro

이번에는 버튼을 클릭하면 프론트 서버에서 미리 적어둔 데이터가 백 엔드 서버로 전달되고,

 

백 엔드 서버에서 전달한 데이터가 출력 되고, 쿠키를 하나 만들어주는 것을 반응으로 주는

 

일련의 아주 간단한 백엔드, 프론트엔드 서버 간 통신 기능을 구현해볼 것이다.

 

2. 프론트앤드 서버 구축

우선 폴더 안에 front, back end 서버 역할을 해줄 폴더를 2개 만들자. 

 

각각 back, front로 폴더명을 정해주고, 각각의 폴더에 server.js 파일을 하나씩 만들어준다.

 

우선 프론트 쪽부터 살펴보자.

 

/*  server.js  */

const express = require('express')
const nunjucks = require('nunjucks')

const app = express()
app.set('view engine', 'html')
nunjucks.configure('views', {express:app})

app.get('/', (req, res) => {
   res.render('main.html')
})

app.listen(3001, () => {
   console.log('front server 3001 run')
})

 

다음으로 front/views 폴더 안에 main.html 을 작성해보자.

 

axios 라이브러리를 html에서 사용하기 위해 head 부분에 axios를 사용하기 위한 script를 하나 넣어준다.

 

그리고 html에 버튼 element를 하나 추가한다.

 

/*  main.html  */

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>

    <button id="btn">버튼</button>
    
</body>
</html>

 

이제 이 버튼에 js를 이용해 백 엔드 서버로 데이터를 주고 받는 기능을 추가할 것이다.

 

우선 버튼 element를 지정하고, 클릭시 발동할 callback을 작성해주자.

 

(async는 일단 넘어가자.)

 

그리고 전송할 데이터를 객체 형태로 선언했다.

 

/*  main.html  */

<script type='text/javascript'>
   const btn = document.querySelector('#btn')
   
   btn.addEventListener('click', async () => {
   
   const data = {
      userid: 'lsj',
      userpw: '1234'
   }
   
</script>

 

그 후, 데이터 전송의 형식을 지정해주자. data 변수 아래에 이어서 써주면 된다.

 

/*  main.html  */

const option = {
   'Content-type' : 'application/json',
   withCredentials:true
}

 

Content-type은 application/json을 지정해준다.

 

withCredentials는 백엔드 서버와 통신을 할 수 있도록 해주는 허가증을 의미한다.

 

아무 서버에서나 백 엔드 서버에 요청을 보내면 안 되므로 withCredentials 값이 있을 때만

 

요청을 받고 응답을 줄 수 있게 해주는 것이다.

 

이제 백 엔드 서버와 axios를 이용해 통신을 하는 코드를 작성한다.

 

/*  server.js  */

const response = await axios.post('http://localhost:4001', data, option)

 

우선 전제로 둬야 할 부분은 프론트 서버에서 백 엔드 서버로 요청을 보내고 응답을 받을때까지 얼마나 걸릴 지

 

알 수 없고, 다른 과정보다는 오래 걸릴 것임이 거의 확실하므로 이를 비동기화 시켜 처리하기 위해

 

async, await를 사용했다. (위의 addEventListener의 콜백에 async가 붙은게 이런 이유 때문이다.)

 

그리고 post method를 사용해, 요청을 보내는데, 인자값이 3개 존재한다.

 

보는 바와 같이 차례로 각각 요청을 보내는 uri, 보내는 data, 보내는 형식이다.

 

이 한 줄의 코드에서 요청을 보내고 응답을 받는 것이 모두 이루어진다.

 

응답이 올 때까지 기다렸다가 (await) 다음 코드를 실행할 것이다.

 

/*  server.js  */

console.log(response)

alert('button clicked')

 

응답은 response 변수 안에 담아주고

 

마지막으로 버튼이 클릭되었다는 알람을 주자.

 

지금까지 쓴 코드를 정리햅면 다음과 같다.

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>

    <button id="btn">버튼</button>
    
    <script type="text/javascript">
        const btn = document.querySelector('#btn')
        btn.addEventListener('click', async () => {

            const data = {
                userid: 'sila',
                username:'lsj'
            }

            const option = {
                'Content-type' : 'application/json',
                withCredentials:true 
            }

            const response = await axios.post('http://localhost:4001', data, option)
            
            console.log(response)

            alert('button clicked')
        })
    </script>
    
</body>
</html>

 

3. 프론트앤드 서버 구축

이제 요청을 받고 응답을 줄 백 엔드 서버를 구축해줘야한다.

 

/*  back/server.js  */

const express = require('express')
const app = express()

const cors = require('cors')

app.use(express.json())

app.use(cors({
   origin:true,
   credentials:true
}))

app.post('/', (req, res) => {
   console.log(req.body)
   res.setHeader('Set-cookie', 'name=lsj; Domain=localhost;')
   res.send('click recognized')
})
 
app.listen(4001, () => {
   console.log('server run 4001')
})

 

다른 서버와 요청과 응답을 주고 받는 것이므로 상술한 것처럼 cors가 필요하다.

 

외부 라이브러리 cors를 npm으로 설치해주고 이를 가져와 사용해야한다.

 

cors의 셋업은 다음과 같이 origin, credential을 true로 설정해주면 된다.

 

프론트 엔드 서버에서 요청을 post로 보내주었으므로 요청을 받은 백 엔드 서버는

 

app.post로 시작, uri는 '/'인 라우터를 실행할 것이다.

 

그러면 요청의 body를 출력하고, 쿠키를 다음과 같이 설정과 값을 만들어 브라우저에 준다.

 

마지막으로 'click recognized' 라는 문구를 출력한다.

 

 

여기까지 한 후, 백엔드 서버, 프론트엔드 서버가 모두 돌아가는 상태에서

 

버튼을 클릭하면 브라우저의 콘솔과 터미널에 각각 원하는 데이터가 출력되는 것을 확인할 수 있다.

'Nodejs > Server' 카테고리의 다른 글

게시판 서버 만들기 #1 - 회원가입  (0) 2022.03.19
파일 업로드 #1  (0) 2022.03.16
Session #2 - 미들웨어  (0) 2022.02.13
Session #1  (0) 2022.02.13
Server의 이해 - Cookie #2  (0) 2022.02.08