37일차 Mini Node Server

2021. 9. 10. 23:52
반응형

2021. 09. 08 수요일

1. Today's Key points!🔑

  • mini node server

2. Sprint 복기!🧐

오늘은 개념정리보다는 바로 sprint과제를 복기해보는 것이 더 좋을 것 같다.

과제를 진행하기에 앞서 설치해야할 것이 하나 있다. 바로 nodemon이다. 터미널에 npm install -g nodemon 입력해서 설치를 한 뒤, package.json 파일을 열어 "scripts" 안에 "start": "nodemon servere/basic-server.js" 를 입력해준다.

"scripts": {
    "start": "nodemon server/basic-server.js",
    "test": "echo no test",
    "submit": "echo you don\\'t need to submit"
  },

이렇게 해준 뒤 npm run start를 해주면 서버.js 파일을 저장하면 자동으로 수정된 서버가 열리게 된다. html 라이브 서버를 사용하듯이 사용할 수 있기 때문에 매우 편리해진다.

nodemon 설치를 완료했다면 이제 과제를 진행해보자.

클라이언트의 액션(버튼 클릭)에 따라 각기 다른 HTTP 요청을 서버로 보내고, HTTP 요청에 담아 보낸 단어를 소문자 또는 대문자로 변경된 단어를 응답으로 받아 화면에 보여준다. 여기 나와있는 'HTTP 트랜잭션 해부' 공식문서를 보면서 과제를 풀어나갔다.

키워드 하나하나를 전부 이해하지는 못했지만, 요청 바디는 이렇게 하면 된다고 나와있다.

const http = require('http');

http.createServer((request, response) => {
  const { headers, method, url } = request;
  let body = [];
  request.on('error', (err) => {
    console.error(err);
  }).on('data', (chunk) => { //data가 들어올 때
    body.push(chunk);
  }).on('end', () => { // data가 다 들어왔을 때
    body = Buffer.concat(body).toString();
    // 여기서 헤더, 메서드, url, 바디를 가지게 되었고
    // 이 요청에 응답하는 데 필요한 어떤 일이라도 할 수 있게 되었습니다.
  });
}).listen(8080); // 이 서버를 활성화하고 8080 포트로 받습니다.

이것을 보고 하나씩 만들어나가 보았다. 우선 크게 4가지의 조건을 줘야한다. 메소드가 OPTION일때 CORS 설정을 돌려줘야하고, 메소드가 POST이고 url이 /lower일때, 메소드가 POST이고 url이 /upper일때, 에러처리까지 4가지 조건을 생각하면서 코드를 작성했다.

여기서 살짝 주의해 주어야 할 부분이 있다. 각 if에서 response.end()를 보내고 있는데, 한 번의 요청을 하면 한 번의 응답을 내어주어야 한다. 그래서 else if 처리를 잘 해주거나, 매 if문 안에서 return으로 전체 함수에서 빠져나와야 한번의 요청에 한번의 응답을 보낼 수 있게 된다. 그렇지 않으면 오류가 나게되니 조심하자.

const http = require('http');
const PORT = 5000;
const ip = 'localhost';

const server = http.createServer((request, response) => {
  if (request.method === 'OPTIONS') {
    response.writeHead(200, defaultCorsHeader);
    response.end();
    return;
  } 
  let body = [];
  if (request.method === 'POST' && request.url === '/lower') {
  request.on('data', (chunk) => {
    body.push(chunk);
  }).on('end', () => {
    body = Buffer.concat(body).toString().toLowerCase();
    response.writeHead(200, defaultCorsHeader);
    response.end(body);
    return;
  });
  } 
  else if (request.method === 'POST' && request.url === '/upper') {
    request.on('data', (chunk) => {
    body.push(chunk);
  }).on('end', () => {
    body = Buffer.concat(body).toString().toUpperCase();
    response.writeHead(200, defaultCorsHeader);
    response.end(body);
    return;
  });
  }
  else {
    response.statusCode = 404;
    response.end();
  } 
}).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 서버를 작동시키면 잘 작동이 된다.

toUpperCase / toLowerCase

잘 작동되는 것을 확인했으니, 이제 serve 유틸리티를 이용해서 클라이언트를 실행하고, 서버의 Access-Control-Allow-Origin을 클라이언트의 origin으로 특정해보면서 지정한 origin외에 다른 곳에서 접근이 가능한지 확인해보자.

그럼 우선 npx serve client -l 5100 을 터미널에 입력해서 5100 포트로 클라이언트를 열어보자. 이때 localhost:5000 서버는 열어둔 상태여야 한다.

(여기서 한가지 주의해야할 점은 npx serve client 이렇게 터미널에 치면 5000번 포트의 클라이언트가 열리게 된다. 그럼 서버와 포트가 겹쳐버려서 제대로 작동이 되지않는 불상사가 일어나게된다. 사실 이거때문에 삽질을 많이 했다.. ㅜㅜ 그래서 포트번호를 지정해서 서버와 안겹치에 클라이언트를 열어서 진행하니 제대로 확인이 가능했다.)

이렇게 5100 클라이언트를 열고 작동시켜보면 잘 작동한다.

왜 잘 작동하냐? CorsHeader에 'Access-Control-Allow-Origin'에 'http://localhost:5100'입력해주었기 때문에 5100번 포트는 잘 작동한다.

const defaultCorsHeader = {
  'Access-Control-Allow-Origin': 'http://localhost:5100',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10
};

그럼 저 부분을 다른 포트 번호로 바꾸고 실행시켜보자.

const defaultCorsHeader = {
  'Access-Control-Allow-Origin': 'http://localhost:5200',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10
};

에러 메시지를 보면 5200번 포트에 허용을 줬기 때문에 5100번 포트는 접근을 할 수 없다는 오류메시지를 볼 수 있다.

다음은 클라이언트 코드(App.js)의 요청 헤더를 수정해서 preflight request가 발생하는지를 살펴보자. Content-Type을 text/plain으로 수정해보자.

post(path, body) {
    fetch(`http://localhost:5000/${path}`, {
      method: 'POST',
      body: JSON.stringify(body),
      headers: {
        'Content-Type': 'text/plain' //이 부분
      }
    })
      .then(res => res.json())
      .then(res => {
        this.render(res);
      });
  }

그렇다면 이유가 무엇일까? 단순 요청(Simple requests)이기 때문이다. 여기 공식문서를 보면 좀 더 자세한 정보를 볼 수 있다. 문서를 살펴 보면 Content-Type 헤더에 아래의 3가지를 입력하면 단순 요청을 하기때문에 preflight requests가 발생하지 않는다고 한다.

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

마무리 Comment...😳

이 스프린트를 통해서 단순한 웹 서버를 구현해 보았다. 가이드를 참고해서 코드는 거의 복붙하다시피 해서 구현했고, 구현하고 나서 요청을 보내거나 받는 방식을 확인하는 것이 좀 더 중요하다는 것을 알 수 있었고, 기본적인 서버 요청과 응답에 대해 익힐 수 있었다. 

반응형
LIST

BELATED ARTICLES

more