<비동기 처리> : 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 자바스크립트의 특성

           console.log("hello")

           setTimeout(function() {

                      console.log('Bye')

           }, 3000)

           console.log("hello again")

           >>hello

           hello again

           Bye

<async, await로 비동기 처리 방식의 문제점 해결>

           function fetchItems() {

           return new Promise(function(resolve, reject) {

                      var items = [1,2,3]

                      resolve(items)

                      })

           }

 

           async function logItems(){

                      var resultItems = await fetchItems();

                      console.log(resultItems)

           }

 

<Promise> : 자바스크립트 비동기처리에 사용되는 객체

프로미스의 3가지 상태(states)

1. Pending(대기)

           new Promise(function(resolve, reject){

                      //

           });

2. Fulfilled(이행)

           new Promise(function(resolve, reject){

                      resolve();

           });

           then()을 이용하여 처리 결과 값을 받을 수 있음

3. Rejected(실패)

           new Promise(function(resolve, reject){

                      reject();

           });

           catch()로 실패 이유를 받을 수 있음

ex) function getData(){

           return new Promise(function(resolve, reject) {

                      var data = 100;

                      resolve(data);

           });

  }

   getData().then(function(resolvedData) {

           console.log(resolvedData);

   }).catch(function(err) {

           console.log(err);

   });

 

<async & await>

장점 - 코드가 꼬리를 물지 않고 가독성이 높아짐. 기존의 비동기 처리 코드 방식으로 사고하지 않아도 됨

async function 함수명() {

           await 비동기_처리_메소드_();

};

async - 예약어

await - 비동기 처리 메소드 앞에 붙임

*비동기 처리 메소드는 반드시 Promise 객체를 반환

예외 처리 - try catch문을 사용

'web개발 > 자바스크립트' 카테고리의 다른 글

변수  (0) 2021.11.27
npm vs yarn  (0) 2021.11.22
nodeJS + express  (0) 2021.08.17
nodeJS  (0) 2021.06.04
javascript basic  (0) 2021.05.17

<<변수>>

js managed language이기 때문에 개발자가 직접 메모리를 제어하지 못한다.

변수명은 변수의 값이 아닌 메모리 주소를 기억, js engine이 변수명과 매핑된 메모리 주소를 찾아가 저장된 값을 반환

할당 : 변수에 값을 저장하는 것

참조 : 변수에 저장된 값을 읽어들이는 것

선언 : 변수명을 자바스크립트 엔진에 알리는 것

* 변수 선언은 선언 -> 초기화를 거쳐 수행

           선언 : 변수명을 등록하여 자바스크립트 엔진에 변수의 존재를 알림

           초기화 : 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화

 

<var>

var은 변수선언단계와 초기화단계가 동시에 진행되어 undefined를 할당해 초기화

여기서 console.log(변수명)을 먼저해도 undefined가 찍히는데 그 이유는 호이스팅이다.

* 호이스팅(hoisting)

           자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기 앞서, 변수 선언을 포함한 모든 선언문(ex. 변수 선언문, 함수 선언문 등)을 찾아내 먼저 실행함.

           변수선언이 어디에 있든 상관없이 다른 코드보다 먼저 실행되는 특징을 hoisting이라 함.

변수 선언과 할당은 하나의 문으로 단축 표현할 수 있지만 두 개의 실행 시점이 다름.

변수 선언이 호이스팅 되어 먼저 실행되고 값의 할당은 소스코드가 순차적으로 실행되는 런타임에 실행.

 

<함수 호이스팅>

함수 선언 방식

1. 함수 선언문

 - 런타임 이전에 자바스크립트 엔진에서 먼저 실행되어, 함수 자체를 호이스팅 시킬 수 있음.

           function.add(x, y){

           return x + y }

 

2. 함수 표현식(함수 이름 생략)

 - 런타임 이전에 undefined로 초기화만 시키고 런타임에서 함수 표현식이 할당됨

           var add = function(x, y){

           return x + y }

 

3. Function 생성자 함수

           var add = new Function('x', 'y', 'return x+ y')

 

4. 화살표 함수

           var add = (x, y) => x + y

 

<스코프(scope)>: 식별자(변수명, 함수명, 클래스명..)의 유효범위

선언된 위치에 따라 스코프가 달라짐.

           전역에 선언된 변수는 전역 스코프를, 지역에 선언된 변수는 지역 스코프를 가짐

자바스크립트에서 모든 코드 블록(if, for, while, try/catch문 등)이 지역 스코프를 만들며, 이러한 특성을 블록 레벨 스코프라 함.

하지만 var로 선언된 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정. 이를 함수 레벨 스코프라고 함.

         var a = 1

         if (true) { var a = 5 }

         console.log(a)

         >> 5

         // 함수가 아닌 곳에 var 키워드를 이용해 a를 선언했기 때문에 전역 변수로 취급

* 주의 : 모든 곳에서 전역스코프를 공유하기 때문에 동일한 변수명이 예상치 못한 결과를 가져올 수 있다는 위험때문에 블록 레벨 스코프를 지원하는 const let을 사용권장.

 

<var, let, const의 차이>

var의 문제점

1. 변수 중복 선언이 가능하며, 예기치 못한 값을 반환할 수 있음.

2. 함수 레벨 스코프로 인해 함수 외부에서 선언된 변수는 모두 전역 변수로 됨

3. 변수 선언문 이전에 변수를 참조하면 언제나 undefined를 반환

 

let const로 문제해결

1. 변수 중복 선언 불가

           let 키워드로 변수 중복 선언(재선언)이 불가하지만 재할당은 가능

           const let과 달리 반드시 선언과 초기화를 동시에 진행, 재할당 불가

                      const name = 'jhj'

2. 블록 레벨 스코프

           let, const 키워드로 선언한 변수는 모두 코드 블록(함수, if, while, try/catch문 등)을 지역 스코프로 인정하는 블록 레벨 스코프를 따름

                      let a = 1

                      if (true) { let a = 5 }

                      console.log(a)

                      >> 1

3. 변수 호이스팅

           let 키워드로 선언한 변수는 선언단계와 초기화단계가 분리되어 진행

                      , 런타임 이전에 자바스크립트 엔진에 의해 선언 단계가 먼저 실행되긴 하지만 초기화단계가 실행되지 않았을 때 해당변수에 접근하려 하면 참조 에러가 뜸.

           const 키워드는 선언단계와 초기화단계가 동시에 진행됨

 

즉 var보다는 const, let으로 변수를 선언하는 것을 권장하고 바뀌지 않는 변수는 const로 선언하는 것이 바람직하다.

 

출처 : https://www.howdy-mj.me/javascript/var-let-const/

'web개발 > 자바스크립트' 카테고리의 다른 글

비동기  (0) 2021.11.28
npm vs yarn  (0) 2021.11.22
nodeJS + express  (0) 2021.08.17
nodeJS  (0) 2021.06.04
javascript basic  (0) 2021.05.17

<<npm>> : (node package manager) 

정의 : 자바스크립트 언어를 위한 패키지 매니저로 nodjs의 기본패키지 관리자.

<명령어>

npm init : package.json 생성

npm install : package.json 파일 및 해당 종속성에 나열된 모든 모듈을 설치

npm install [packagename] @[버전] : 특정 패키지의 특정 버전 설치

npm uninstall : 패키지 삭제

npm update : 설치한 패키지 업데이트

npm dedupe : 중복 설치된 패키지들을 정리

 

