08/18, chatterbox server

Ian·2020년 8월 18일
0

Today I Learned

목록 보기
1/40
post-thumbnail

CORS, 그리고 Header

  • CORS가 생긴이유

예전엔 서버가 클라이언트라는 파일을 가지고 있었고, 유저가 서버에게 요청을 하면 서버가 클라이언트를 전달하는 방식이었음. Same Origin, 즉 서버에서 준 Client 였기 때문에 서버는 의심을 하지 않고 주고받음

그러나 최근 Web App 이 고도화되면서, 여러 곳에 있는 리소스를 활용해야 할 이유가 생겼음. 그래서 이전처럼 Same Origin 이 아니라, Cross Origin 상황이 생김. CORS 는 위와 같은 상황인 Cross Origin Resource Sharing 의 약자로, 다른 Origin 에서 Resource 를 요청하기 위해 필요한 것.

일단 기본적으로 브라우저에서 Corss Domain Request 는 기본적으로 제한되어있음. 이유는 보안상의 이유. 그러나 고도화 된 앱의 기술수준을 만족하기 위해서 이는 필요한 기능이었고 개선을 거쳐 현재는 서버가 허용한 범위 내에서는 Cross Origin 요청을 허용 할 수 있음.

  • Header파일의 설정

이를 가능케 하는 것은 Header파일에서의 설정인데, 이 CORS 를 허용하게끔 하는 헤더의 대략적인 코드와 주석을 적어보자면 다음과 같음

const defaultCorsHeader = {
  'access-control-allow-origin': '*',
	//wild card(*) 를 이용해, 모든 도메인에서의 CORS 요청을 허용하겠다는 의미 
  'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',
	//허용 가능한 method 는 'GET, POST, PUT, DELETE, OPTIONS' 로 제한함
  'access-control-allow-headers': 'content-type, accept',
	//헤더에는 'content-type, 그리고 accept' 까지만 쓸 수 있으며 
  'access-control-max-age': 10 //sec
	//preflight 요청은 10초까지만 허용가능하다 
};

그리고, 이 CORS 요청과 서버와의 통신은 이런 순서대로 이뤄진다

  1. 브라우저가 OPTION 메서드를 통해 서버에게 preflight request 를 보내 CORS ORIGIN 에 대한 정보를 확인한다.
  2. 허가를 받는다면, POST 등의 요청을 보내면서(서버가 허용한 메서드여야 가능하) 서버와 통신을 계속한다.

Sprint : Chatterbox-Server

intro chatterbox-server

  1. SPEC
    • HTTP 서버 만들기
    • 각 요청 분기하기 (routing)
    • 분기에 따른 API 제공하기
    • API 문서 작성하기

2. SPEC 에 대한 상세 설명

  • HTTP 서버 : HTTP Protocol을 통해 통신해서 API 를 제공하는 주체
    • 메세지를 달라는 GET 요청을 하면 GET 요청에 대한 응답을 줌
    • 메세지를 저장하라는 POST 요청을 하면 POST 요청에 대한 응답을 줌
    • 응답을 주지 않으면 안 됨!
  • GETPOST 에 따라 분기하기
    • 분기를 통해 데이터가 오면, 서버는 필요한 데이터를 만들어 다시 응답함
  • 데이터는 저장이 가능하고, 불러오기가 가능해야 함
    • 그러나 일단 저장하는 방법을 배우진 않았기 때문에, ObjectArray를 통해 임시로 받아서 처리해보자
    • 물론, 이는 서버가 꺼지면 사라지는데, 서버가 꺼져도 사라지지 않게 하기 위해 fs module을 통해 저장하는 방법이 있긴 함 (기본적으론 Database 를 통해서 하지만...)
      • 일단 위에 나온대로 Array 나 Object 에 저장하는 방식을 먼저 구현하고 모든 bare requirement 를 끝낸 다음 도전해보자
  • API 를 만들고 API 문서 제작까지 해야 한다, 그것이 백엔드 개발자의 소양
  • API 문서에 들어가야 할 내용들
    • 간략한 API 사용법 : 어떤 method 에 어떤 path 로 들어와야 API 가 작동하는지
    • 기대되는 return data 의 형식
    • 예제 코드

node js 에서의 require, 그리고 export

require(), exports, module.exports 공식문서로 이해하기

이해하기 쉽게 요약한 글

Node.js v14.8.0 Documentation

node.js 의 export shortcuts 문서

Node.js v14.8.0 Documentation

node.js 의 require 문서

예제 코드

request-handler.js파일에서 const 로 선언한 함수 requestHandler를 export 하려면?

const requestHanlder = function(req, res) {
	//code...
}

module.export = requestHanlder;

그리고 그것을 불러오려면?

const requestHanlder = require('/request-handler.js');

그 외에도 JS의 export 가 있는데, node.js 환경에서는 module.export 만이 사용이 가능하다. 그래서 module.export 를 사용하여 requestHandler 를 내보냈다.

routing, and how to make efficient routing?

routing 의 정의 : 서버로부터 들어오는 요청들을 조건에 따라 나누는, 즉 분기하는 것

일단 오늘은 /messages 라는 URL 만을 사용해서 데이터를 주고받을 것이라, URL 을 기준으로 먼저 routing 을 했다. 그리고 그 다음엔 method 들을 기준으로 routing 을 처리하였다.

