코드스테이츠_S2U10_8,9W_목,금,월

윤뿔소·2022년 10월 13일
0

CodeStates

목록 보기
26/47

프론트여도 필요한 서버 만들기를 위해 CORS, node.js, Express 등을 알아본다!
참고

CORS

Cross-Origin Resource Sharing, 교차 출처 리소스 공유 허용 기술
SOP을 뚫어주는 기술

  • 유명한 CORS policy 오류,, 아래 사진은 호스트가 달라 반려됐다는 오류가 떴음
  • 그래서

그러면 SOP는 뭔데?!

SOP

Same-Origin Policy, 같은 출처만 리소스 공유 허용

  • 왜 있는 건데?
    • 잠재적 위험이 있는 문서들을 차단
    • 공격 경로 감소로 해킹 위협 감소 등
  • 동일한 출처는 뭔데?
    1. 프로토콜이 같아야함
      • https://www.codestates.com vs http://www.codestates.com
    2. 호스트가 같아야함
      • urclass.codestates.com vs codestates.com
    3. 포트가 같아야함(프로토콜도 이유가 됨)
      • https-443, http-80
      • http://codestates.com:81 vs http://codestates.com : 전자가 81로 들어가기에 X!

⭐️Mini Node Server

node.js 내장 모듈로 서버의 구조를 알고 nodemon으로 서버를 만들어보자! 서버 만들어지는 과정을 알기!
server.listen(포트, 아이피, 함수)를 입력해야 서버가 열림
그래서 nodemon으로 열면은 들어가짐, 근데 무한 로딩 왜?! 응답(respons.end)가 없어서!

기본 예시

서버는 이런 방식으로 열리고 요청, 응답을 받는다.

const http = require("http");
const server = http.createServer((request, response) => {
  // 여기서 작업 진행
  // 응답을 작성해 요청 시 이게 나오도록 설정
  // 결과적으로 응답이 1개만 나오도록 설정해야함(조건문 이용)
  response.end("응답 받았다~")
})
// 그 포트에 서버 열기
server.listen(4999, () => {
  console.log("서버 열렸다~")
})

OPTIONS + Pre-Flight + CORS

이 항목은 이제 같은 출처인지(CORS 정책에 맞는지) 확인하고 그다음 요청을 수행되게 만드는 항목이다.

// const server 중략
  // Pre-Flight 요청
  if (request.method === "OPTIONS") {
      response.writeHead(200, defaultCorsHeader);
      response.end("hello mini-server sprints");
    }
// 중략
// 맨 아래 구역에 '응답 헤더 존' 제작
const defaultCorsHeader = {
  // Value부분을 입력하여 완성
  "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,
};
  • Pre-FlightOPTIONS라는 메소드를 활용해 요청을 받기 전 허락되는 출처인지 확인 후 수용 or 반려함
    • 따로 있는 이유는 요청을 받기 전 서버를 보호함과 동시에 그 다음 요청을 하기 전 break같이 반려하기 위함이다. 더 효율적
  • defaultCorsHeader은 CORS 정책 기반으로 저렇게 작성하여 사용
    • .endresponse.writeHead(201, defaultCorsHeader);를 작성해 성공적인 응답이 되었다는 것을 CORS 기반으로 알려준다.

body 담기

body는 저번에 배웠다싶이 요청에서 담겨져 오는 내용을 뜻함

// 공식 사이트 : 배열로 넣고 
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // 여기서 `body`에 전체 요청 바디가 문자열로 담겨있음
});
// 야매 : chunk가 문자열로 담겨져 온다는 것을 이용, 큰 데이터는 무의미
let body = "";
request.on('data', (chunk) => {
  data = data + chunk;
})
  • .on()메소드는 addEventListner('click'()=>{})이랑 같은 사용법이 있어 'data'가 오면 data가 오고 있는, 즉 Buffering중일 때 '무엇을 하느냐'를 콜백함수로 지정했고, 'end'가 오면 이제 버퍼링이 끝났을 때 하라는 일을 지정한 것이다!!!!@

참고 : Buffer와 chunk

  • Buffer는 버퍼링에서 쓰는 버퍼로 chunk(덩어리)와 같은 말임, 유튜브 스트리밍될 때 '버퍼링이 걸렸다' => '데이터(청크, 버퍼)를 받아오는데 로딩이 걸리고 있다'라는 말과 똑같음
  • 위 코드를 보면 Bufferconcat()이라는 메소드가 있고 안에 body를 넣어 저렇게 쪼개져있던 버퍼, 청크들을 연결시켜줘 결론을 나오게 만드는 구조임

POST 요청 만들기