<package.json>

프로젝트 정보와 의존성을 관리하는 문서

어떤 패키지를 사용하는지, 어떤 버전을 사용하는지 등을 기록함으로써 어느곳에서도 동일한 개발환경을 구축할 수 있게 해줌

 

<<yarn>>

정의 : 페이스북에서 만든 자바스크립트 패키지 매니저

장점 : npm에 비해 빠르고 안정성과 보안성이 높다.

다운받은 패키지 데이터를 캐시에 저장하여, 중복된 데이터는 다운로드하지않고, 캐시에 저장된 파일을 활용함으로써 이론적으로 npm에 비해 패키지 설치속도가 빠름. 또한 여러개의 패키지를 설치할 때 병렬로 처리하기 때문에 performance와 speed가 증가.

*yarn.lock은 모든 디바이스에 같은 패키지를 설치하는 것을 보장하기 때문에 버전의 차이로 인해 생기는 버그를 방지해줄 수 있음

 

<명령어>

yarn init : package.json 생성

yarn install : package.json의 해당 종속성에 나열된 모든 모듈 설치

yarn add [packagename] @[version] : 특정 패키지의 특정 버전 설치

yarn remove : 패키지 삭제

yarn upgrade : 패키지 업데이트

 

출처: https://velog.io/@kysung95/%EA%B0%9C%EB%B0%9C%EC%83%81%EC%8B%9D-npm%EA%B3%BC-yarn

'web개발 > 자바스크립트' 카테고리의 다른 글

비동기  (0) 2021.11.28
변수  (0) 2021.11.27
nodeJS + express  (0) 2021.08.17
nodeJS  (0) 2021.06.04
javascript basic  (0) 2021.05.17

<<nodeJS>>

크롬 V8 자바스크립트 엔진으로 빌드 된 자바스크립트 런타임

    브라우저 밖에서 돌아가는 자바스크립트

    Ryan은 자바스크립트를 브라우저에서 분리하여 nodeJS를 만듦

    *런타임(runtime) : 프로그램이 실행되고 있을 때 존재하는 곳, 프로그래밍 언어가 구동되는 환경

    (Javascipt web browser에서 작동하는 JavaScript가 있고 Node.js에서 구동되는 JavaScript가 있다)

 

 

<<npm>>

자바스크립트 언어를 위한 패키지 매니저

nodeJS와 상호작용을 할 수 있게 해줌 (yarn과 같은 기능)

대부분 npm 명령어 사용 아주 가끔 node 명령어

유명한 사람들이 만든 패키지들을 다운받고 사용할 수 있음.

ex) express 패키지 - 한달에 7000만명 다운로드

    npm 덕분에 npm install express로 사용가능

 

<<json>>

프로그래머가 파일에 정보를 저장하기 위해 만든 방식 중 하나

파일에 정보를 입력하는 방식, { key : value }

nodeJS인 경우 파일이름 = package.json이어야만 함.

 

<<start>>

폴더생성 - git init - git repository - git remote add - npm init

 

<<package.json>>

<scripts>

"scripts": {

    "start": "node index.js"

}

Tml > npm run start

    -> node index.js가 실행됨

나중에는 서버를 시작하는 script, CSS를 압축하는 script, 웹사이트를 빌드하고 서버에 배포하는 script등을 만듦

*package.json이 있는 폴더 내에서 terminal명령어 실행시켜야 함.

*babel - "dev": babel-node index.js -> babelnode index.js 실행

    ex) const express = require("express"); -> import express from "express";

        Tml > npm run dev

        -> 뭔가 바뀌면 항상 저장하고 계속 실행시켜줘야함 -> nodemon사용

*nodemon - 파일이 수정되는 걸 감시해주는 패키지, 수정되면 알아서 재시작

            "nodemon --exec babel-node index.js"

            index.js를 수정하고 저장하면 알아서 서버를 재시작

 

<<npm>>

<npm install> (npm 웹사이트에 있는 그대로 복사 붙여넣기!)

Tml > npm i(nstall) express

package-lock.json파일과 node_modules폴더 자동 생성됨

package-lock.json - 패키지들을 안전하게 관리

node_modules - npm으로 설치한 모든 패키지가 저장되어 있음

    <express>

    node_modules > express > lib > package.json

        "dependencies" : {}- express가 작동되려면 필요한 패키지들

            npm install express시 같이 다운받아짐

npm package.json dependencies를 보고 그 안에 있는 모듈들을 알아서 설치함

-> package.json이 중요한 이유!

<dependencies>

    프로젝트를 실행하기 위해 필요(가솔린)

<devDependencies>

    개발자에게 필요한 dependencies(운전을 잘하기 위한 음악)

 

<<babel>>

babel - JavaScript compiler, 작성한 최신 자바스크립트를 컴파일

nodeJS가 이해하지못하는 최신 JavaScript가 있음

    선택지 1. nodeJS가 이해하는 자바스크립트만 사용

    선택지 2. babel을 사용!

babel이 알아서 babel.config.json이라는 파일의 내용을 들여다 봄

 

<preset> - babel을 위한 거대한 플러그인

    preset-env : smart preset, 최신 자바스크립트 구문 사용가능

 

<express>

정의 :웹 및 모바일 애플리케이션을 위한 일련의 강력한 기능을 제공하는 간결하고 유연한 Node.js 프레임워크

사용 :import express from "express"; node_modules express에서 가져옴

        const app = express(); express application(server)생성

 

<server>

    항상 켜져있는 컴퓨터 같은 것, 인터넷에 연결 돼 있음

    request를 항상 listening.

        callback : 서버가 시작될 때 작동하는 함수

        callback전에 어떤 port listening할지 얘기해 줘야 함

    보통 서버를 시작했다면 localhost:portNum를 통해서 접속할 수 있음

 

<Cannot GET />

    / : 서버의 root, 혹은 첫 페이지(home)

    GET : HTTP method, 페이지 갖다줘, request중 하나

        *http: 우리 혹은 서버가 서버와 소통하는 방법

        *http request : 웹사이트에 접속하고 서버에 정보를 보내는 방법

        *request : 유저가 뭔가를 요청하거나, 보내거나, 네게 무슨 행동을 하는 것

 

app.get("/", callback) : 누군가 root page(/) get request를 보낸다면 서버는 callback함수를 작동

                        'cannot GET /' error 해결

*사용자가 /login page같은 page를 원할 때 브라우저가 get request를 보냄

 

<handleHome>

const handleHome = (req, res) => console.log("asdf");

req res express로 부터 받은 것 따라서 get request를 받으면 express

handleHome({request받은 것}, {respond할 것})을 넣어줌

 

<request>

브라우저가 보내는 요청

request object는 파일, search query, username, password를 포함 할 때도 있다

 

<response>

request를 받으면 response return해야 함

res.end(); response 종료

res.send("");로 페이지에 "" print ""안에는 html,json도 포함가능

 

<middleware>

request response사이에 존재, 모든  middleware handler

handler = controller

controller req, res말고 next라는 argument를 가지고 있다.

middleware next();를 포함하는 controller

 

<next();> - 다음 함수를 호출

 

<app.use(globalMiddleware);> : global middleware를 생성

모든 route에서 이 globalMiddleware를 가짐

* express는 위에서 아래로 순서대로 실행하기 때문에 순서 중요

ex) privateMiddleware

