NodeJs.서버의 분리 실습코드

2023. 1. 4. 03:27NodeJs

https://char1ey.tistory.com/64

 

 

NodeJs.XMLHttpRequest이용하기

목차 1. 효율적인 통신을 위해서 2. XMLHttpRequest 3. XMLHttpRequest 사용하기 1. 효율적인 통신을 위해서 이전에는 서버와 클라이언트(브라우저)가 서로 데이터를 주고 받을 때, 화면을 그리는 방법은 요

char1ey.tistory.com

https://char1ey.tistory.com/66

 

NodeJs.서버의 분리와 CORS

목차 1. SSR과 CSR 2. CORS 1. SSR 과 CSR 데이터의 요청과 응답 그리고 템플릿을 이용한 html을 그리는 기능까지 하는 서버 파일을 이전에 구현한적이 있다. SSR(Server Side Rendering) 데이터의 처리와 화면의

char1ey.tistory.com

 

이번에는 지난번에 작성했던 포스팅의 XML 사용법과 서버 분리의 개념을 이용해서 코드를 작성해 보도록하자.

 

 

목표

 

Post 요청시 데이터를 추가한다.

 

추가된 데이터를 화면에 차례대로 그린다.

 

JSON을 역할을 정확히 이해한다.

 

DOM 파일의 진행에 적응하자.

 

 

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>
    <link rel="stylesheet" href="/css/index.css">
</head>
<body>
    <div class="wrap">
        <h1>AJAX 연습하기</h1>
        <div id="msg">POST 출력되는 곳</div>
        <div class="btn_wrap">
            <button id="ajax_get">GET</button>
            <button id="ajax_post">POST</button>
        </div>
        <div class="parallax"></div>
        <div id="userlist">
            <ul>
                <li>번호</li>
                <li>아이디</li>
                <li>비밀번호</li>
                <li>이름</li>
                <li>성별</li>
            </ul>
        </div>
        <div class="input_wrap">
            <input type="text" name="userid" id="userid">
            <button id="btn">유저 추가</button>
        </div>
    </div>
    <script src="/js/index.js"></script>
</body>
</html>

 

CSS (화면이 너무 심심해서 작성했다)

 

html {
    margin: 0;
    padding: 0;
    background-color: #000;
    color: #ececec;
    font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
}

button {
    cursor: pointer;
}

.parallax {
    min-height: 100px;
    background-attachment: fixed;
    background-image: url(../img/universe.jpg);
    background-size: cover;
    background-repeat: no-repeat;
}

h1 {
    margin: 2rem auto;
    text-align: center;
}

#msg {
    margin: 0 auto;
    padding: 1rem;
    width: 30%;
    height: 100px;
    background-color: rgb(90, 90, 90);
    border: 0.25rem solid #ececec;
    border-radius: 0.5rem;
    box-sizing: border-box;
}

.btn_wrap {
    margin: 0 auto;
    padding: 1rem;
    width: 30%;
    height: 50px;
    display: flex;
    justify-content: center;
}

.btn_wrap > button {
    margin: 0 1rem;
    width: 6rem;
    height: 3rem;
    background-color: #000;
    border: 0.25rem solid #ececec;
    border-radius: 5px;
    color: #ececec;
    font-size: 1.5rem;
    font-weight: 700;
    transition: all 0.5s;
}

.btn_wrap > button:hover {
    background-color: rgb(200, 180, 200);
    color: #2e2e2e;
}

ul, li {
    list-style: none;
}

#userlist {
    width: 30%;
    margin: 1rem auto;
    display: grid;
    grid-template-columns: repeat(1, 1fr);
}

#userlist > ul {
    margin: 0.1rem;
    display: flex;
    justify-content: space-around;
    background-color: #111111;
    border: 1px solid #ececec;
}

#userlist > ul > li {
    margin: 0.5rem;
    width: 20%;
    text-align: center;
}

.input_wrap {
    margin: 0 auto;
    width: 30%;
    display: flex;
    justify-content: space-evenly;
    align-items: center;
}

#userid {
    margin: 0 1rem;
    width: 12rem;
    height: 2rem;
    line-height: 2rem;
    border-radius: 5px;
}

#btn {
    margin: 0 1rem;
    width: 12rem;
    height: 3rem;
    background-color: #000;
    border: 0.25rem solid #ececec;
    border-radius: 5px;
    color: #ececec;
    font-size: 1.5rem;
    font-weight: 700;
    transition: all 0.5s;
}

#btn:hover {
    background-color: rgb(200, 180, 200);
    color: #2e2e2e;
}

 

 

public/JavaScript( DOM을 이용, 브라우저에서 화면을 그리도록하는 코드 )

 

const ajax_get = document.querySelector('#ajax_get')
const ajax_post = document.querySelector('#ajax_post')
const msg = document.querySelector('#msg')

const request = ({ method, path, body }, callback) => {
    const host = 'http://localhost:3000'
    const xhr = new XMLHttpRequest()
    xhr.open(method, `${host}${path}`)
    xhr.setRequestHeader('Content-type', 'application/json')
    xhr.send(JSON.stringify(body))
    
    xhr.onload = () => {
        if(xhr.status === 200){
            callback(xhr.response)
        }
    }
}

ajax_get.addEventListener('click', () => {
    request({method: 'get', path:'/users/1'}, (response) => {
        console.log(response)
    })
})

const data = {
    userid:'char1ey',
    userpw:'1234',
    username:'char1ey',
    gender:'남자'
}

ajax_post.addEventListener('click', () => {
    request({method:'post', path:'/users', body:data}, (response) => {
        console.log(response)
        msg.innerHTML = response
    })
})


