본문 바로가기
국비학원/수업기록

국비 지원 개발자 과정_Day47

by 루팽 2023. 2. 2.

Node.js

확장성 있는 네트워크 애플리케이션(특히 서버 사이드) 개발에 사용되는 소프트웨어 플랫폼

작성 언어로 자바스크립트를 활용하며 논블로킹(Non-blocking)  I/O와 단일 스레드(순서지킴) 이벤트 루프를 통한 높은 처리 성능을 가짐

 

JSON.stringify()

JavaScript 값이나 객체(Object)를 JSON 문자열로 변환

const datas = JSON.stringify(객체{”key”:”password”})

 

JSON.parse()

JSON 문자열의 구문을 분석하고, 그 결과에서 JavaScript 값이나 객체를 생성

문자열을 배열로 바꾸어 구조분해하는 함수 지원

const jsonDoc = JSON.parse(datas)

jsonDoc[0].key → 키값 출력

 

<네이버 API - captcha>

/* 
Express는 웹 및 모바일 애플리케이션(하이브리드앱->웹+앱{네이티브})을 위한 일련의 강력한 기능을 제공하는
간결하고 유연한 Node.js 웹 애플리케이션 프레임워크
ExpressAPI를 이용하면 자유롭게 활용할 수 있는 수많은 HTTP 유틸리티 메소드 및 미들웨어를 통해
쉽고 빠르게 강력한 API를 작성할 수 있음
*/

const express = require("express"); // 웹 어플리케이션을 위한 프레임워크 선언
// 선언하면 프레임워크가 제공하는 API를 누릴 수 있다 -> 그럴 때 nodejs에서는 require함수 사용
// 리액트에서는 import가 제공된다
// <script type = " module"></script> <-지원하면서 nodejs기반 서버사이드가 가능하게됨
const app = express();
// 네이버 서버에서 발급한 고유 아이디값 - 회원가입이 되어있고 개발자센터에서 어플리케이션 등록
const client_id = ""; // 개발자센터에서 발급받은 Client ID
const client_secret = ""; // 개발자센터에서 발급받은 Client Secret
const code = "0";
let key;
// expressjs에서는 REST API를 지원하는 메소드를 제공하고 있다
// 두번째 파라미터는 콜백 함수 - 첫번째 파라미터 요청에 대한 응답을 받기위해 호출되는 함수
// http프로토콜을 이용하여 서버에 요청하고 응답 처리를 위해서는
// 반드시 어떤 언어이든 요청 객체와 응답 객체를 제공받아야 한다
// 익스프레스도 그래서 제공하고있다
// req는 요청객체의 인스턴스 변수로 express로부터 객체주입 받는다 - 사용자가 생성할 수 없다
// 이런 경우 의존성 주입(Dependency Injection)이라고 할 수 있다
app.get("/captcha/nkey", function (req, res) {
  // 네이버 서버가 제안하는 URL주소 - 키값을 받아와야함(인증과정)
  const api_url = "https://openapi.naver.com/v1/captcha/nkey?code=" + code;
  // 네이버가 제공하는 URL주소로 네이버 서버에 요청을 해야하니까
  // npm i -g request -> request설치함
  const request = require("request");
  const options = {
    url: api_url,
    // http프로토콜을 통해 전송할 때 header body가 있는데 get은 그 중 headet를 이용함
    headers: {
      "X-Naver-Client-Id": client_id,
      "X-Naver-Client-Secret": client_secret,
    },
  };
  request.get(options, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      res.writeHead(200, { "Content-Type": "text/json;charset=utf-8" });
      // res.end(body);
      // console.log(body);
      key = body.substring(8, 24);
      console.log(key);
    } else {
      res.status(response.statusCode).end();
      console.log("error = " + response.statusCode);
    }
  });
});
// express로 구성하는 서버의 포트번호는 3000번
// 완성 URL
app.listen(3000, function () {
  console.log("http://127.0.0.1:3000/captcha/nkey app listening on port 3000!");
});

/* 
REST API
우리가 하고싶은 작업에 따라 다른 메소드로 요청을 하는 방법을 제공

HTTP메소드 수단으로 이용
GET - 데이터 조회
POST - 데이터 등록 및 전송
PUT - 데이터 수정
DELETE - 데이터 삭제
*/

 

