이번 스프린트는 직접 서버와 API를 작성하고 cors 사용하는 방법을 가져 보았습니다.
node.js의 express를 사용하지 않고 작성 해보았습니다.
// http를 통한 서버 만들기
const http = require('http');
// PORT번호 3000 사용자가 원하는데로 바꿀수 있다.
const PORT = 3000
const server = http.creatServer ((req, res) => {
res.writeHead(200); // Header에 보내준다. stateCode 200은 원하는 응답을 받았을 경우이다.
res.end('Hello, World!'); // response.end 함수 -> 원하는 객체, 문자열 ,배열 등등을 페이지에 보내준다.
});
server.listen(PORT, ip, () => {
console.log(`http server listen on ${ip}:${PORT}`);
});
리뷰는 reference code를 기반으로 해보겠습니다. 코드 내부의 주석 처리로 코드에 대한 전반적인 내용을 정리하고 스프린트를 진행하는데 있어서 힘들었던 부분에 대해 얘기 해보겠습니다.
const http = require('http');
// PORT번호 5000번을 사용한다.
const PORT = 5000;
const ip = 'localhost';
// 서버 생성
const server = http.createServer((req, res) => {
// 여기서의 req는 client에서 온 요청이다.
if (req.method === 'POST') {
if (req.url === '/lower') { // 요청 받은 url에 따라 처리해 줍니다.
let data = ''; // data를 "" 빈 스트링으로 설정해 주었다 , 여기서 배열로 설정 해 줄 수도 있습니다.
req.on('data', chunk => { // req.on 함수를 사용하여 data를 처리 한다. chunk 는 요청받은 데이터 입니다. 이 데이터를 빈 문자열인 data에 더해 주어 data를 사용합니다.
data += chunk;
});
req.on('end', () => {
data = data.toLowerCase();
res.writeHead(201, defaultCorsHeader);
res.end(JSON.stringify(data)); // 데이터를 다시 보내주는 경우에는 JSON.stringify를 사용하여 다시 `data(?)`로 문자열을 해주어 보내줍니다.
});
} else if (req.url === '/upper') {
let data = '';
req.on('data', chunk => {
data += chunk;
});
req.on('end', () => {
data = data.toUpperCase();
res.writeHead(201, defaultCorsHeader);
res.end(JSON.stringify(data));
});
} else {
res.writeHead(404, defaultCorsHeader); // 원하지 않는 url을 받았을 경우 stateCode 404를 보내주어 응답이 옳지 않음을 보내 줍니다.
res.end();
}
}
// OPTIONS처리를 해주어 cors를 미리 적용 시킵니다.
if (req.method === 'OPTIONS') {
res.writeHead(200, defaultCorsHeader);
res.end();
}
});
server.listen(PORT, ip, () => {
console.log(`http server listen on ${ip}:${PORT}`);
});
// CORS코드입니다. CORS는 헤더에 들어가며 url을 받는데에 있어서 허용된 url인지 확인해주는 역할을 합니다. 이를 통해서 외부 공격을 방지 할 수 있습니다.
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
};
스프린트를 진행 하는데에 있어 힘들었던 부분은 클라이언트로부터 요청받은 데이터(바디)를 어떻게 가공하고 처리 해야하나 이 부분에 있어서 가장 힘들었습니다. 이는 아래 출처인 node.js 공식문서 트랜잭션 해부를 통해서 해결 할 수 있었습니다.
위의 코드에서는 body부분을 data로 빈 문자열로 선언하였고 이를 chunk라는 req의 바디를 더해주어 해결 하였습니다.
이 바디를 배열로 선언하고 처리할때는 흥미로운 부분이 생깁니다.
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// 여기서 `body`에 전체 요청 바디가 문자열로 담겨있습니다.
});
배열에서는 바디를 body = Buffer.concat(body).toString(); 로 처리 해줍니다.
빈 문자열 let data = ''; data += chunk; 로 처리 하는데에 있어 큰 차이를 보입니다.
바디에 요청 받은 내용물인 chuck를 push해주고 이를 문자열로 바꾸어 줌에 따라 body를 사용 할 수 있게 해줍니다.
이 과정을 통해 body를 자유롭게 사용 할 수 있고 이를 다시 응답으로 보내 줄 때에는 즉 res.end
을 사용 할 때에는 문자열로 처리해주는 JSON.stringify
함수를 사용해서 문자열 처리를 해준 후 응답을 보내 줄 수 있습니다.
스프린트를 진행 하는데에 있어서 사실 혼자 처음 할 때는 해결 하지 못했습니다. 하지만 아래 출처를 엔지니어분으로부터 알게 되고 적용 하면서 나중에 처리 할 수 있게 되었습니다.
출처 : https://nodejs.org/ko/docs/guides/anatomy-of-an-http-transaction/