const userList = document.querySelector('#userlist')
const btn = document.querySelector('#btn')
const card = ({ idx, userid, userpw, username, gender }) => {
    const ulElement = document.createElement('ul')
    const idxElement = document.createElement('li')
    const idElement = document.createElement('li')
    const pwElement = document.createElement('li')
    const nameElement = document.createElement('li')
    const genderElement = document.createElement('li')

    idxElement.innerHTML = idx
    idElement.innerHTML = userid
    pwElement.innerHTML = userpw
    nameElement.innerHTML = username
    genderElement.innerHTML = gender
    
    ulElement.append(idxElement)
    ulElement.append(idElement)
    ulElement.append(pwElement)
    ulElement.append(nameElement)
    ulElement.append(genderElement)
    userList.append(ulElement)
}

request({method: 'get', path:'/users'}, (response) => {
    const arr = JSON.parse(response)
    arr.forEach((v) => {
        card(v)
    });
})

btn.addEventListener('click', () => {
    request(
        {
            method:'post',
            path:'/users',
            body: {
                userid: document.querySelector('#userid').value,
                userpw: '1234',
                username: 'ingoo',
                gender: '남자',
            },
        },
        (response) => {
            card(JSON.parse(response))
        }
    )
})

 

 

이번에는 프론트서버 백서버의 코드를 작성해보자.

 

 

프론트서버

 

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

app.use(express.static('public'))
app.set('view engine', 'html')
nunjucks.configure('views', { express : app })

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

app.listen(3005, () => {
    console.log('server start')
})

 

백서버

 

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

app.use(express.urlencoded({extended:false}))
app.use(express.json())
app.use(cors())

const user = [
    {
        idx:1,
        userid:'web7722',
        userpw:'1234',
        username:'ingoo',
        gender:'남자',
    },
]

//list
app.get('/users', (req,res) => {
    res.json(user)
})

// write
app.post('/users', (req,res) => {
    const { userid, userpw, username, gender} = req.body
    const response = { idx:user[user.length -1].idx + 1, userid, userpw, username, gender}
    user.push(response)
    res.json(response)
})

// view
app.get('/users/:idx', (req,res) => {
    const { idx } = req.params
    const [response] = user.filter((v) => v.idx === parseInt(idx))
    res.json(response)
})

app.listen(3000, () => {
    console.log('server start')
})

 

 

설명

 

우선 동작 원리를 알아보도록하자.

 

<그림 1> 코드 동작원리와 각 서버의 미들웨어 현황

 

 

프론트 서버에서는 처음 화면을 그려줄 템플릿(넌적스)와 정적파일을 처리해주는 static만 장착이 되어있다.

 

첫 화면을 그리는데만 도움을 주고, 이후에는 브라우저에서 Javascript로 화면을 그려주기(DOM 이용) 때문이다.

 

백 서버에서 미들웨어 장착 현황은 오로지 데이터의 응답에 충실한 모습을 볼 수 있다.

 

원래는 한곳에서 위의 미들웨어를 모두 장착했지만, 서버의 역할에 따라 분리된 것을 알 수 있다.

 

이전의 서버 구현과는 달리 path가 간단해 진 것을 확인할 수 있다. 

 

 

백서버의 라우터 부분

 

 

원래는 직접 /list, /view, /write를 넣었지만, 굳이 url을 이동하지 않기 때문에 라우터의 경로가 간단하게 설정된 것을 볼 수 있다.

 

주목해서 볼 부부은 // write 안의 response 부분과 //view 아래의 모든 부분을 이해해야한다.

 

res.json( )은 데이터를 보낼 때 스트링 타입으로 보내야하기 때문에 쓰는 express에서 제공하는 메서드이다.

 

req.params는 /:idx라고 적혔을 경우 idx의 값을 객체로 담고있다. /:abc라고했다면 abc의 키와 값이 담긴다.

 

parseInt를 쓰는 이유는 idx의 값이 string으로 되어 오류가 나기때문이다.

 

 

그 다음으로 볼 부분은 화면을 그려주는 Javscript(DOM) 부분이다.

 

Javascript 파일의 AJAX요청을 함수로 작성했다

 

 

위의 함수를 실행하면, 코드를 줄여서 작성이 가능하다.

 

주의할 점은 setRequestHeader의 Content-type이다. 데이터의 형태를 잘 파악하고 작성해주어야한다.

 

 

Javascript 부분의 DOM 부분(노가다)

 

 

아래로 내려와서 DOM을 작성하는 부분을 살펴보자 코드가 길어보이지만 단조롭게 구성되어있어 어렵지않다.

 

다만, 반복해서 적어줘야하는 부분이기에 귀찮을 수는 있다.

 

 

버튼 클릭시 화면에 출력하는 코드

 

 

위의 코드는 버튼을 클릭하면 화면에 데이터를 출력해준다.

 

 

 

페이지 새로고침시 가진 데이터를 모두 출력해준다.

 

위의 코드가 없으면 새로고침시 페이지에 이전 데이터가 모두 날라가 보이지 않게된다.

 

이 코드를 실행하여 웹페이지로 확인해보도록하자.

 

 

코드 실행

 

순서는 POST 클릭 n회 > 새로고침 > 유저추가 버튼 클릭이다.

'NodeJs' 카테고리의 다른 글

NodeJs.ORM(Object Relational Mapping)  (0) 2023.01.11
NodeJs.XMLHttpRequest의 이해(코드)  (0) 2023.01.04
NodeJs.서버의 분리와 CORS  (0) 2023.01.04
NodeJs.MVC 패턴  (0) 2023.01.03
NodeJs.XMLHttpRequest이용하기  (0) 2023.01.03