const myHeaders = new Headers();
myHeaders.append("X-Naver-Client-Id", "");
myHeaders.append("X-Naver-Client-Secret", "");

const requestOptions = {
  method: "GET",
  headers: myHeaders,
  redirect: "follow",
};

fetch("https://openapi.naver.com/v1/captcha/nkey?code=0", requestOptions)
  .then((response) => response.json()) // json이면 result.key로 바로 키값 꺼내오 수 있음
  .then((result) => {
    console.log(result.key);
  })
  .catch((error) => console.log("error", error));

 

<연산자>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>연산자</title>
  </head>
  <body>
    <script type="text/javascript">
      /* 
    연산자
    특정 값을 도출하기위해 연산을 처리하는 식별자
    -산술 연산자 -, +, /, *, %, ++, --
    -대입 연산자 =, +=, =+, *=, /=
    -비교 연산자 ==, ===
    두개이면 값만 비교(타입체크X)
    세개이면 타입까지도 비교

    */
      let result = 1 == 1;
      console.log(1 == 1); // true, 콘솔에 찍힘
      console.log(1 === 1); // false
      document.write(result); // true, 화면에 찍힘
    </script>
  </body>
</html>

 

console.log(1 == "1"); // true, 값만 비교
console.log(1 === "1"); // false, 값과 타입까지 비교

 

<형변환>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>형변환</title>
  </head>
  <body>
    <script type="text/javascript">
      // 형변환 - 특정 조건이 만족되면 자료형이 강제로 변환됨
      const num1 = "2"; // 문자
      const num2 = 3; // 숫자
      const num3 = 5; // 숫자
      
      console.log(num1 + num2 + num3); // 235, 문자+숫자 = 문자
      document.write(typeof (num1 + num2 + num3)); // string
      document.write("<br />");

      console.log(num3 + num2 + num1); // 82, 숫자+문자 = 문자
      document.write(typeof (num3 + num2 + num1)); // string
      document.write("<br />");

      console.log(num3 + num2 + parseInt(num1)); // 10, 숫자+숫자
      document.write(typeof (num3 + num2 + parseInt(num1))); // number
    </script>
  </body>
</html>

 

<배열>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>배열</title>
  </head>
  <body>
    <!-- 브라우저는 mime타입을보고 판단 -->
    <script type="text/javascript">
      /* 
    배열(Array)
    연관된 값들을 하나의 그룹으로 묶어서 나열한 구조
    */
      const fruits = ["🍓", "🍌", "🍒"];
      // 원시적인 for문 처리(인덱스값이 있음)
      for (let i = 0; i < fruits.length; i++) {
        document.write(fruits[i]);
      }

      // forEach 처리(리액트 많이사용)
      const array1 = ["a", "b", "c"];
      fruits.forEach((element) => console.log(element));
      fruits.forEach((element, index) => console.log(index, element));
      fruits.forEach((element, index, fruits) =>
        console.log(index, element, fruits)
      );
      fruits.forEach((element, index, fruits) => {
        document.write(index, element, fruits);
      });
    </script>
  </body>
</html>

 

<객체>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>객체</title>
  </head>
  <body>
    <script type="text/javascript">
      /*
        객체(Object)
        데이터를 property라는 인덱싱을 통해 구조적으로 묶어놓은 것
        */
      let student = {
        name: "이성계",
        age: 35,
        address: "서울시 마포구 공덕동",
      };
      document.write(student);
      document.write("<br />");
      document.write(student.name);
      document.write("<br />");
      document.write(student["name"]);
      document.write(student["age"]);
      document.write("<br />");
      student.name = "강감찬";
      document.write(student["name"]);
    </script>
  </body>
</html>

 

<함수>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script type="text/javascript">
      // 선언적 함수
      hap(); // 호출 먼저 선언 나중에해도 실행됨
      function hap() {
        console.log("hap"); // hap
      }

      // 대입형 함수(일급함수)
      const minus = function (a = 1, b = 3) {
        const num1 = 2;
        const num2 = 1;
        document.write(num1 + num2);
        document.write("<br />");
        document.write(a + b);
      };

      minus(5, 7); // 3과 12출력됨
    </script>
  </body>
</html>