// http, server 중략
  // request 메소드, url은 도메인 뒤 path를 뜻함
  const { method, url } = request;
  // 요청 중 POST를 제작
  if (method === POST && url === "/upper") {
    // /upper로 요청 받은 상태, end
    response.end("upper의 결과물")
    // defaultCorsHeader는 CORS를 대입한 거임
  } else if (method === POST && url === "/lower") {
    // /lower로 요청 받은 상태, end
    response.end("lower의 결과물")
  } else (
    // 오류 예외 처리, 404로 에러 코드 주고 end로 마무리
    response.statusCode = 404;
    response.end();
    // CORS 기반 오류 처리
    // response.writeHead(404, defaultCorsHeader);
    // response.end("에러 떴어! 제대로 요청해줘")
  )

결론

// task
// [x] 1. 서버생성
// [x] 2. 메서드, 헤더, url  (node는 request객체에 각 프롭 넣어두어져있음 ok!)
// [x] 3. 요청 바디 ('data' 이벤트에서 발생시킨 청크는 Buffer)
// ------------------------------------------------------------
const http = require("http");
const PORT = 4999;
const ip = "localhost";

const server = http
  .createServer((request, response) => {
    //   console.log(`http request method is ${request.method}, url is ${request.url}`);
    //   response.writeHead(200, defaultCorsHeader);
    //   response.end("hello mini-server sprints");
    // });
    if (request.method === "OPTIONS") {
      response.writeHead(200, defaultCorsHeader);
      response.end("hello mini-server sprints");
    }
    if (request.method === "POST") {
      let data = "";
      request
        // data 이벤에서 나온 청크는 문자열임 => Buffer랑 같
        .on("data", (chunk) => {
          data = data + chunk;
          console.log(data);
        });
      if (request.url === "/upper") {
        // upper 주소시 바디 문자열이 upper로 변경, 리스폰 객체에 태워 보냄
        console.log("up" + data);
        request.on("end", () => {
          response.writeHead(201, defaultCorsHeader);
          response.end(data.toUpperCase());
        });
        return;
      } else if (request.url === "/lower") {
        console.log("low" + data);
        request.on("end", () => {
          response.writeHead(201, defaultCorsHeader);
          response.end(data.toLowerCase());
        });
        return;
      }
    } else {
      // 예외처리
      response.statusCode = 404;
      response.end();
    }
  })
  .listen(PORT, ip, () => {
    console.log(`http server listen on ${ip}:${PORT}`);
  });

// 응답헤더존 : CORS
const defaultCorsHeader = {
  // Value부분을 입력하여 완성
  "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,
};
  • 되게 길다.. 특히 CORS를 따로 만들어주는 것도,writeHead를 계속 집어 넣어주는 것도 힘들었는데 Express에서 다 해준다니 바로 해보자!

Express

node.js의 프레임워크
1. 미들웨어 추가 가능
2. 라우터 제공!

미들 웨어

  • express.json는 보통 배열, 객체만 받아준다. 왜냐면 json은 배열 객체만 다루기 때문에, 그래서 문자열을 넣으면 오류가 날 수 있다.
    • 그래서 오류가 나면 express.json()에 따로 넣어줘야한다.
    • app.use(express.json({ strict: false }));라는 미들웨어 추가한 뒤 JSON으로 된 요청바디(request body)를 파싱해서 받아오게 된다!

페어과제: StateAirline Server

  • 기본적으로 라우팅을 기본으로 서버를 쌓음
    • /airport, /flights 등 분기마다 expots, require을 써 불러오고 마지막에 모으는 형태
    • 맨 아래를 보면 저렇게 해주고 js파일을 따로 만들어서 만들었음, 한 파일에 몰아 쓰는 것 보다 훨씬 클린코딩!
    • 리액트의 컴포넌트식 개발법과 비슷함

req.params vs req.query

두가지 항목의 사용법과 차이점을 알아보자!

  • URI 접속 중(요청 중) /뒤에 쓰여진 것은 params, ?뒤에는 query이며 req.params(), req.query()로 불러온다.
    • const { params or query } = req.params or query 식으로 디스트럭쳐링도 가능
  • req.params(), req.query()의 용도 차이(의견 차이가 있음 고유함의 기준 차이?)
    • req.params()는 보통 고유값에 관한 값을 사용할 때
    • req.query()는 자주 쓰이고 고유하지 않을때, 특히 params의 데이터 중 걸러주는 역할

알게된 것

coa도 있다 express 만든 사람들이 만든 건데 차세대 프레임워크란다. express 마스터하고 한번 해보자!

profile
코뿔소처럼 저돌적으로

0개의 댓글