const privateMiddleware = (req, res, next) => {

    const url = req.url;

    if(url === "/protected"){

        return res.send("<h1>Not Allowed</h1>");

    }

    console.log("Allowed, you may continue.");

    next();

};

 

<Setup Recap>

package.json = node.js  관련정보를 넣은 text

    npm이 어떤 행동을 할 수 있게 해주는 것들이 있음

        "scripts": { "something": "" } - Tml : npm run something(aliasing)

    "dependecies": { "express": "^4.17.1"} - node_modules에 자동으로 추가

    "devDependencies": { } - node_modules로 가는 것 동일, 차이점 : 개발자가 개발할 때 필요한 것들

        ex) nodemon - 파일을 보고 있다가 변화가 생기면 command를 재시작

        ex) @babel - server.js node가 아닌 babel-node로 돌림 -> 최신 언어 사용가능

                babel.config.json파일을 만들어 babel에 추가하고싶은 plugin(preset)을 추가

 

<Server Recap>

Server : 항상 켜져있고 인터넷에 연결 돼 있으면서 request listening하고 있는 컴퓨터

request : 우리가 서버에 요청하는 것(브라우저를 통해 웹사이트와 상호작용하는 것)

    import express from "node_modules/express";

    const app = express(); express application을 사용할 수 있게 변수로 설정

port : 서버의 창문, request를 보내는 곳

    app.listen(4000, handleListening); : 창문(port)을 여는 곳

4000 port : backend 관습, 거의 비어있음

cannot get / : server가 브라우저의 request listening하고 있는데 대답해 줄 사람이 없음

http method : post, delete, get

    ex) get : 사용자가 요청을 하면 서버가 보내줌 우리가 가는 것이 아님

            express.js에서 하는 방법은 app.get을 사용

            argument : req, res, handdler

 

<Controller Recap>

모든 controller req res가 있다. (express로부터 주어짐, arg 순서 중요)

respond는 여러 method가 있다. ex)res.send(), res.end(), res.cookies(), res.json()

    res.end(); : finish connection

    res.send(); : text,html,json을 보낼 수 있음(화면에 띄울 수 있음)

request도 여러 method ex)req.ip(), req.cookies(), req.secure()

    req.method(); : get, post, put등의 http method 정보를 줌

    req.path(); : url

 

<morgan> : middleware return

기존 middleware보다 정교함, next()를 포함함

    "dev" : method, path, status code, respond time

    "combined" : time, method, http version, status code, browser, os..

    "tiny"

사용 : import logger from "morgan";

    app.use(logger("dev"));

 

// const loggermid = (req, res, next) => {

//     console.log(`METHOD ${req.method} ${req.path}`);

//     next();

// };

// app.use(loggermid);

// const home = (req, res) => {

//     return res.send("hello");

// };

// app.get("/", home);

 

 

<<router>> - 컨트롤러와 URL의 관리를 쉽게 해줌(mini-application)

작업중인 주제를 기반으로 URL을 그룹화함

    글로벌라우터, 유저라우터, 비디오라우터

 

*import 하기전엔 export해야함

    default export로 변수를 export

    import한 변수는 export한 것을 불러왔기 때문에 똑같은 이름으로 안써도 무방

    반드시 하나만 default export할 수 있음

 

*라우터와 컨트롤러를 섞어서 쓰는것은 좋지않음

    컨트롤러는 함수, 라우터는 그것을 이용하는 입장이기 때문

 

*default export하면 이름을 바꿀 수 있었지만

 export const로 하면 실제 이름을 그대로 써야함 (오브젝트를 그대로 들고 옴)

 

 <:id>

 parameter - url안에 변수를 바꿔줄 수 있음

 모든 영상마다 매번 라우터를 만드는 것을 방지

 ex) /videos/123142/edit - express :id 123142를 넣음

 사용 : req.params

 

<정규표현식> - express에선 정규표현식 사용가능

/ab*cd - abasdfsfacd, abrandomcd, abcd

/ab+cd - abbbcd, abbbbbbbbcd

/ab?cd - b가 옵션

/ab(cd)?e - (cd)가 옵션

/(nico\w+)/g - nico로 시작하는 단어들

/(\d+)/g - 숫자만

    *JavaScript \ 두번

 

*템플릿 : 뷰 엔진으로 표시하는 웹페이지

 

<<pug>> - 템플릿 엔진

굉장히 편리함, html에서 <>을 생략가능(깔끔한 html), html에 자바스크립트를 포함가능

<최대장점> : partials를 이용하여 반복할 필요가 없음

<설정방법> : npm install pug -> app.set("view engine", "pug")

    :(Express에게 html helper(view engine) pug를 쓰겠다고 말함)

    views폴더안에 something.pug로 파일생성(express views폴더 안의 view폴더를 봄)

<작성방법>

    모든 건 소문자로 작성, 속성이 있으면 괄호안에 작성

    모든 건 부모속성보다 안쪽에 있어야 함(tab)

        #{Javascript code}으로 변수를 사용하거나 pug에서 자바스크립트를 사용 가능

<적용방법> : (pug에게 파일을 보내면 pug가 렌더링해서 normal html로 변환함)

    : res.render("something") #something view파일

<partials>

    footer example) view/partials/footer.pug 생성 -> footer내용 작성

    -> include partials/footer.pug

<상속>

    html base를 만들 수 있음

    base.pug에 반복되는 html을 넣고 반복할 pug extends base.pug

    override하려면 block을 사용

    block : 내용을 넣을 수 있는 템플릿의 창, 부모 pug block st로 작성

        content block에 무언가 넣으려면 자식 pug block st \n html(st는 서로 이름 같아야 함)

<변수>

    #{variable}로 변수 줄 수 있음

    변수 선언은 rendering 하는 곳에서 res.render("pugfile", {변수})

    =variable으로도 변수를 줄 수 있음

    class, href, id..등은 `${}`을 사용하여야 함

<conditional>

    만약 fakeUser가 들어왔을 때 logout link만 보이도록 하려면?

    if fakeUser.loggedIn, else if fakeUser.loggedIn, else

<iteration>

    만약 array를 가져온다면 변수로 each variable in variables로 쓸 수 있음

        else도 쓸 수 있음

    *mixin : data를 받을 수 있는 partial

        작성: mixin video(mixin가 받을 data)

                반복될 문장들

        적용: include pugfile

            +video(each문의 element)

        어떤 페이지에서도 reuse가능

<ternary operator>

#{video.views == 1 ? "view" : "views" }

 

*&rarr; : 오른쪽 화살표

 

*cwd = current working directory, process.cwd() = return 프로세스 현재 작업 dir

*현재 server process하는 것은 package.json(node.js를 시동), 그렇기때문에 process.cwd package.json이 있는 dir

*app.set("views", process.cwd() + "/directory/views") 로 임의로 views폴더 경로 설정 가능

 

<<MVP style>>

html을 예쁘게 만들어 줌

사용 : (in head)link(rel="stylesheet" href="https://unpkg.com/mvp.css")

 

* ES6 문법

const id = req.params.id;

=> const { id } = req.params;

(array: array)

=> (array)

 

<<Post>> : backend로 보내는 방법

form(method="POST")

cf) get을 사용하는 form

    form(action="/save-changes", method="GET")

    구글에서 뭔가 검색할 때 검색어가 주소창에 포함되어 있음

*videoRouter.get("url", getController), videoRouter.post("url", postController)

=>videoRouter.route("url").get(getController).post(postController)