<!--
  함수
    자주쓰는 실행코드를 블록단위로 묶어놓은 것
    기능단위로 재사용하기위해서
    선언은 function 키워드 사용하거나 arrow function 처리
    호출: 정의되어있는 함수는 호출해야 비로서 기능이 실행됨

  함수의 종류
    선언적 함수
      이름을 붙여서 정의한 함수
      자바스크립트를 읽을 때 우선적으로 읽어줌
      호출 위치가 자유롭다
      
    익명 함수
      이름없이 정의한 함수 - 콜백함수와 연결(중요)
      자체로 호출 불가
      변수에 익명함수를 대입하거나 특정 이벤트 객체에 대입해서 호출

    대입형 함수
      변수에 익명함수가 대입된 형태 -> 일급함수, 고차함수
      일급함수(함수를 다른 변수와 동일하게 다룸, 함수에 다른 함수를 인수로 제공, 함수 반환)

    즉시실행함수
      함수가 자기자신을 정의하자마자 바로 자신을 호출함
-->

 

<일급함수>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>일급함수(대입형함수)</title>
  </head>
  <body>
    <script type="text/javascript">
      //함수를 다른 함수에 파라미터로 제공
      function sayHello() {
        return "Hello, ";
      }
      function greeting(helloMessage, name) {
        console.log(helloMessage() + name);
      }

      // sayHello를 greeting 함수에 인자(파라미터)로 전달
      greeting(sayHello, "JavaScript!");
    </script>
  </body>
</html>

<!--
  일급함수
  함수를 다른 변수와 동일하게 다루는 언어는 일급 함수를 가졌다고 표현함
  일급 함수를 가진 언어에서는 함수를 다른 함수에 인수로 제공, 함수가 함수를 반환, 변수에 할당할 수 있음
-->

 

<고차함수>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>고차함수(반환형으로 함수가능)</title>
  </head>
  <body>
    <script type="text/javascript">
      // 일급함수(대입형함수)
      const sayHello = function () {
        //고차함수(함수를 반환형으로 사용)
        return function () {
          console.log("Hello!");
        };
      };

      const myFunc = sayHello();
      myFunc();
    </script>
  </body>
</html>

<!-- 
  고차함수
    함수를 반환하는 함수
    리액트 리덕스 컨셉 재현할 때 필요
    구독발행 모델 구현해볼때
    커리함수
-->

 

<화살표함수>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>화살표함수</title>
  </head>
  <body>
    <script type="text/javascript">
      // 선언적 함수
      function hap(a1, a2) {
        console.log(a1);
      }

      hap(); // undefined - 지역변수
      hap(1, 2); // 1, call by value(호출될때 초기화, 값이 결정됨)
      hap(3); // 3

      // 일급 함수
      const hap1 = function (a1, a2) {
        const result = a1 + a2;
        return result;
      };
      console.log(hap1(1, 1)); // 2

      // 화살표함수
      const hap2 = (a1, a2) => {
        const result = a1 + a2;
        return result;
      };
      console.log(hap2(2, 2)); // 4

      // 화살표함수, 인자가 하나일 땐 괄호 생략 가능
      const hap3 = (a1) => {
        const result = a1;
        return result;
      };
      console.log(hap3(3)); // 3
    </script>
  </body>
</html>

<!-- 
  Arrow function(화살표함수)
    기존의 익명함수를 좀 더 쓰기 쉽게 축약한 형태
    내부로 전달되는 파라미터가 하나면 괄호는 생략 가능
    
  자바스크립트는 같은 이름의 함수를 중복정의 못함
  왜냐면 메소드 오버로딩이 없으니까
  결론: 함수의 이름은 무조건 다르게 작명함
-->

 

<마임타입>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script type="text/javascript"></script>
  </body>
</html>

<!-- 
  함수 매개변수(parameter) - myBatis ORM솔루션
    사용자가 입력한 값을 받아오는 자리
    함수 외부에서 함수 내부로 특정값을 전달하기위한 통로

    mime type
    메인타입/서브타입
    주의: 모르는 타입이면 무조건 다운로드 발생
    text/plain -> 텍스트노드일때
    text/html, text/css, text/javascript, text/xml
    media/mp4, media/avi
    image/jpg, image/png, image/gif, image/tiff
    application/json
    application/word
    application/excel
    브라우저는 마임타입을 읽어서 판독함
