앞에서는 client의 요청을 보내는 것을 구현해보았다. 그렇다면 이제는 서버에서 그 요청을 받아서 응답을 처리하는 js를 구현해 볼 것이다
.
요청을 처리하고 응답을 하는데 앞서 우리는 먼저 서버를 구축해야만 한다. 다음 코드가 서버를 생성하는 기초적인 식이다.
const http = require('http');
const PORT = 5000;
const ip = 'localhost';
const server = http.creatServer((request, response) => {
//여기에서 작업이 진행 된다.
})
// 위의 코드는 아래 코드의 축약형식 이다.
const server = http.createServer(); //server 객체는 EventEmitter이다.
server.on('request', (request, response) => { //리스너를 추가하는 문법
// 여기서 작업이 진행 된다.
});
server.listen(PORT, ip, () => {
console.log(`http server listen on ${ip}:${PORT}`);
});
const defaultCorsHeader = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Accept',
'Access-Control-Max-Age': 10
}
위 작업을 통해서 우리는 작은 서버를 하나 만들었다. 이제는 이 서버에 어떤 기능을 부여할 것이냐?
어떤 텍스트를 요청받아서 그 받은 텍스트를 대문자 혹은 소문자로 돌려주는 기능을 하는 서버를 만들어 볼 것이다.
이를 위한 Client 쪽과 html은 미리 구현이 되어있다.
class App {
init() {
document
.querySelector('#to-upper-case')
.addEventListener('click', this.toUpperCase.bind(this));
document
.querySelector('#to-lower-case')
.addEventListener('click', this.toLowerCase.bind(this));
}
post(path, body) {
fetch(`http://localhost:5000/${path}`, {
method: 'POST',
body: JSON.stringify(body),
headers: {
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(res => {
this.render(res);
});
}
toLowerCase() {
const text = document.querySelector('.input-text').value;
this.post('lower', text);
}
toUpperCase() {
const text = document.querySelector('.input-text').value;
this.post('upper', text);
}
render(response) {
const resultWrapper = document.querySelector('#response-wrapper');
document.querySelector('.input-text').value = '';
resultWrapper.innerHTML = response;
}
}
const app = new App();
app.init();
<html>
<head>
<meta charset="utf-8">
<style>
.input-text {
resize: none;
font-size: 1.5rem;
width: 80%;
height: 10ch;
border: 1px solid #000;
}
#response-wrapper {
width: 80%;
font-size: 2rem;
border: 1px solid #000;
height: 10ch;
}
button {
font-size: 2rem;
}
</style>
</head>
<body>
<div id="root">
<h2>요청</h2>
<textarea
placeholder="여기에 작성한 데이터를 서버로 보내면 응답으로 받을 수 있어야 합니다."
class="input-text"
></textarea>
<div>
<button id="to-upper-case">toUpperCase</button>
<button id="to-lower-case">toLowerCase</button>
</div>
<h2>응답</h2>
<pre id="response-wrapper"></pre>
</div>
<script src="./App.js"></script>
</body>
</html>
이제 우리는 서버가 제 기능을 하도록 구현하기만 하면 된다.
우선은 먼저 preflight
를 먼저 처리해줘서 이 클라이언트가 접근할 수 있는 권한을 허용해 줘야한다. 그러기 위해서는 먼저 올라온 요청의 method
을 뽑아내서 비교해 줘야하는데 그것 분해 하는 방법은 다음과 같다.
const { method, url} = request;
위 표현을 통해서 우리는 올라온 요청에 대한 method
와 url
을 추출해 낼 수 있다.
이제 이걸 이용해서 preflight를 처리하고 실제 요청을 받아와서 실제요청을 잘 처리해주면 된다. 여기서 요청을 처리할 body
부분은 기존의 method
와 url
을 받아오는 방법과는 차이가 있다.
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// 여기서 `body`에 전체 요청 바디가 문자열로 담긴다.
});
위 코드를 잘 활용해서 요청에 따른 응답을 적절하게 반환해 주면 된다.
app.js
의 코드를 본다면 뒤에 붙는 url
이 /upper
인지 /lower
인지에 따라서 대,소문자 변경이 바뀌게 된다. 그렇다면 if
문을 통해서 각 경우를 나눠주고 각자 반환된 값을 response
를 통해서 돌려주면 된다.
if (req.method === 'POST') {
if (req.url === '/lower') {
let data = '';
req.on('data', chunk => {
data = data + chunk;
});
req.on('end', () => {
data = data.toLowerCase();
res.writeHead(201, defaultCorsHeader);
res.end(data);
});
} else if (req.url === '/upper') {
let data = '';
req.on('data', chunk => {
data = data + chunk;
});
req.on('end', () => {
data = data.toUpperCase();
res.writeHead(201, defaultCorsHeader);
res.end(data);
});
} else {
res.writeHead(404, defaultCorsHeader);
res.end();
}
}
if (req.method === 'OPTIONS') {
res.writeHead(200, defaultCorsHeader);
res.end();
}
앞서 우리가 작성한 Chatterbox Client의 서버 부분을 직접 구현해보려 한다.
let results = {results:[]}
const requestHandler = function (request, response) {
if(request.method === 'OPTIONS'){
response.writeHead(200, headers)
response.end();
}else if(request.method === 'GET' && request.url === '/messages'){
response.writeHead(200, headers)
response.end(JSON.stringify(results));
}else if (request.method === 'POST' && request.url === '/messages') {
let body = [];
request
.on('error', (err) => console.log(err))
.on('data', (chunk) => {body.push(chunk)})
.on('end', () => {
body = Buffer.concat(body).toString();
results.results.push(JSON.parse(body));
response.writeHead(201, headers);
response.end(JSON.stringify(results));
})
}else{
response.writeHead(404, headers)
response.end();
}
}
앞서 배운 내용을 활용해서 요청에 따라서 분기를 나눈다. 각 메소드의 경우 처리를 다음과 같이 나눴다.
OPTION : CORS 요청을 처리해 준다.
GET : Client가 처리 가능한 데이터로 넘겨준다.
POST : results에 올라온 데이터를 넣어주고 데이터를 반환해 준다.