*express.urlencoded : post controller form body를 이해할 수 있도록 하는 middleware

    app.use(express.urlencoded({ extended: true }));

    express application form value들을 이해할 수 있도록 하고 쓸 수 있는

    자바스크립트 형식으로 변형시켜 줌

 

<<DataBase>>

<mongoDB>

document-based(json-like document) : object로 생각 함

document를 검색할 수 있고, 만들 수 있고, 삭제할 수도 있고, 수정, 업데이트 가능

데이터베이스를 클라우드에 배치하고, 모니터링가능

 

 

<<mongoose>> 자바스크립트에서 mongodb상호작용, nodeJS mongoDB를 이어주는 다리역할

<install>

>>npm i mongoose

db.js import mongoose from "mongoose";

mongoose.connect("url/your database name");

Event)  *mongoose.connection.on("error", function) : 여러번 발생 가능

        *mongoose.connection.once("open", function2) : 단 한번만 실행

<schema>

mongoose에게 데이터가 어떻게 생겼는지 알려줘야 함(model을 만드는 이유)

    shape = schema

    const videoSchema = new mongoose.Schema({

        title: {type: String, required: true},

        createdAt: Date,

    })

    const Video = mongoose.model("Video", videoSchema);

    export default Video; 그리고 server.js에서 import

<database loading>

Video.find({search terms},callback)

    search terms가 비어있으면 모든 형식을 찾는다는 것을 뜻함

data loading된 후에 진행하여야 하므로 기다려야 함.

그 방법에는 callback promise가 있다.

    callback : 무언가 발생하고 난 다음 호출되는 function, err docs라는 signature를 가짐

    promise : const home = async(req,res){ const videos = await Video.find({});}

        error-> try{}catch{}, 장점 : 보다 직관적임

        *await : database를 기다림

<post>

const video = new Video({}) //models에서 Video schema import

or await Video.create({}) - save()안해도 됨

만약 schema에 반하는 형식으로 post된다면 mongoose가 형변환 시키거나 제외시켜버림

video.save() database에 저장, promise가 내장돼있기 때문에 async await로 기다려야함

try{}catch{}문으로 에러검출

 

<CRUD>

Create, Read, Update, Delete

 

<return & render>

함수에서 render가 여러번 있으면 안됨

return : 함수를 종료시켜주는 기능, return + render로 실수 방지 가능

 

<schema>

기능 : uppercase, lowercase, trim(whitespace제거), default, required, minLength

, maxLength(보안차원에서 form에도 설정해야 함)

unique: 중복 x

 

*db에 저장된 데이터를 업데이트 하는 방법

1. 각 데이터의 내용들을 하나하나 바꾸고 save()하는 방법

2. mongoose의 함수를 쓰는 방법(await Video.findByIdAndUpdate(id,{}))

 

*update 이전에 확인 할 것들 - middleware(hooks)

model이 생성되기 전에 만들어야 함

form : videoSchema.pre("save", async function (){})

 

<static>

schema에 대한 함수를 임의로 만들 수 있음

Video import하면 static함수는 import 없이 사용 가능

form : videoSchema.static("formatHashtags", function(){})

 

<mongoDB filter>

find().sort({ createdAt : "desc" }) - 내림차순, "asc" - 오름차순

query에 정규표현식을 포함시킬 수 있음

videos = await Video.find({

    title: {

        $regex: new RegExp(keyword, "i")

    }

})

* i - 대문자, 소문자 구분x

* keyword - keyword를 포함하는 단어

* `^${keyword}` - keyword로 시작하는 단어

* `${keyword}$` - keyword로 끝나는 단어

 

<<User>>

*console창에 DeprecationWarning : 만든지 오래된 기능을 쓰고 있으니 업데이트 요망

 

<hash>

database password가 노출되면 안되기 때문에 hash기능을 사용함

*deterministic function(결정적 함수) : 입력이 같으면 같은 내용을 출력함(hashing)

*bcrypt : rainbow table공격을 막아줌

    설치 : npm i bcrypt

    사용 : bcrypt.hash(password, saltRounds, callback)

    *saltRounds : hash를 반복하는 횟수

   

<$or operator>

{ $or: [ {조건1}, {조건2}, ... {조건n} ] }

    각 조건이 true일 때 실행할 수 있도록 할 수 있음

    ex)

    const usernameExists = await User.exists({

    $or: [{ username: username }, { email }],

    }); - username 또는 email이 존재하면 usernameExists = true

 

*res.status(400).render("",) 으로 브라우저에 상태 코드를 보낼 수 있음

 

<login>

입력한 password를 해쉬한 값으로 비교 해야함(입력값이 같으면 결과가 같으므로)