-->

 

<즉시실행함수>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>즉시실행함수</title>
  </head>
  <body>
    <script type="text/javascript">
      (function (x) {
        // 실행부 - 변수 선언( paecel설정하면 var -> let, const인 것같이 처리됨)
        // 제어문, 로직
        // document는 즉시실행함수.html문서 전체를 받는 내장객체
        // 내장객체는 브라우저 안에 정의되어있어서, 필요시 생성없이 브라우저로부터 객체주입이 됨
        // const myCar = new Sonate() -> 이런 인스턴스화 없이 쓸 수 있는게 내장객체
        document.write("test" + x);
      })(5000);
    </script>
  </body>
</html>

<!-- 
  즉시실행함수
    호이스팅 이슈를 해결하는 방법으로 사용
    특정 원치않는 공간으로 그 값이 빠져나가지 못하게 할 때 사용
    즉시 실행 함수 안쪽의 값들을 캡슐화할 때 사용

    괄호가 2개
      첫번째 괄호는 함수의 정의 부분
      두번째 괄호는 그 함수를 호출하는 괄호
-->

 

<익명함수>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>익명함수</title>
  </head>
  <body>
    <script type="text/javascript">
      // text/javascript -> module -> 구글개발자센터 -> RealtimeServer(채팅구현 쉽다)
      const words = [
        "spray",
        "limit",
        "elite",
        "exuberant",
        "destruction",
        "present",
      ];

      const result = words.filter((word) => word.length > 6);

      console.log(result); // (3) ['exuberant', 'destruction', 'present']
      document.write(typeof result); // object
      document.write("<br />");
      document.write(result[0]); // exuberant
      document.write("<br />");
      document.write(result[1]); // destruction
      document.write("<br />");
      document.write(result[2]); // present
      document.write("<br />");
      document.write("<hr>");

      // 배열[] 구조분해할당 -> 리액트 필수문법
      const [a, b, c] = result;
      document.write(a, " ", b, " ", c, " "); // exuberant destruction present
      document.write("<hr>");

      // 객체{} 구조분해할당
      let student = {
        name: "이성계",
        age: 35,
        address: "서울시 마포구 공덕동",
      };

      const { name, age, address } = student;
      document.write(`${name} ${age} ${address}`); // 이성계 35 서울시 마포구 공덕동
    </script>
  </body>
</html>

 

<전개연산자>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script type="text/javascript">
      let hobby = ["게임", "헬스", "독서"];
      let hobby2 = ["코딩", "스노우보드", "댄스"];
      let merge = [...hobby, ...hobby2];

      merge.forEach((item) => {
        document.write(item + "<br />");
      });
      // 게임 헬스 독서 코딩 스노우보드 댄스

      merge.forEach((row, index) => {
        document.write(`<b>${row}</b>${index} <br />`);
      });
      // 게임0 헬스1 독서2 코딩3 스노우보드4 댄스5
    </script>
  </body>
</html>

 

