Server

안정태·2021년 5월 1일
0

Study

목록 보기
16/33

앞에서는 client의 요청을 보내는 것을 구현해보았다. 그렇다면 이제는 서버에서 그 요청을 받아서 응답을 처리하는 js를 구현해 볼 것이다
.

Mini node server

요청을 처리하고 응답을 하는데 앞서 우리는 먼저 서버를 구축해야만 한다. 다음 코드가 서버를 생성하는 기초적인 식이다.

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;

위 표현을 통해서 우리는 올라온 요청에 대한 methodurl을 추출해 낼 수 있다.
이제 이걸 이용해서 preflight를 처리하고 실제 요청을 받아와서 실제요청을 잘 처리해주면 된다. 여기서 요청을 처리할 body부분은 기존의 methodurl을 받아오는 방법과는 차이가 있다.

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 Server

앞서 우리가 작성한 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에 올라온 데이터를 넣어주고 데이터를 반환해 준다.

profile
코딩하는 펭귄

0개의 댓글