*compare함수

    bcrypt.compare(password, hash).then(function(result){

    }) 혹은

    async function checkUser(username, password){

        const match = await bcrypt.compare(password, user.passwordHash);

        if(match){ //login }

    }

 

<유저를 기억하는 방법>

유저에게 쿠키를 보냄

*세션 : 백엔드가 자신과 브라우저 간에 어떤 활동을 했는지 기억하는 것( 2주 뒤에 사라짐)

*express-session : express에서 세션을 처리하게 하는 미들웨어

    사이트로 들어오는 모두를 기억하게 됨(로그인하지 않아도)

req.header cookie가 있음

백엔드가 누가 요청했는지 다 기억하고 있음

백엔드가 요청을 보내는 유저한테 id(세션)를 보냄

브라우저의 쿠키 안에 id가 있음

서버가 재시작될 때마다 메모리에 있는 세션이 지워짐(mongoDB로 기억할 수 있음)

 

<백엔드가 쿠키로 브라우저를 구분하는 방법>

백엔드의 메모리에 세션을 저장할 수 있는 DB가 생김

백엔드의 각 세션들은 id를 가지고 있음, id를 브라우저가 요청 보낼 때마다 브라우저에게 보냄

=>어떤 세션이 각 브라우저와 일치하는지 알 수 있음

 

*

세션id를 가지고 있으면 세션 object에 정보 추가 가능

서버가 브라우저한테 세션 id를 주고 브라우저가 요청을 보낼때마다

쿠키에서 세션 id를 가져와 보내줌 그러면 서버가 그 세션 id를 읽고

우리가 누군지 알 수있음

브라우저가 서버의 모든 URL을 방문할 때마다 브라우저가 받았던 id를 요청에 담아 보냄

정리 :

내가 브라우저에서 웹사이트를 방문할 때마다 세션 미들웨어가 있으면

express가 알아서 그 브라우저를 위한 세션 id를 만들고 브라우저에게 보내줌

그러면 브라우저가 쿠키에 그 세션 id를 저장하고

express에서도 그 세션을 세션 DB에 저장함

그러면 브라우저한테 보내서 쿠키에 저장한 세션 id

브라우저가 localhost:4000의 모든 url에 요청을 보낼 때마다

세션 id를 요청과 함께 보냄

그러면 백엔드에서 어떤 유저가 어떤 브라우저에서 요청을 보냈는지 알 수 있음

 

<login>

user controller req.session object에 정보 추가

이 정보를 template과 공유하려면 res.locals

    res locals template가 접근할 수 있음 #{}

    전역변수이기 때문에 모든 template가 사용 가능

localMiddleware session middleware보다 나중에 작성해야 작동

 

<recap login>

express-session : middleware, 브라우저와 backend가 상호작용할 때 마다

브라우저에게 쿠키를 전송

쿠키 : 백엔드가 브라우저에게 주는 정보, 브라우저가 요청을 보낼 때 쿠키를 덧붙여 보냄

    쿠키에는 많은 정보를 넣을 수 있는데 session ID를 넣을 수 있음

session store : 우리가 session을 저장하는 곳, 서버를 재시작할 때마다 초기화

 

<connect-mongo>

session MongoDB에 저장

사용 : import MongoStore from "connect-mongo"

      session({ stroe: MongoStore.create({mongoUrl: "mongodb://127.0.0.1:27017/wetube",}),})

메모리가 아닌 db에 저장되어있으므로 서버가 재시작 되어도 로그인 되어있음

mongoUrl은 배포시 공개하면 안됨

 

<Uninitialized Session>

*모든 사용자에 대해 세션을 만들고 쿠키를 저장하는 것은 좋은 생각이 아님

로그인한 사용자의 세션만 저장하는 게 좋음

saveUninitialized: false : 세션이 새로 만들어지고 수정된 적이 없을 때

    Uninitialized

    세션이 수정되는 곳 : userController req.session.~~

 

<cookie property>

secret : 쿠키에 sign할 때 사용하는 string

    우리 backend가 쿠키를 줬다는 걸 보여주기 위해 sign

Domain : 이 쿠키를 만든 backend가 누구인지 알려줌, 브라우저는 Domain에 따라서

    쿠키를 저장하도록 되어있음

Expires : session cookie 만료 날짜, 적지않으면 session cookie는 사용자가 닫으면 끝남

Max-Age : 언제 쿠키가 만료되는지 알려줌

 

<.env>

환경변수, env 파일에 추가하는 모든 건 대문자로

사용 : process.env.~~

 

<dotenv>

require("dotenv").config();

최대한 먼저 선언(가능한 빨리 env load해야하기 때문)

하지만 require하면 번거롭게 사용하는 모든 파일에 require 해야 함

import "dotenv/config"; 로 바꿔사용

 

<깃허브의 login flow>

1. 사용자를 깃허브로 보냄, 정보를 공유하는 것을 승인

2. 깃허브는 사용자를 token과 함께 우리의 웹페이지로 돌려보냄

3. 그러면 우리가 그 token으로 사용자의 정보를 받아옴, token은 빠르게 만료

 

<1. OAuth>

github.com/settings/applications 앱 만들기

href="https://github.com/login/oauth/authorize?client_id=앱의

 client_id&scope=user:email" parameter를 보내줘야 함

github public data보다 많은 정보를 얻으려면

scope에 전송, 사용자에 대해 어디까지 알 수 있는지 적으면 됨

*scope : docs/github.com/en/developers/apps/scopes-for-auth-apps

    우리가 필요한 것 : user user email

        &scope=read:user user:email

allow_signup : github 계정이 있는 사람만 혹은 x

url을 각각 써주게 되면 번거로우므로 Controller url생성

*URLSearchParams : utility,

    URLSearchParams(config).toString으로 모두 이은 url 생성가능

 

<2. >

authorized 누르면 app authorized url으로 code와 함께 이동

    code 10분 뒤 만료

Github 에서 받은 토큰을 Access 토큰으로 바꿔야 함

    POST https://github.com/login/oauth/access_token

*backend에서 fetch를 쓰는 법 : node-fetch를 설치 후 import

 

<3. >

access_token을 가지고 Github API를 사용해 user의 정보를 알 수 있음

access_token

fetch(https://github.com/login/oauth/access_token?id+secret+code,

 {method:"POST", headers: {Accept:"application/json"}, },}).json으로

구할 수 있음

access_token의 형태

{

    access_token: 'asd_fsafdffdfsfdsfs',

    token_type: 'bearer',

    scope: 'read:user'

}

구한 access_token을 깃헙에 GET으로 보내야 함

깃헙의 user public정보는 await fetch("https://api.github.com/user",

 {headers: {Authorization: `token ${access_token}`,},})).json();으로

 구할 수 있음

 

<로그인규칙>

 *소셜로그인 시 데이터베이스상에 똑같은 email이 있을 때 그것으로 로그인 시켜 줌

 const existingUser = await User.findOne({ email: emailObj.email });

    req.session.loggedIn = true;

    req.session.user = existingUser;

 

<logout>

req.session.destroy();

return res.redirect("/");

 

<github login recap>

startGithubLogin - baseUrl config를 이어 finalUrl을 만든 후 User를 그곳으로 보냄

깃헙 사이트에서 동의하면 우리 웹사이트로 돌아옴(/github/finish라는 Url으로) 그것의 controller

finishGithubLogin - url ?code=xxx가 붙어서 들어옴, baseUrl+config = finalUrl

    모든것이 올바르다면 github는 우리에게 access_token을 줌

    apiUrl/user access_token을 보내면 user데이터를 받을 수 있음

    apiUrl/user/emails access_token을 보내면 useremail데이터를 받을 수 있음

        email들에서 primary이고 verified인 이메일을 찾은 후 로그인

 

<middleware +>

로그인하지 않은 사용자가 edit페이지로 들어왔을 때 protect

로그인한 사용자가 다시 login페이지로 들어왔을 때 protect

로그인한 사용자만 video upload하게 protect

적용 : controller에서 controller부르기 전에 middleware를 삽입

       .route로 만든 controller all(middleware).get().post()

 

<edit profile>

db user의 정보를 업데이트하고 session에서도 업데이트 해야 함

1. 직접 작성

    ...req.session.user : 기존에 req.session.user에 있는 내용을 전달

2. updatedUser를 새로 만들고 new: true를 줌

    const updatedUser = await User.findByIdAndUpdate(_id, {update contents},

     {new: true})

이미 있는 내용으로 바꿀 때 할 수 없다고 말해줘야 함

 

<password 변경>

*href="link" /없이 link를 작성할 경우 상대경로를 사용

    "link" === "/previouslocation/link"

 

github로 로그인했을 때 비밀번호가 없음

1. home으로 redirect

2. 비밀번호가 있어야 변경가능이라고 알림

3. 깃허브로 로그인한 사람들에겐 안보이게

 

pre save middleware password hash해 줌- create save hash

session password또한 update 해야 함

또는 DB에서 가장 최근의 password를 가져오면 session을 건들필요 없음

 

<<upload file>>

<multer> : file을 업로드할 수 있도록 도와줌

설치 : $npm i multer

사용조건 : form multipart form으로 만듬

        form(enctype="multipart/form-data")

        파일을 백엔드로 보내기 위한 encoding type

사용 : 1. middleware 설정

        uploadFiles = multer({ dest: "uploads/"})

        upload한 파일들의 경로를 설정

       2. 경로의 폴더 생성

       3. middleware router에 추가

        .post(uploadFiles.single("avatar"), postEdit);

        *single : file을 하나만 받아옴, avatar = input name

        *multer input으로 avatar 파일을 받아 uploads폴더에 저장한 후 그 파일 정보를 postEdit에 전달

        req.file에 파일이 있음

   

*db에는 절대 file을 저장하면 안됨, 폴더에 파일을 저장후 그 위치만 db에 저장

*static files serving 활성화 : 폴더를 브라우저에게 노출시킴

    app.use("/uploads", express.static("uploads"))

        -"/url"에 폴더 "uploads"를 노출

 

<video upload>

multer file 크기 제한

multer({limits: { fileSize: 10000000,},});

 

*ES6 문법

    const fileUrl = req.file.path;

    => const { path: fileUrl } = req.file;

    === const {path} = req.file;

        const fileUrl = path;

 