<구조분해, 전개 연산자>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>도전문제 - 구조분해, spread연산</title>
  </head>
  <body>
    <script type="text/javascript">
      // 리액트 -> 태그와 자바스크립트 코드를 같이쓴다
      // items는 배열 -> 배열 안에 객체가 있다(배열, 객체, 배열안에 객체 있을때 전부 연습)
      let items = [
        { id: 1, name: "벤치프레스", count: 10 },
        { id: 2, name: "랫풀다운", count: 12 },
        { id: 3, name: "스쿼트", count: 30 },
      ];

      //조회하기 - forEach
      // 더블쿼테이션(")과 싱글쿼테이션(') -> 같이 사용하 경우 바깥쪽을 더블, 안쪽을 싱글
      // <태그 속성명=값>내용</태그>
      document.write("<div>");
      document.write("<table border='1' borderColor='green'>");
      items.forEach((item) => {
        document.write("<tr>");
        document.write(`<td>${item.id}`);
        document.write(`<td>${item.name}</td>`);
        document.write(`<td>${item.count}</td>`);
      });
      document.write("</tr>");
      document.write("</table>");
      document.write("</div>");

      // 추가하기 - 전개연산자
      let items_copy = [...items, { id: 4, name: "플랭크", count: 5 }];
      // 출력
      document.write("<table border='1' borderColor='blue'>");
      items_copy.forEach((item) => {
        document.write("<tr>");
        document.write(`<td>${item.id}`);
        document.write(`<td>${item.name}</td>`);
        document.write(`<td>${item.count}</td>`);
      });
      document.write("</tr>");
      document.write("</table>");

      // 삭제하기 - filter함수
      // 대화형 프로그래밍 처리 훈련
      // prompt로 받으면 반환값이 문자열이다(===, !== 사용시 타입도 따지기에 주의!)
      let result = -1;
      // result = window.prompt("삭제하고자 하는 id를 입력하세요");
      // alert("사용자가 선택한 id는 " + result + "입니다.");
      // filter함수는 조건을 수렴하는 것만 남겨서 새로운 배열을 반환함
      items_copy = items_copy.filter((item) => item.id !== parseInt(result));
      // 출력
      document.write("<table border='1' borderColor='red'>");
      items_copy.forEach((item) => {
        document.write("<tr>");
        document.write(`<td>${item.id}`);
        document.write(`<td>${item.name}</td>`);
        document.write(`<td>${item.count}</td>`);
      });
      document.write("</tr>");
      document.write("</table>");

      // 수정하기 - 추가하기와 동일하게 처리
      let x = [...items_copy];
      result = window.prompt("수정하고자 하는 id를 입력하세요");
      x.forEach((item) => {
        if (item.id === parseInt(result)) {
          x = items_copy.filter((item) => item.id !== parseInt(result));
          x = [
            ...x,
            { id: `${parseInt(result)}`, name: "마운틴 클라이머", count: 30 },
          ];
        }
      });
      // 출력
      document.write("<table border='1' borderColor='yellow'>");
      x.forEach((item) => {
        document.write("<tr>");
        document.write(`<td>${item.id}`);
        document.write(`<td>${item.name}</td>`);
        document.write(`<td>${item.count}</td>`);
      });
      document.write("</tr>");
      document.write("</table>");
    </script>
  </body>
</html>

 

번들러

html, css, ES5만으로 페이지를 구현하는 것은 비효율적

vue.js, ES6,7, typescript, sass(css전처리기), postcss, svelt 등을 이용해서 페이지를 구현하게 됨

기존의 html, css, ES5로 바꿔주는 것이 번들러

 

parcel

sass 그대로 브라우저 실행이 불가함

이것을 css로 변경해주는 것이 parcel이 하는 역할

 

프로젝트명 정하기

물리적 폴더를 작성

이 폴더 아래에서 순서대로 진행하기

이렇게 프로젝트를 생성하면 하위버전의 컴퓨터, 브라우저에서도 동작할 수 있다

원시적인 코드로 만들어준다

이때 환경변수 설정 파일은 package.json이다

JSON형식에 대한 역할, 이해가 필요하다

 

1. npm init -y 엔터 하여 package.json을 생성해 줌

2. npm i -D parcel 엔터 하여 번들러 설치

npm 설치옵션 -D 패키지를 설치하고 프로젝트의 devDependencies 목록에 추가한다

--save-dev 패키지를 설치하고 프로젝트의 devDependencies 목록에 추가한다

-g 패키지를 프로젝트가 아닌 시스템의 node_modules 폴더에 설치한다

설치 후 반드시 package.json을 열어서 devDependencies목록에 parcel번들러 추가 확인할 것

3. index.html 파일 생성

4. package.json에 실행 명령문 등록 및 배포(빌드포함) 명령문 등록하기

5. npm run dev 실행명령

6. npm run build 배포버전 만들 때 사용할 것 main:index.js 삭제해야 에러 없이 배포버전이 생성 배포버전이 만들어지면 dist폴더가 생성됨

 

<해커뉴스 API>

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>해커뉴스API-실습</title>
    <link rel="stylesheet" href="./css/style.css" />
  </head>
  <body>
    해커뉴스 서비스입니다.
  </body>
</html>

 

* {
  /* *는 모든 요소(태그, 노드)를 나타냄 */
  box-sizing: border-box; /* 외부 여백, 내부 여백을 포함한 크기 계산 */
}

댓글