// /messages 로 날아오는 것들을 먼저 route 한다 
if (request.url === "/messages") {
    // 그 다음, method 기준으로 분기를 해주자
    if (request.method === "POST") {
      let data = '';
      request.on('data', (chunk) => {
        data += chunk;
      });
      request.on('end', () => {
        data = data.toString(); // 일단은 buffer -> string 으로 바꿔줌
        console.log(data);
        container.results.push(JSON.parse(data));
        response.writeHead(201, headers);
        response.end(data); // 그리고 json -> object 로 바꿔줌
      })
    }
    else if (request.method === "GET") {
      response.writeHead(200, headers);
      // console.log(msgDatas)
      // console.log(msgDatas[0])
      response.end(JSON.stringify(container));
    }
		//OPTIONS 로 preflight request 를 날리는 경우는 header 와 status code 만 response
    else if (request.method === "OPTIONS") {
      response.writeHead(201, headers);
      response.end();
    }
    // endpoint가 /messages 가 아닌 경우는 모두 404 status code 를 response 
  } else {
    response.writeHead(404, headers);
    response.end();
  }

// cors 관련 세팅을 잡아준 header 
const headers = {
  "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 // Seconds.
};

request and response

  • How to handle the POST request body in Node.js without using a framework

How to handle the POST request body in Node.js without using a framework

  • node 의 HTTP 트랜잭션 해부

HTTP 트랜잭션 해부 | Node.js


Office Hour

오늘 하는 것은 http module 를 사용한 서버 구현

oneventEmitter, event 가 오면 작동을 시작하라! 라는 기능이라고 볼수 있다.

→ 요청에 따른 응답을 주는 HTTP 의 기본적인 형태와 일맥상통하다.

문서를 '반드시' 위에부터 꼭 정독할 필요는 없다, 실행되는 예제(working example)들을 복붙하고 조금씩 수정해가고, 그 때 문서를 찾아보며 능동적으로 이해하는 게 좋다. 그러면서 test case 들을 통과시키면서 이해하면 Best.

request 의 error, 그리고 response 의 error 를 둘 다 처리해주면 좋다.

response.end() 는 응답을 마무리해준다는 걸 명시해주는 객체이다.

content-type : 적절한 MIME type 을 넣어주는 header 의 일부분

**header 를 넣는 방법은 두 개**

  • setHeader : 하나하나씩 key-value 쌍으로 넣는다
  • writeHead : 객체형태까지 한 번에 넣어준다, 대신 여기에 statusCode 도 같이 넣어준다
    • writeHead(statusCode, headerObj) 와 같은 식으로 사용가능
  • node.js 문서의 serverResponse 를 참고하면 된다.

**routing : 요청에 따른 분기를 의미하며, 크게 두 개를 기준으로 라우팅을 해준다.**

  • method (POST, GET, OPTION, PUT 등등)
  • url (aka endPoint) (/message, /users 등등)
    • 특히 중요한 건 request.url을 기준으로 나눠줄 때, /url 과 url 은 완전히 다르다는 점
  • CORS test flight request 를 위해 OPTION method 도 잡아줘야 한다

→ 날아오는 request 들을 를 이런 기준으로 나누어주면 된다. (조건문을 사용한다)

**Stream**

데이터를 한 번에 받지 않고 나누어 받는 일련의 단위를 의미한다. 그 일련의 단위만큼 잠시 데이터를 담아놓는 RAM 에 할당된 임시 공간을 Buffer라고 한다.

let body = [];
request.on('data', (chunk) => {
	body.push(chunk);
}).on('end', () => {
	//body 배열에 담긴 buffer 를 toString() 메서드를 이용해 변환한다
	//아니면, 공백 문자열에 + 연산자를 통해 buffer 의 하나하나의 조각들(chunk)를 합쳐도 된다
}

❓궁금한 점, 왜 .on 을 또 body 에 chunk 들을 다 담은다음 붙여주는 것일까?
→ 요청을 다 받고 요청이 끝나면 end 를 보내주는 걸 명시하기 위해 on('end') 를 사용한다.

**CORS setting with header file**

header 파일에 CORS 를 허용하는 정보를 기입하여 CORS 가 가능하게끔 해준다.

OPTIONS 메소드도 설정해 줘야한다, 왜냐면 계속 header 정보가 맞는지 아닌지 확인해봐야 하기 때문에.

네트워크 탭에서 All 부분에 method name 이fetch 가 아닌 경우는 OPTIONS method 라고 생각하면 된다.

여튼, 네트워크 탭에서 요청을 보았을 때 내 client 의 localhost 뒤의 port number 와 내가 구축한 server 의 port number 가 다른 상황이기 때문에 cross origin resource sharing 설정을 잡아주어야 한다는 점이다.

네트워크 탭에서 내가 어떤 요청을 보내고 어떤 응답을 보냈는지 반드시 확인해야 한다!


따로 알아본 것들

JSON.stringfy() 를 안 해주면 객체가 풀로 나오는게 아니라 [Object, Object] 같이 뜬다.

[ERR_INVALID_ARG_TYPE] 오류

HTTP 통신에서 서로 주고받는 데이터의 타입은string 혹은 buffer 만 가능하다. Object 를 그대로 전달해선 안 된다. 이를 JSON.stringify(Object) 등을 통해 string 화를 시켜주고, 받을 땐 이 JSON 을 parsing 해서 받아주면 된다.

error code 중에 201과 200 의 차이점

  • 200 : OK
    • 요청이 성공적으로 되었다는 의미만을 가진다
  • 201 : Created
    • 요청이 성공적고, 그 결과로 새로운 리소스가 생성되었다는 의미 또한 포함한다
    • 그렇기에 새로운 리소스를 생성하는 HTML method 인 POST 나 일부 PUT 요청 이후에 사용하는 것이 적절하다
profile
правда и красота, truth and beauty

0개의 댓글