<User profile>

1. video owner(id)를 추가,

 owner objectId, video Schema에서 owner를 설정할 때

    type:mongoose.Schema.Types.ObjectId

    ref:"model name" - mongoose에게 owner에 어떤 model objectId를 저장하겠다고 알림

upload video부분에서 owner: req.session.user._id 추가

*populate: 문서의 경로를 다른 컬렉션의 실제 문서로 자동으로 바꾸는 방법

    const owner = await User.findById(video.owner)를 추가로 쓸 필요없이

    const video = await Video.findById(id).populate("owner");

    schema에서 ref="model"한 부분의 내용을 id값에서 실제값으로 채워줌

    video의 모든 값들을 owner에 추가

 

2. user에는 소유한 video(id) list 추가

user가 여러 video를 소유할 수 있으므로 user schema videos array

    videos: [{ type: mongoose.Schema.Types.ObjectId, ref: "Video" }],

upload video부분에서 const user = await User.findById(_id);

                     user.videos.push(newVideo._id);

                     user.save();

user controller에서 .populate("videos");추가 => user videos : {,,,}가 추가됨

*video push되고 save될 때마다 password hash되는 bug발생

    if(this.isModified("password")){}

 

<<frontend>>

<Webpack> : backend babel처럼 브라우저가 이해할 수 있도록 css로 바꿔주는 역할

.scss -> css

cf) Gulp - Webpack의 대체제 중 하나, Webpack만큼 유용친 않음

Webpack을 직접 사용할 일은 거의 없음, react react native등 대부분의 프레임 워크에 내장

<webpack.config.js>

module.exports = {

    entry: "",// src code, 처리하고 싶은 코드

    output: {

        filename: "",

        path: "절대경로", //저장될 경로

    }

}

<rules>

각각의 파일 종류에 따라 어떤 전환을 할 건지 결정

1. js bable

* mode : 개발중에는 코드를 압축하면 안되므로 코드가 완성본인지 아닌지 알려줘야함

    production - 완성본

    development - 진행중

client폴더(webpack 처리 전)를 작업하면 browser assets폴더(webpack 처리 후) 내용을 읽음

하지만 브라우저가 assets폴더의 존재를 모르기 때문에 알려줘야함

 

*app.use("/assets", express.static("assets")) // 전자 : url경로설정, 후자 : 폴더경로

: express한테 사람들이 이 폴더 안에 있는 파일들을 볼 수 있게 하라고 요청하는 것

 

*pug assets폴더 연결

script(src="/asset/js/main.js")

 

2. scss(sassy css) css

세가지의 loader

    1) scss를 일반 css로 변형하는 loader(sass-loader)

    2) 폰트같은걸 불러올 때 css에 굉장히 유용하게 쓰이는 loader(css-loader)

    3) 변환한 css를 웹사이트에 적용할 loader(style-loader)

역순으로 합침

    use:["style-loader", "css-loader", "sass-loader"]

style-loader대신 webpack plugin을 사용  <- js파일에서 css를 넣고 싶지 않기 때문

분리된css파일을 사용하기 위해 MiniCssExtractPlugin!

 

<정리>

client파일이 webpack에 의해 로딩되고 assets폴더에 변환된 js, css파일이

저장되고 base.pug가 그 파일을 읽으면서 브라우저가 이해할 수 있게 됨

*watch: true - run dev assets 매번 할 필요 x

    back-end까지 재시작 됨

        nodemon.json에서 ignore해줌

 

*clean : output folder build(재시작)전 지워 줌

 

**중요! 두가지 콘솔을 이용해야함

    1. backend 2. watch client파일

 

<css작업>

client > scss > components - header, footers..

client > scss > screens - home, search...

 

<<player>>

사전 작업 : webpack entry object로 만들어 video player만의 js

    만들고 둘을 변환하도록 만듬

    output filename이 중복되므로 "[name].js" webpack의 기능을 활용해

    entry의 이름으로 두개의 파일을 만들도록 만듬

    *주석처리

        // : frontend에서도 보임

        //- : 보이지 않음

*input(type="range") eventlistener "input"은 실시간변화, "change"는 마지막변화

 

<loadedmetadeta> (event)

    metadate : video의 움직이는 이미지를 제외한 모든 엑스트라들

 

<timeupdate> : video의 시간이 변화될 때마다 발생

* Math.ceil() : 올림, Math.floor() : 버림

video에서만 timeupdate라는 event사용 가능

 

 

<format time>

new Date(0) - zerotime

    zerotime : 1970 1 1 00 00(영국)

new Date(29*1000).toISOString().substr(from, length)

    우리가 원하는 부분만 추출

 

<fullscreen>

document.fullscreenElement : 풀스크린인 element추출

 

<cursor를 넣으면 contoller>

event - mousemove, mouseleave

*id = setTimeout(function, time) : time밀리초 후 function이 불려짐\

    id setTimeout의 하나뿐인 id

    *clearTimeout(id)로 초기화 가능

 

<cursor멈추면 controller x>

움직일 때 마다 timeout을 설정하고 움직임이 있으면 timeout clear

 

<<API view>> : rendering 하지 않는 view

*요즘 시대에는 백엔드에서 템플릿을 렌더링하지 않음

API : frontend backend가 서버를 통해 통신하는 방법

interactivity: url이 바뀌지 않아도 페이지가 변화하는 것

*url을 바꾸는 것이 백엔드에게 강제로 무언가를 하게 하는 유일한 방법

event backend에 요청 : fetch("id") - id를 얻을 수 없음

<data attribute> : HTML element에 데이터를 저장할 수 있음

    controller1({}) -> pug(dataset) -> controller2(fetch)

        (data-videoId=video._id)

fetch("url", {method:"POST"})

    상태코드를 보내야 함 : res.sendStatus(400)

   

<<Recorder>>

MediaDevices.getUserMedia(constraints) : navigator에서 카메라와 오디오를 가져다 줌

    실행 시 시간이 걸리므로 promise await를 사용해야 함

        *await를 사용하려면 regeneratorRuntime을 설치

    constraint : { audio: true, video: true}

    preview.srcObject = stream;

    *srcObject : video가 가질 수 있는 무언가

<MediaRecorder>

const recorder = new MediaRecorder(stream);

recorder.start();

recorder.stop()을 호출하면 dataavailable event가 발생됨,

    e data property를 받은 BlobEvent

    handler : ondataavailable

<URL.creatObjectURL(event.data)> : 브라우저 메모리에서만 가능한 URL을 만들어 줌

URL은 파일을 가리키고 있음

URL video.src에 저장하고 video.play를 하면 녹화되어 재생됨

*video.loop = true - 반복재생

 

<download>

a.href = videoFile;

a.download - a.href로 가는 것이 아니라 download를 시켜줌

a.click();

 

<<WebAssembly>>

*objectURL : url을 사용해서 파일을 가리키도록 브라우저가 만든 마법의 url

<FFmpeg> : video를 압축하거나 video format을 변환하거나 video에서 audiou를 추출하거나

    video의 스크린샷을 찍는 등 많은 것들을 할 수 있음

    ex) video를 네가지 화질의 버전으로 나누는 것

    백엔드에서 실행해야만 함 - 비쌈 => webassembly를 사용

<webassembly> : 우리가 프론트엔드에서 매우 빠른 코드를 실행할 수 있게 해줌

    - 실행 비용이 큰 프로그램들을 브라우저에서 실행할 수 있음

<ffmpeg.wasm> : 비디오를 변환하기 위해 사용자의 컴퓨터를 사용함(사용자의 브라우저)

    import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";

    const ffmpeg = createFFmpeg({});

    await ffmpeg.load();

        사용자가 다른 소프트웨어를 사용할 것이기 때문에 await

    ffmpeg.FS("writeFile", "filename.webm", binary data function)

        - ffmpeg의 가상의 세계에 파일을 생성, ffmpeg의 파일시스템에 영상의 정보를 작성

    await ffmpeg.run("-i", "filename.webm", "-r", "60", "ouput.mp4")

        -초당 60프레임 mp4 인코딩

    const mp4File = ffmpeg.FS("readFile", "output.mp4"); - output.mp4라는 파일을 읽음

        return 값은 Uint8Array

        *Uint8Array : unsigned integer (양의 정수)

*Blob : binary 정보를 가지고 있는 파일, 만드려면 [binary data]를 줘야 함

binary data에 접근하려면 mp4File.buffer를 사용해야 함

*ArrayBuffer : 영상을 나타내는 bytes의 배열 (mp4File.buffer)  

    const mp4Blob = new Blob([mp4File.buffer], {type: "video/mp4"})

    const mp4Url = URL.createObjectURL(mp4Blob)

<thumbnail>

await ffmpeg.rund("-i", "recording.webm", "-ss", "00:00:01", "-frames:v", "1", "thumbnail.jpg")

    -ss : 영상의 특정시간대로 가게 해줌

    -frames:v : 특정 프레임의 스크린샷을 찍어줌

    const thumbFile = ffmpeg.FS("readFile", thumbnail.jpg")

    const thumbBlob = new Blob([thumbFile.buffer], {tupe: "image/jpg"})

    const thumbUrl = URL.creatObjectURL(thumbBlob)

*unlink - 브라우저 속도가 느려지는걸 방지

    ffmpeg.FS("unlink", "recording.webm")

    ffmpeg.FS("unlink", "output.mp4")

    ffmpeg.FS("unlink", "thumbnail.jpg")

<두 개의 파일 multer upload>

fields([{name: },{name :}])

controller에서 req.files로 변경

 

<<Flash message>>

<express-flash>

설치 : npm i express-flash

app.use(flash()); - session에 연결해서 user에게 메세지를 남김

사용 : req.flash("error", "message");

messages라는 locals를 만들어줌

 

<<comment>>

default behavior를 막는 법 - event.preventDefault();

fetch(`/api/videos/${videoId}/comments`, {

      method: "POST",

      headers: {"Content-Type": "application/json"},

      body: JSON.stringify{text},

  }); - 이런식으로 url변경없이 req.body를 보낼 수 있음

app.use(express.json()); - express에게 json을 보내고 있다는 것을 알려주는 middleware

    fetch로 통해서 보내는 데이터는 JSON이므로 JSON.stringfy해줘야 함

    JS object string으로 바꿔서 인터넷으로 보낼 수 있도록 했고

    string이 서버에 도착하면 JS object로 바꿔서 req.body.text를 쓸 수 있도록 함

        1. fetch로 백엔드에 요청을 보낼 때에 URL과 더불어 이 세 가지를 덧붙여야 한다.

        method: "POST",

        headers: {},

        body: {},

        2. headers에는 이 요청의 세부 사항을 명시하며, body에는 실질적인 컨텐츠가 포함된다.

        3. 따로 명시하지 않을 시에 모든 body의 컨텐츠는 Text File로서 전송되고 받아 인식된다.

        4. 특히 body: { ... }, 이런 식으로 자바스크립트 오브젝트를 넘겨줄 시 외부에서 이 오브젝트는 [object Object]라는 의미 없는 문자열로 변환된다.

        5. 오브젝트와 그 안의 세부 변수 목록들을 넘겨주고 싶을 시, JSON이라는 규약에 의거한 오브젝트 내의 모든 기록을 텍스트화하여 넘겨주어야 하는데, 이때 JSON.stringify({ ... }) 라는 편리한 자체 표준 함수를 사용하면 된다.

        6. 덧붙여 headers 안에 "Content-Type": "application/json"이라는 명시를 해 주어 전송된 텍스트가 JSON파일임을 백엔드에 인식시켜 준다.

        7. 백엔드에 (이를테면 express를 사용 중이라면) app.use(express.json()); 미들웨어를 추가해주어 자체 내에서 JSON.parse("..."); JSON파일을 다시 자바스크립트 오브젝트로 변환해주는 표준 함수로 요청 body 내의 컨텐츠를 디코딩하는 작업을 한다.

 

comment를 보낼 때 또한 cookie를 전송

*sendStatus() vs status()  

    sendStatus - status code를 보내고 request를 끊어버림

<comment db에 저장후 Video에 연결>

  video.comments.push(comment._id);

  video.save();

  await video.find().populate("comments");

* window.location.reload(); 새로고침 but 부하

    => js fake comment를 추가

* fetch status code를 추출 :

    const response = await fetch();

    const status = response.status;

 

<controller에서 comment id response하기>

return res.json({ newCommentId: comment._id});

const response = await fetch();

const json = await response.json();

 -> $ newCommentId: 123141;

 

 <<build backend>>

 <babel/cli>

 설치 : npm i --save-dev @babel/cli

 사용 : script { "build:server": "babel src -d bulid"},

        -d : build directory

    => bulid 디렉토리에 init.js가 생김

nodemon은 파일을 실행하고 그 파일이 모든걸 실행함

babel src폴더를 빌드, 결과물은 build 폴더에 저장

=>build폴더에 src에 있는것들의 old code들이 있음

script { "start": node build/init.js" }

=>$ npm start로 시작가능(npm 기본 명령어)

    -babel의 도움없이 node.js가 이 코드를 모두 이해가능

<Error fix>   

    *client폴더는 빌드안하게 하는 법

    *build한 코드가 async await를 사용할 수 있도록 하는 법

    *build폴더에 pug파일들이 없음

        이유: views set에서 process.cwd() node를 실행한 위치, backend가 알아서 위치를 찾아감

        같은 이유로 .env파일을 찾아갈 수 있음

 

<<build frontend>>

webpack mode development가 아닌 production로 바꾸고 싶음

    "build:assets": "webpack --mode=production",

    =>모든 코드가 한줄로 압축

development mode에서만 watch하도록

    "dev:assets": "webpack --mode=development -w"

 

<Heroku>

create app

Heroku backend를 업로드하는 방법

1. Heroku Git  

    Heroku는 오직 git history만 본다 - commit을 안하면 Heroku가 볼 수 없음

    - .gitignore에 있는 것들은 볼 수 없다(.env)

    =>Heroku config vars

    Heroku random으로 port번호를 줌(process.env.PORT)

2. Github

*Heroku는 배포를 하면 모든 프로젝트에 대해 새로운 서버를 만듦

    => 기존의 collection 파일들이 없어짐

 

<AWS>

S3 - 실질적인 미디어 저장소

IAM - S3의 권한 부여

 

<mongo DB atlas>

local에서 mongo의 역할

 

<Multer S3> : AWS에 업로드 함

npm i aws-sdk

 

'web개발 > 자바스크립트' 카테고리의 다른 글

비동기  (0) 2021.11.28
변수  (0) 2021.11.27
npm vs yarn  (0) 2021.11.22
nodeJS  (0) 2021.06.04
javascript basic  (0) 2021.05.17

<<nodeJS>>
크롬 V8 자바스크립트 엔진으로 빌드 된 자바스크립트 런타임
    브라우저 밖에서 돌아가는 자바스크립트 
    Ryan은 자바스크립트를 브라우저에서 분리하여 nodeJS를 만듦

<<npm>>
자바스크립트 언어를 위한 패키지 매니저
nodeJS와 상호작용을 할 수 있게 해줌 (yarn과 같은 기능)
대부분 npm 명령어 사용 아주. 가끔 node 명령어
유명한 사람들이 만든 패키지들을 다운받고 사용할 수 있음.
ex) express 패키지 - 한달에 7000만명 다운로드
    npm 덕분에 npm install express로 사용가능

<<json>>
프로그래머가 파일에 정보를 저장하기 위해 만든 방식 중 하나
파일에 정보를 입력하는 방식, { key : value }
nodeJS인 경우 파일이름 = package.json이어야만 함.

<<start>>
폴더생성 - git init - git repository - git remote add - npm init 

<<package.json>>

<scripts>
"scripts": {
    "start": "node index.js"
}
Tml > npm run start
    -> node index.js가 실행됨
나중에는 서버를 시작하는 script, CSS를 압축하는 script, 웹사이트를 빌드하고 서버에 배포하는 script등을 만듦
*package.json이 있는 폴더 내에서 terminal명령어 실행시켜야 함.
*babel - "dev": babel-node index.js -> babelnode로 index.js 실행
    ex) const express = require("express"); -> import express from "express";
        Tml > npm run dev
        -> 뭔가 바뀌면 항상 저장하고 계속 실행시켜줘야함 -> nodemon사용
*nodemon - 파일이 수정되는 걸 감시해주는 패키지, 수정되면 알아서 재시작
            "nodemon --exec babel-node index.js"
            index.js를 수정하고 저장하면 알아서 서버를 재시작

<<npm>>

<npm install> (npm 웹사이트에 있는 그대로 복사 붙여넣기!)
Tml > npm i(nstall) express
package-lock.json파일과 node_modules폴더 자동 생성됨
package-lock.json - 패키지들을 안전하게 관리
node_modules - npm으로 설치한 모든 패키지가 저장되어 있음
    <express>
    node_modules > express > lib > package.json 
        "dependencies" : {}- express가 작동되려면 필요한 패키지들
            npm install express시 같이 다운받아짐
npm은 package.json의 dependencies를 보고 그 안에 있는 모듈들을 알아서 설치함
-> package.json이 중요한 이유!
<dependencies>
    프로젝트를 실행하기 위해 필요(가솔린)
<devDependencies>
    개발자에게 필요한 dependencies(운전을 잘하기 위한 음악)

<<babel>>
babel - JavaScript compiler, 작성한 최신 자바스크립트를 컴파일
nodeJS가 이해하지못하는 최신 JavaScript가 있음
    선택지 1. nodeJS가 이해하는 자바스크립트만 사용
    선택지 2. babel을 사용!
babel이 알아서 babel.config.json이라는 파일의 내용을 들여다 봄

<preset> - babel을 위한 거대한 플러그인
    preset-env : smart preset, 최신 자바스크립트 구문 사용가능

'web개발 > 자바스크립트' 카테고리의 다른 글

비동기  (0) 2021.11.28
변수  (0) 2021.11.27
npm vs yarn  (0) 2021.11.22
nodeJS + express  (0) 2021.08.17
javascript basic  (0) 2021.05.17

<<1. Theory>>
HTML에서의 삽입 위치 : body의 가장 마지막
    <script src="script.js"></script>

* allert(something)
* console.log(something) : console에 print해줌
* camel case 작성법 : 소문자로 시작후 space대신 대문자로 시작

한 줄 : expression
    끝 : ;
변수의 사용방법
    Create -> Initioalize -> Use
    생성과 초기화를 동시에 할 수 있음
변수 생성
    let a; : 일반적인 변수 생성
    const a = n; : 상수 선언, 바꿀 수 없음
    var a;
*주석처리
    //do not read this
    /*it's also work */
변수의 종류
    String
        const what = "Something";
    Boolean
        const wat = true;
    Float
        const num = 55.1;
data 정렬
    Array
        const daysOfWeek = ["Mon", "Tue", True, 40];
    
    Object
        const Info = {Name:"name", 
        age:32,
        gender:"LALALAL",
        favMovies: ["Allong the gods", "HarryPoter"]
        favFood: [{name:"kimchi", fatty:false}]} //선언, 초기화

*console.log(Info.gender); //실행

function
    argument(인자)
    function func_name(arg1, arg2){
        console.log("Hello!", arg1, "world!", arg2, "\n")
    }
    func_name(1,'a');

    ``:백틱 - ${인자}로 변수대입 가능
    '':싱글 - string
    "":더블 - string

    function func_name(arg1, arg2){
        return `Hello! ${arg1} world! ${arg2} \n`
    }
    console.log(func_name(1,'a'));
        
    const calculator = {
        plus: function(a,b){
            return a+b
        }
    }
    console.log(calculator.plus(5,5))

    브라우저에서 제공하는 함수
        javascript에서 id를 불러오려면
            *DOM(Document Object Model)객체로 !
                javascript는 html에 있는 모든 요소를 object로 바꿔준다
            const title = document.getElementById("id");
            title.innerHTML = "Hi! From JS";
                원래 HTML의 요소를 바꿨음
            console.dir(title); - title이 가진것들 콘솔에 나열(자바스크립트 객체 표기법)
            title.style.color = "red"
            const title1 = document.querySelector("#id"); - 노드의 첫 번째 자식반환
event
    function handleResize(event){
        console.log(event);
        console.log("I have been resized");
    }

    window.addEventListener("resize", handleResize)
    *함수뒤에() : 함수를 지금 즉시 호출
    **함수뒤에()없음 : 함수호출

    const title = document.getElementById("id");
    function mouseclick(){
        title.style.color = "blue"
    }
    title.addEventListener("click", mouseclick);

*prompt - 매우 오래된 자바스크립트 함수로 무언가 입력할 수 있도록 해줌

if(condition){
    block
}
else if{
    block
}
else {
    block
}

* === 는 조건을 확인하는 용도
** && : and
*** || : or
**** !== : 같지않다

    if else로 click과 default 나눠 색깔 정해주기
        1. css를 바꿔주는 방법 js_try.js참고
        2. 클래스를 추가해주는 방법
            단점: 이전의 클래스가 사라져버림(replace)
            =>클래스리스트 사용 
                title.classname(CLICKED_CLASS)->
                title.classList.add(CLICKED_CLASS)
                title.classList.remove(CLICKED_CLASS)
                title.classList.contains(CLICKED_CLASS)
                    =>title.classList.toggle(CLICKED_CLASS)

 

 

javascript function

const date = new Date(); - 현재시각으로 변수 선언

setInterval(function, time); - 함수를 실행 하고 싶은 시간간격동안 함수를 반복 실행

 

local storage - 작은 자바스크립트 정보들을 브라우저에 저장

'web개발 > 자바스크립트' 카테고리의 다른 글

비동기  (0) 2021.11.28
변수  (0) 2021.11.27
npm vs yarn  (0) 2021.11.22
nodeJS + express  (0) 2021.08.17
nodeJS  (0) 2021.06.04

+ Recent posts