컴퓨터/nodejs

Node.js 백엔드맛보기1

풍경소리^^ 2022. 1. 11. 18:22

https://www.youtube.com/playlist?list=PLSK4WsJ8JS4cQ-niGNum4bkK_THHOizTs 

 

[Node.js] 백엔드 맛보기

 

www.youtube.com

03[Node.js] 백엔드 맛보기 | express로 서버 띄워보기

app.js----------------------

const express = require("express");
const app = express();
app.listen(3000, () => {
    console.log("서버 가동");
});

====================

node app.js

Error: Cannot find module 'express'

 

node_modules 폴더 안에 express 모듈 설치하기

npm install express -s

 

node app.js

서버 가동

 

192.168.1.65:3000

Cannot GET /

서버에 들어오기는 했는데 / 루트경로를 찾을 수 없다는 뜻

서버에서 / 루트경로 만들어주면 된다.

app.js----------------------

const express = require("express");
const app = express();
app.get("/",(req,res)=>{
    res.send("여기는 루트 입니다.");
});
app.listen(3000, () => {
    console.log("서버 가동");
});

====================

실행 중인 프로세스(서버) 종료

ctrl + c

node app.js

서버 가동

 

192.168.1.65:3000

여기는 루트 입니다.

app.js----------------------

const express = require("express");
const app = express();
app.get("/",(req,res)=>{
    res.send("여기는 루트 입니다.");
});
app.get("/login",(req,res)=>{
    res.send("여기는 로그인 화면 입니다.");
});
app.listen(3000, () => {
    console.log("서버 가동");
});

====================

실행 중인 프로세스(서버) 종료

ctrl + c

node app.js

서버 가동

 

192.168.1.65:3000/login

여기는 로그인 화면 입니다.

 

ctrl + / 주석처리

 

04[Node.js] 백엔드 맛보기 | http로 서버 띄워보기

express 서버 프레임워크를 사용하지않고 하면 어렵다는 걸 느껴보자

app.js----------------------

const http = require("http");
const app = http.createServer((req,res)=>{
    console.log(req.url);
});
app.listen(3000, () => {
    console.log("http로 가동된 서버 입니다.");
});

====================

http는 내장모듈이어서 따로 다운 받을 필요 없다

 

실행 중인 프로세스(서버) 종료

ctrl + c

node app.js

 

192.168.1.65:3000/

http로 가동된 서버 입니다.

/

 

192.168.1.65:3000/login

http로 가동된 서버 입니다.

/login

app.js----------------------

const http = require("http");
const app = http.createServer((req,res)=>{
    if (req.url === '/'){
        res.end("여기는 루트 입니다.");
    } else if (req.url === '/login'){
        res.end("여기는 로그인 화면 입니다.");
    };
});
app.listen(3000, () => {
    console.log("http로 가동된 서버 입니다.");
});

====================

실행 중인 프로세스(서버) 종료

ctrl + c

node app.js

 

192.168.1.65:3000/

http로 가동된 서버 입니다.

한글 깨져서 나옴

app.js----------------------

const http = require("http");
const app = http.createServer((req,res)=>{
    res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"});
    if (req.url === '/'){
        res.end("여기는 루트 입니다.");
    } else if (req.url === '/login'){
        res.end("여기는 로그인 화면 입니다.");
    };
});
app.listen(3000, () => {
    console.log("http로 가동된 서버 입니다.");
});

====================

실행 중인 프로세스(서버) 종료

ctrl + c

node app.js

 

192.168.1.65:3000/

http로 가동된 서버 입니다.

여기는 루트 입니다.

 

05[Node.js] 백엔드 맛보기 | 로그인 화면 만들기 | 리얼 하드코딩으로

app.js----------------------

const express = require("express");
const app = express();
app.get("/",(req,res)=>{
    res.send(`
    <!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>
        여기는 루트입니다.
    </body>
    </html>
    `);
});
app.get("/login",(req,res)=>{
    res.send(`
    <!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>
        <input type="text" placeholder="아이디"><br>
        <input type="text" placeholder="패스워드"><br>
        <button>전송</button>
    </body>
    </html>
    `);
});
app.listen(3000, () => {
    console.log("서버 가동");
});

====================

안 좋은 코드 개선하자

06[Node.js] 백엔드 맛보기 | 로그인 뷰(view) 최적화 | MVC의 V(view) 분리하기

app.js 에서 화면 view 단에 해당하는 부분을 처리해줄 수 있는 view 엔진을 셋팅해주자

app.js----------------------

"use strict";
// 모듈
const express = require("express");
const app = express();
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.listen(3000, ()=>{
    console.log("서버 가동");
});

====================

app.js에서 login 부분 떼어내어 별도 파일 만들자

views\home\login.ejs----------------------

<!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>
    <input type="text" placeholder="아이디"><br>
    <input type="text" placeholder="패스워드"><br>
    <button>전송</button>
</body>
</html>

====================

app.js에서 / 부분 떼어내어 별도 파일 만들자

views\home\index.ejs----------------------

<!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>
    <h1>여기는 루트 입니다.</h1>
</body>
</html>

====================

 

app.js----------------------

const express = require("express");
const app = express();
// 앱 세팅
app.set("views", "./views"); // views폴더 위치
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.get("/",(req,res)=>{
    res.render("home/index");
});
app.get("/login",(req,res)=>{
    res.render("home/login");
});
app.listen(3000, () => {
    console.log("서버 가동");
});

====================

node app.js

 

192.168.1.65:3000/

서버 가동

Error: Cannot module 'ejs'  찾을 수 없다

 

npm install ejs -s

 

node app.js

서버 가동

 

192.168.1.65:3000

 

여기는 루트 입니다.

 

07[Node.js] 백엔드 맛보기 | 라우팅 분리

app.js----------------------

const express = require("express");
const app = express();
// 앱 세팅
app.set("views", "./views"); // views폴더 위치
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.get("/",(req,res)=>{
    res.render("home/index");
});
app.get("/login",(req,res)=>{
    res.render("home/login");
});
app.listen(3000, () => {
    console.log("서버 가동");
});

====================

라우팅을 보기 쉽도록 만들자

라우팅 관련은 별도 폴더로 관리 routes-home

routes\home\index.js----------------------

"use strict";
const express = require("express");
const router = express.Router(); // 라우터를 사용할려면 express의 Router를 불러와주어야 한다
// app.js 라우팅 부분 잘라오기
// app.get("/",(req,res)=>{
    //     res.render("home/index");
    // });
    // app.get("/login",(req,res)=>{
        //     res.render("home/login");
// });
router.get("/",(req,res)=>{
    res.render("home/index");
});
router.get("/login",(req,res)=>{
    res.render("home/login");
});
module.exports = router; // 외부파일에서 사용할 수 있도록 보내기

====================

app.js 메인 파일에서는 index.js파일이 어디있는지 모른다

두 파일 연결해주자 index.js → app.js

app.js에 routes\home\index.js 위치 셋팅

 

app.js----------------------

"use strict"; //ecma script 준수하겠다
const express = require("express");
const app = express();
// 앱 세팅
app.set("views", "./views"); // views폴더 위치
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
const home = require("./routes/home"); // index.js
app.use("/", home); // use → 미들 웨어를 등록해주는 메서드.
app.listen(3000, () => {
    console.log("서버 가동");
});

====================

use는 미들웨어를 등록해주는 메서드이다

/ 루트 경로로 들어오면 home으로 보내주는데

home 경로를 명시해야 된다

const home = require("./routes/home"); 안에 있는 자바스크립트 파일을 읽어와줘

 

home 을 위로 빼자

포트 명시하자

app.js----------------------

"use strict";
// 모듈
const express = require("express");
const app = express();
const PORT = 3000;
// 라우팅
const home = require("./routers/home"); // index.js
// 앱 세팅
app.set("views", "./views");
app.set("view engine", "ejs");
app.use("/", home); // use → 미들 웨어를 등록해주는 메서드.
app.listen(PORT, () => {
    console.log("서버 가동");
});

====================

08[Node.js] MVC의 C(controller) 컨트롤러 분리하기

router는 도메인(/login)으로 들어왔을 때

클라이언트의 요청을 연결해 주는 부분이다

routes\home\index.js----------------------

"use strict";
const express = require("express");
const router = express.Router();
router.get("/",(req,res)=>{
    res.render("home/index");
});
router.get("/login",(req,res)=>{ // 콜백함수가
    res.render("home/login");    // 기능을 수행하는
});                              // 부분
module.exports = router; // 외부파일에서 사용할 수 있도록 보내기

====================

(req,res)=>{res.render("home/login");} 콜백함수가 라우팅 기능을 수행하는 부분 - 컨터롤러

이 부분을 따로 빼 주자

routes\home\home.ctrl.js----------------------

"use strict";
const ctrlindex = (req,res)=>{
    res.render("home/index");
};
const ctrllogin = (req,res)=>{
    res.render("home/login");
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrlindex,
    ctrllogin,
};

====================

오브젝트 {key:value}으로 되어있는데

key 하나만 넣어주면 key와 같은 값을 넣어준다

{

hellohome:hellohome,

hellologin:hellologin,

}

같은 뜻이다

routers\home\index.js----------------------

"use strict"; //ecma script 준수하겠다
const express = require("express");
const router = express.Router(); // 라우터를 사용할려면 express의 Router를 불러와주어야 한다
const ctrl = require("./home.ctrl");
// app.js 라우팅 부분 잘라오기
// app.get("/",(req,res)=>{
    //     res.render("home/index");
    // });
    // app.get("/login",(req,res)=>{
        //     res.render("home/login");
// });
router.get("/",ctrl.ctrlindex);
router.get("/login",ctrl.ctrllogin);
module.exports = router; // 외부파일에서 사용할 수 있도록 보내기

====================

node app.js

서버 가동

 

192.168.1.65:3000

여기는 루트 입니다.

 

09[Node.js] 백엔드 맛보기 | app.listen() 모듈화 | 최적화에는 끝이 없다!?

app.js----------------------

"use strict";
// 모듈
const express = require("express");
const app = express();
const PORT = 3000;
// 라우팅
const home = require("./routers/home"); // index.js
// 앱 세팅
app.set("views", "./views");
app.set("view engine", "ejs");
app.use("/", home); // use → 미들 웨어를 등록해주는 메서드.
app.listen(PORT, () => {      // 이 부분 잘라내자
    console.log("서버 가동"); // 이 부분 잘라내자
});                           // 이 부분 잘라내자

====================

서버를 띄워주는 코드 분리

bin\www.js----------------------

"use strict";
const app = require("../app");
const PORT = 3000;
app.listen(PORT, () => {
    console.log("서버 가동");
});

====================

이 www.js 파일에서는 app 이라는 부분을 찾을 수 없어서

연결해주자

 

app.js----------------------

"use strict";
// 모듈
const express = require("express");
const app = express();
// 라우팅
const home = require("./routes/home"); // index.js
// 앱 세팅
app.set("views", "./views");
app.set("view engine", "ejs");
app.use("/", home); // use → 미들 웨어를 등록해주는 메서드.
module.exports = app; // 외부로 넘겨 주기

 

====================

서버 실행시키는 코드 분리했으니까

그 폴더에 가서 실행해줘야 된다

node ./bin/www.js

서버가동

 

192.168.1.65:3000

여기는 루트 입니다.

 

10[Node.js] 백엔드 맛보기 | package.json | package-lock.json | node_modules | npm start

서버를 실행시키기 위해서 node ./bin/www.js 를 사용했었는데

간편한 명령어로 바꾸어 보자

package.json 이용해서 만들자

먼저 package.json을 설치를 하자

package.json 만들기 위해서는

npm init

엔터~엔터

            ↓

한번에 npm init 하는 방법

npm init -y

 

npmjs.com 접속하면 패키지 검색할 수 있다 (형식참조)express검색

 

package.json----------------------

~
"scripts": {
    "start": "node ./bin/www.js",
    "test": "echo \"Error: no test specified\" && exit 1"
 },
 ~
 "license":"MIT" 누구나 사용가능

====================

node start

>login-lecture@1.0.0 start

>node ./bin/www.js

 

서버 가동

 

192.168.1.65:3000

여기는 루트 입니다.

 

ctrl + c

일괄 작업을 끝내시겠습니까 (Y/N)? y

 

node_modules 폴더 설명

: 우리가 설치한 package.json-"dependencies"-모듈들이 있는 곳

 

github 에 올릴 때는 node_modules 올리지 않는다

package.json 만 있으면 된다.

 

실험 삼아 node_modules 폴더 지우고

 

npm install

하면

node_modules 폴더가 생성된다

 

그러면 package-lock.json

보다 정확한 패키지들의 버전 허용 표시

~3.1.5 ~세째 자리 위로 허용 3.1.6 3.1.7 ... 허용을 뜻함

^3.1.5 ^둘째 자리 위로 허용, 첫째 자리는 안됨 ... 3.2. 3.3.허용 4.1허용안됨

 

11[Node.js] 백엔드 맛보기 | 깃과 깃허브에 노드 프로젝트 업로드 | 주의할 점

github.com

 

저장소 만들기

방법1

왼쪽에 있는

Repositories

New

 

방법2

오른쪽에 있는

자기 프로필 눌러서

Your repositories

New

Owner/login-lecture

Creating repository

 

vs code 터미널에서

ls

git init

ls

하면 .git 폴더가 생성 되어서 보인다

 

nano README.md

# login-lecture

백엔드 맛보기 강의

 

^X

Y

엔터

 

모든 파일을 한 번에 add 해주자

먼저 git에 업로드하면 안되는 파일이나 폴더 지정

nano .gitignore

/node_modules

 

^X

Y

엔터

 

ls

git status

 

Untracked files:

깃허브에 업로드될 파일들

 

올리는 과정

git add 스테이징 에리어에 올라감

git commit 저장소 .git 폴더에 변경내용 저장

git push 깃허브 원격저장소에 올린다

 

clear

git add .

git status

git commit -m "깃 저장소 초기화"

git status

nothing to commit, working tree clean

 

리모터 설정하기

git remote -v

git remote add origin https://github.com/jeongyongman/nodejs-backend.git

 

git remote -v

origin  https://github.com/jeongyongman/nodejs-backend.git (fetch)
origin  https://github.com/jeongyongman/nodejs-backend.git (push)

 

원격으로 push

git push origin master

 

깃허브 주소에서 오른쪽에 Code 클릭 복사

 

cd .. 상위 폴더로 이동

git clone https://github.com/jeongyongman/nodejs-backend.git login-lecture2

 

ls

login-lecture login-lecture2

폴더이동 

cd login-lecture2

 

ls

code .

클론한 login-lecture2 가 나온다

node_modules가 없다

만들어주자

ctrl + ` 터미널 창 보기

npm install 또는 npm i

 

npm start

ctrl + c

y

 

클론한 login-lecture2 닫고

cd ..

cd login-lecture

폴더들을 개발하기 쉽도록 정리해보자

src 폴더 만들어주고

/bin

/node_modules

/routes

/views/home

app.js

package-lock.json

package.json

안에 넣기

폴더 구성 바뀜

 

깃허브 login-lecture 선택해서 들어가면

라이센스 생성

Insights 탭 클릭

Community Standards  클릭

License

Add

MIT License

Review and submit

Commit directly to the master branch.

Commit new file

 

깃허브의 내용을 수정했으니까

깃허브의 내용을 로컬로 당기자

git pull origin master

 

실수@@@@@@@@@@@@@@@@@@@@@@@여기 실행하지 말 것

원격 깃허브에서 당겨온 내용 git 에 기록

git add .

git status 스테이지에 올리기

문제점 node_modules는 업로드 안해야 되는데 다들어갔다

 

git reset HEAD . 언스테이지

git status

실수@@@@@@@@@@@@@@@@@@@@@@@여기 실행하지 말 것

 

.gitignore 에서 /node_modules 명시해줬는데 왜 모두 스테이지에 올라 갔나

.gitignore 편집 

**node_modules

 

git add .

git status

git commit -m "소스코드 src 폴더로 분류"

git push origin master

 

깃허브 원격에 가보면 다 고쳐졌다

원격저장소의 .gitignore들어가면

.gitignore를 node 템플릿으로 바꾸어 주자

.gitignore 클릭

연필 edit this file

오른쪽

Choose .gitignore:None 클릭하여 수정

Node 로 수정

그러면

왼쪽에서 

# Dependency directories

node_modules/ 를 수정

**node_modules/

밑으로 내리면

Commit changes

 

더 예쁘게 보이는 방법

현재 Repository 에서

오른쪽 About 기어박스 클릭

 

Description

백엔드 맛보기 강의

Topics

nodejs es6-javascript

Release 체크해제

Packages 체크해제

Save changes

 

12[Node.js] 백엔드 맛보기 | 폴더 구조 최적화

.gitignore 원격에서 수정한 거 받아오기

git pull origin master

 

src 폴더 .node_modules 어디갔지????????

진짜로 구조를 바꾸어주자

src 폴더 이름을 app 으로 바꾸어 주자

app 안에 src라는 폴더를 만들고

src 폴더에 routes 폴더, views 폴더 넣어주자

 

npm start 하면 에러난다

 

app 폴더 안에 package.json 을 읽어야 하기 때문에

cd app =========================================중요

 

npm start 하면 또 에러

.node_modules 없으니까

npm install

 

npm start 하면 또 에러

라우팅 경로 변경해주어야 된다

app.js 안에

routers 폴더 경로가 src안에 있어야 된다

app>app.js----------------------

"use strict";
// 모듈
const express = require("express");
const app = express();
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// 앱 세팅
app.set("views", "./views");
app.set("view engine", "ejs");
app.use("/", home); // use → 미들 웨어를 등록해주는 메서드.
module.exports = app; // 외부로 넘겨 주기

====================

npm start

 

서버 가동

Error: Failed to lookup view "home/index"

 

views폴더도 src 폴더안 있으니까

app>app.js----------------------

"use strict";
// 모듈
const express = require("express");
const app = express();
const PORT = 3000;
// 라우팅
const home = require("./src/routers/home"); // index.js // routes폴더가 src폴더 안에 있다
// 앱 세팅
app.set("views", "./src/views"); // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs");
app.use("/", home); // use → 미들 웨어를 등록해주는 메서드.
module.exports = app; // 외부로 넘겨 주기

====================

npm start

 

서버 가동

 

정상작동

 

참고  혹시 에러나면-서버가 켜져 있다고 하면

killall -9 node

npm start

 

git status

git add .

git commit -m "폴더 구조 최적화"

git push origin master

 

13[Node.js] 백엔드 맛보기 | 프런트를 위한 JS 만들기 | public 폴더 연결

app>src>js폴더 만들어줌

app>src>js>home폴더 만들어줌

app>src>js>home>login.js----------------------

"use strict";
console.log("hello");

====================

 

app>src>js>home>login.js 파일과 app>src>views>home>login.ejs 파일 연결해주기

app>src>views>home>login.ejs----------------------

<!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">
    <script src="/js/home/login.js"></script>
    <title>Document</title>
</head>
<body>
    <input type="text" placeholder="아이디"><br>
    <input type="text" placeholder="패스워드"><br>
    <button>전송</button>
</body>
</html>

그냥 단순히 script 만 만들어주면 nodejs에서 접근할 수 없다

연결해주는 미들웨어 등록

 

app>app.js 에 정적경로 추가----------------------

"use strict";
// 모듈
const express = require("express");
const app = express();
const PORT = 3000;
// 라우팅
const home = require("./src/routers/home"); // index.js
// 앱 세팅
app.set("views", "./src/views");
app.set("view engine", "ejs");
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use("/", home); // use → 미들 웨어를 등록해주는 메서드.
module.exports = app; // 외부로 넘겨 주기

====================

${__dirname}은 app.js파일이 있는 위치를 반환합니다

해석하면 app/이야기하는 거고

${__dirname}/src/public이라는 것은 app/src/public폴더를 정적경로로 추가해주겠다는 것

 

app/src/public폴더 만들어 주자

app/src/js폴더를 app/src/public폴더에 넣어주자

 

app>src>views>home>login.ejs----------------------

<!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">
    <script src="/js/home/login.js"></script> // 여기 코드 추가
    <title>Document</title>
</head>
<body>
    <input type="text" placeholder="아이디"><br>
    <input type="text" placeholder="패스워드"><br>
    <button>로그인</button>
</body>
</html>

====================

이렇게 하는 순간 app/src/views/home/login.ejs에서 

<script src="/js/home/login.js"></script>

 

여기 /js/는 app/src/public/js/home/login.js으로 연결된다

 

테스트하기 위해서

app>src>public>js>home>login.js----------------------

"use strict";
console.log("hello");

====================

 

cd app =========================================위치 중요

npm start

 

192.168.1.65/login

hello

 

git add .

git commit -m "프런트 단 javascript 파일 만들기"

git push origin master

 

14[Node.js] 백엔드 맛보기 | nodemon으로 서버 띄우기 | 개발 생산성 높이기

글로벌로 깔아주자

npm install nodemon -g

 

nodemon ./bin/www.js 보안에러

git bash 관리자권한으로 실행

 

경로app>상태에서

nodemon ./bin/www.js

 

서버 가동

 

nodemon의 장점 : 서버를 끗다 켰다 안해도 된다

 

app>src>public>js>home>login.js----------------------

"use strict";
console.log("hello");
console.log("bye");

 

명령 실행 번거로우니까

app>package.json----------------------

{
  "name": "login-lecture",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "bin": {
    "login-lecture": "www.js"
  },
  "dependencies": {
    "accepts": "^1.3.7",
    "ansi-styles": "^3.2.1",
    "balanced-match": "^1.0.2",
    "async": "^0.9.2",
    "array-flatten": "^1.1.1",
    "body-parser": "^1.19.1",
    "chalk": "^2.4.2",
    "brace-expansion": "^1.1.11",
    "bytes": "^3.1.1",
    "color-convert": "^1.9.3",
    "concat-map": "^0.0.1",
    "color-name": "^1.1.3",
    "content-type": "^1.0.4",
    "content-disposition": "^0.5.4",
    "debug": "^2.6.9",
    "cookie": "^0.4.1",
    "cookie-signature": "^1.0.6",
    "depd": "^1.1.2",
    "destroy": "^1.0.4",
    "ee-first": "^1.1.1",
    "encodeurl": "^1.0.2",
    "ejs": "^3.1.6",
    "escape-html": "^1.0.3",
    "escape-string-regexp": "^1.0.5",
    "etag": "^1.8.1",
    "express": "^4.17.2",
    "finalhandler": "^1.1.2",
    "filelist": "^1.0.2",
    "forwarded": "^0.2.0",
    "fresh": "^0.5.2",
    "http-errors": "^1.8.1",
    "inherits": "^2.0.4",
    "has-flag": "^3.0.0",
    "iconv-lite": "^0.4.24",
    "merge-descriptors": "^1.0.1",
    "media-typer": "^0.3.0",
    "mime": "^1.6.0",
    "ipaddr.js": "^1.9.1",
    "methods": "^1.1.2",
    "mime-db": "^1.51.0",
    "mime-types": "^2.1.34",
    "minimatch": "^3.0.4",
    "jake": "^10.8.2",
    "negotiator": "^0.6.2",
    "ms": "^2.0.0",
    "parseurl": "^1.3.3",
    "on-finished": "^2.3.0",
    "proxy-addr": "^2.0.7",
    "path-to-regexp": "^0.1.7",
    "raw-body": "^2.4.2",
    "qs": "^6.9.6",
    "safe-buffer": "^5.2.1",
    "range-parser": "^1.2.1",
    "send": "^0.17.2",
    "safer-buffer": "^2.1.2",
    "serve-static": "^1.14.2",
    "setprototypeof": "^1.2.0",
    "statuses": "^1.5.0",
    "supports-color": "^5.5.0",
    "type-is": "^1.6.18",
    "unpipe": "^1.0.0",
    "utils-merge": "^1.0.1",
    "vary": "^1.1.2",
    "toidentifier": "^1.0.1"
  },
  "devDependencies": {},
  "scripts": {
    "start": "nodemon ./bin/www.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

====================

cd app =========================================위치 중요

npm start

서버 가동

 

git add .

git commit -m "nodemon 적용"

git push origin master

 

15[Node.js] 백엔드 맛보기 | DOM으로 HTML 객체 제어하기 | 프런트 기능 구현

cd app =========================================위치 중요

npm start

 

app>src>views>home>login.ejs 와

app>src>public/js/home/login.js 가 연결되어

 

app>src>public/js/home/login.js 이동해서

 

값을 입력하면 javascript에서 제어할 수 있어야 한다.

html에 있는 값을 javascript에서 제어하려면

DOM객체가 필요하다. (Document Object Model 문서 객체 모델- 일종의 인터페이스)

: HTML이나 XML 문서를 프로그래밍 언어가 접근할 수 있는 방법을 제공하여

그들이 문서 구조, 스타일, 내용 등을 변경할 수 있게 돕는다(제어한다)

HTML ↔ DOM ↔ Javascript

document

-html-head-title-text

-body-h1

        -a

 

app>src>views>home>login.ejs ----------------------주의 defer

<!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">
    <script src="/js/home/login.js"></script>
    <title>Document</title>
</head>
<body>
    <input id="id" type="text" placeholder="아이디"><br> // id = "id" 추가
    <input id="psword" type="text" placeholder="패스워드"><br> // id = "psword" 추가
    <button>전송</button>
</body>
</html>

====================

 

app>src>public>js>home>login.js----------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
console.log(id);
console.log("hello");

====================

자동 재부팅

아이디 입력해도 null

이것은 ejs 때문에 안되는 것이다

ejs에서 document querySelector 의 해당 값을 가져오기 전에

console.log(id)가 먼저 실행되어서 그런 것이다

app>src>views>home>login.ejs ----------------------

<!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">
    <script src="/js/home/login.js" defer></script> <!-- defer 추가 -->
    <title>Document</title>
</head>
<body>
    <input id="id" type="text" placeholder="아이디"><br> <!-- * id = "id" 추가 -->
    <input id="psword" type="text" placeholder="패스워드"><br> <!-- id = "psword" 추가 -->
    <button>로그인</button>
</body>
</html>

====================

app>src>public>js>home>login.js----------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login); // 두 번째 인수는 함수이다
function login(){
    console.log("bye");
};

====================

버튼 클릭하면

bye

 

app>src>public>js>home>login.js----------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    console.log(id.value);
};

====================

아이디 입력하고 버튼 클릭하면

아이디 나옴

 

app>src>public>js>home>login.js----------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    console.log(req);
};

====================

아이디,비밀번호 입력하고 버튼 클릭하면

{id: 'newstep', psword: '1234'}

 

git add .

git commit -m "돔을 이용하여 HTML 객체 저장"

git push origin master

 

깃허브에 가보면

8commit 되어 있다

 

16[Node.js] 백엔드 맛보기 | fetch | 프런트에서 서버로 데이터 보내기

우리가

전달 하고자 하는 데이터-req 이고

fetch를 통해서 전달한다

어떤 경로를 통해서 전달할 것인지 정해줘야 한다

서버 개발자가 설계하고

프론트 개발자는 해당 경로를 요청하기 전에

해당 경로에 API가 만들어져 있어야 한다

app>src>routes>home>index.js--------------------

 

====================

오브젝트를 통해서 키값 전달

fetch("/login",{body:JSON.stringify(req)})

json형태로 보내기위해서

req오브젝트를 json형태로 감싼다

참고로 stringify는 오브젝트를 문자열형태로 바꾸어주는 메서드

이것만 console.log로 찍어서 어떻게 나오는지 보자

 

app>src>public>js>home>login.js--------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    console.log(req); // 일반 req 리퀘스트 데이터와
    console.log(JSON.stringify(req)); // JSON 형태로 감싼 req 리퀘스트 데이터 비교해 보자
};

====================

cd app

npm start

 

192.168.1.65:3000/login

newstep

1234

전송

 

콘솔

{id: 'newstep', psword: '1234'}

    id: "newstep"

    psword: "1234"

    [[Prototype]]: Object


{"id":"newstep","psword":"1234"} ---------- JSON은 문자열의 형태로 나온다

이 형식으로 서버에게 JSON의 형태로 전달되는 것이다

 

app>src>public>js>home>login.js--------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
      method: "POST",
      body: JSON.stringify(req),
    });
};

====================

서버에 데이터만 전달하면 안되고

body를 통해서 데이터를 전달할 때는

http 메서드 중에서 POST 메서드로 데이터를 전달해 주어야 한다

 

{Restful:API} 서버가 클라이언트와 통신하기위한 규약

서버로 보낼 때

fetch

JSON 형태로 보낸다는 것도 알려줘야 한다.

headers

"Content-Type":"application/json"

 

app-src-public-js-home-login.js

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
      },
      body: JSON.stringify(req),
    });
};

====================

데이터가 서버로 전달되게 되면

서버에서 이 데이터를 받으려면

/login 이라는 경로

POST 라는 메소드로 데이터를 받을 수 있는 API가 마련이 되어 있어야 한다

 

그런데 서버에는

app>src>routes>home>index.js--------------------

"use strict"; //ecma script 준수하겠다
const express = require("express");
const router = express.Router(); // 라우터를 사용할려면 express의 Router를 불러와주어야 한다
const ctrl = require("./home.ctrl");
// app.js 라우팅 부분 잘라오기
// app.get("/",(req,res)=>{
    //     res.render("home/index");
    // });
    // app.get("/login",(req,res)=>{
        //     res.render("home/login");
// });
router.get("/",ctrl.ctrlindex);
router.get("/login",ctrl.ctrllogin);
module.exports = router; // 외부파일에서 사용할 수 있도록 보내기

====================

/login 이라는 경로는 있는데

router.post("/login", ctrl.ctrllogin);이 없다

이것을 다음 시간에 만들고 이 기능을 구현해 보자

 

git add .

git commit -m "로그인을 요청하는 fetch 생성"

git push origin master

 

다음 시간에 fetch /login method:"POST" 만들어주자

 

17[Node.js] 백엔드 맛보기 | 로그인 API 만들기 in 서버 | 프런트의 요청데이터 파싱 | body-parser

app>src>public>js>home>login.js--------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
      },
      body: JSON.stringify(req),
    });
};

====================

해당 API(fetch부분)가 동작할 수 있도록

실제 서버에서 해당 API를 만들어 주도록 하자

app>src>routes>home>index.js--------------------

"use strict"; //ecma script 준수하겠다
const express = require("express");
const router = express.Router(); // 라우터를 사용할려면 express의 Router를 불러와주어야 한다
const ctrl = require("./home.ctrl");
// app.js 라우팅 부분 잘라오기
// app.get("/",(req,res)=>{
    //     res.render("home/index");
    // });
    // app.get("/login",(req,res)=>{
        //     res.render("home/login");
// });
router.get("/",ctrl.ctrlindex);
router.get("/login",ctrl.ctrllogin); // 아랫줄 post 추가해서 login 중복이 발생
router.post("/login",ctrl.ctrllogin); // post 추가 ← 이 부분
module.exports = router; // 외부파일에서 사용할 수 있도록 보내기

====================

먼저 기존에 get으로 동작하는 /login

router.post 추가하는 바람에

기존의 router.get 이 있는

/login 중복이 발생한다

좀 더 이해하기 쉬운 코드로 변경하자

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const ctrlindex = (req,res)=>{
    res.render("home/index"); // views\home
};
const ctrllogin = (req,res)=>{
        res.render("home/login"); // views\home
    };
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrlindex,
    ctrllogin,
};

====================

ctrlindex와 ctrllogin는 해당 페이지를 렌더링 해주는 함수

이 함수를 ctrloutput이라는 객체로 빼주자

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
}
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
};

====================

ctrloutput 객체를 만들어서

기존 ctrlindex와 ctrllogin 을 넣어주자

키값으로 변경 ctrlindex: ~~ ctrllogin: ~~

오브젝트이니까 세미콜론이 아니라 콤마로 바꾸어주고

외부로 보내줄 때도 ctrloutput 으로 보내줘야 한다

 

index.js에서 ctrloutput 반영해주자

app>src>routes>home>index.js--------------------

"use strict"; //ecma script 준수하겠다
const express = require("express");
const router = express.Router();
const ctrl = require("./home.ctrl");
// app.js 라우팅 부분 잘라오기
// app.get("/",(req,res)=>{
    //     res.render("home/index");
    // });
    // app.get("/login",(req,res)=>{
        //     res.render("home/login");
// });
router.get("/",ctrl.ctrloutput.ctrlindex); // ← 이 부분 ctrloutput
router.get("/login",ctrl.ctrloutput.ctrllogin); // ← 이 부분 ctrloutput
router.post("/login",ctrl.ctrlprocess.ctrllogin); // ctrlprocess로 수정
module.exports = router; // 외부파일에서 사용할 수 있도록 보내기

====================

router.post login프론트엔드가 전달한 데이터를 받아서 로그인 기능을 처리해 주는 것이기 때문에

ctrlprocess라는 오브젝트안에 넣어주고 

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const ctrloutput = {
    ctrlindex : (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin : (req,res)=>{
        res.render("home/login"); // views\home
    },
}
const ctrlprocess = {             // ← 이 부분
    ctrllogin:(req,res)=>{
        console.log(req.body);    // ← 이 부분 받을 수 있는지 테스트
    },
}
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,             // ← 이 부분
};

====================

ctrlprocess 안에 다시 살펴보면

app>src>public>js>home>login.js--------------------

'use strict'; //ecma script 준수하겠다
// 테스트하기위해서
// console.log("hello");
// console.log("bye");
// login 기능 구현 - 프론트 단 기능 구현
// 아이디와 비밀번호 입력 받고
// 로그인 버튼이 눌릴 때 server로 전달이 된다
// 아이디와 패스워드를 javascript로 처리해야 된다
const id = document.querySelector("#id"),
    psword = document.querySelector("#psword"),
    loginBtn = document.querySelector("button");
// console.log(id);
// console.log("hello");
loginBtn.addEventListener("click",login); // 두 번째 인수는 함수이다
function login(){
    // console.log("bye");
    // console.log(id.value);
    const req = {
        id: id.value,
        psword: psword.value,
    };
    // console.log(req); // 일반 req 리퀘스트 데이터와
    // console.log(JSON.stringify(req)); // JSON 형태로 감싼 req 리퀘스트 데이터 비교해 보자
    fetch("/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
        },
        body: JSON.stringify(req),            // ← 이 부분
      });
};

====================

body로 데이터를 전달하니까

home.ctrl.js에서 req를 보려면

req요청에서 body로 접근해야 한다

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const ctrloutput = {
    ctrlindex : (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin : (req,res)=>{
        res.render("home/login"); // views\home
    },
}
const ctrlprocess = {             // ← 이 부분
    ctrllogin:(req,res)=>{
        console.log(req.body);    // ← 이 부분 받을 수 있는지 테스트
    },
}
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,             // ← 이 부분
};

====================

body를 보려면

모듈을 설치해주어야 한다

우선 안되는거 테스트해보자

 

 

프론트엔드에서 body: JSON.stringify(req), 리퀘스트 데이터를 전달했으니까

ctrl파일에서 받을 수 있게

app>src>routes>home>home.ctrl.js 받을 수 있는지만 테스트-테스트 데이터를 한 번 보자

실행

cd app

npm start

서버실행

id, psword 넣고 로그인 클릭해도

undefined

 

해당 bodyparser 모듈을 설치해주자

메인파일인

app.js 에 모듈 설치

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser"); // ← 추가 npm i body-parser -s
const app = express();
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

body-parser모듈 설치

npm i body-parser -s

--save 붙이면 package.json에 dependencies 안에 body-parser라는 모듈을 명시해준다

다시 서버를 켜서

cd app

npm start

서버가동

login 프론트엔드에 id,psword 입력 후 로그인 버튼 해도

undefined

body-parser로 파싱을 했는데도 못가져온다

body-parser를 사용할 때는 별도 미들웨어를 등록해주어야 하는데

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser"); // ← 추가
const app = express();
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home");
// 앱 세팅
app.set("views", "./src/views");
app.set("view engine", "ejs");
app.use(express.static(`${__dirname}/src/public`));
app.use(bodyParser.json());              // ← 이 부분 미들웨어 등록
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

미들웨어 등록해주고

bodyParser가 json데이터를 파싱해 올 수 있도록 명시해주고

URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제

cd app

npm start

 

192.168.1.65:3000/login

newstep

1234

 

서버 가동

{ id: 'newstep', psword: '1234' }

 

다음 시간에는 백엔드에서 로그인 기능을 처리하는 것을 해보자

 

18[Node.js] 백엔드 맛보기 | 로그인 인증 기능 만들기 in 서버 | 유저 데이터 만들기

프론트에서 전달한 body 데이터를 가지고

로그인 기능을 만들어보자

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
}
const ctrlprocess = {
    ctrllogin:(req,res)=>{
        console.log(req.body); // ← 프론트엔드에서 전달한 body 데이터를 가지고 로그인 기능 만들어 보기
    },
}
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

app>src>routes>home>home.ctrl.js 안에 있는 process 에서 응답받은 body

로그인이 가능할려면 

프론트에서 전달한 id 와 pw 값을 서버에서 인증하는 과정이 필요하다

인증을 할려면 해당 데이터를 서버가 가지고 있어야 한다

 

우선 해당 데이터를 콘트롤러 자체에 데이터를 넣어보자

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const output = {
    hello: (req,res)=>{
        res.render("home/index");
    },
    hellologin: (req,res)=>{
        res.render("home/login");
    },
}
const users = {
    id: ["newstep", "miero", "김팀장"], // ← 서버 대신 데이터 가지고 테스트
    psword: ["1234","1234","123456"],
};
const ctrlprocess = {
    ctrllogin:(req,res)=>{
        // console.log(req.body);          // ← 프론트엔터에서 보내준 데이터랑 비교
        const id = req.body.id,
            psword = req.body.psword;
        console.log(id,psword);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    output,
    process,
};

====================

cd app

npm start

 

192.168.1.65:3000/login

newstep

1234 입력하면

 

콘솔에 찍힌다 newstep 1234

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const ctrloutput = {
    hello: (req,res)=>{
        res.render("home/index");
    },
    hellologin: (req,res)=>{
        res.render("home/login");
    },
}
const users = {
    id: ["newstep", "miero", "김팀장"],
    psword: ["1234","1234","123456"],
};
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        if (users.id.includes(id)) {			// id, psword 검증 해주자
            const idx = users.id.indexOf(id);
            if (users.psword[idx] === psword) {
                return res.json({
                    success: true,
                });
            }
        }
        return res.json({
            success: false,
            msg: "로그인에 실패하셨습니다.",
        });
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

id,psword 검증해주자

if users.id에 프론트엔드에서 입력한 id가 있고

users.id 같은 위치에 있는 psword가 프론트엔드에서 입력한 psword와 같으면

res.json 객체로 프론트엔드로 응답해주게 됨

오브젝트로 만들어서 전달

success 키 값으로 true 반환

실패하면 if 문 밖에서 해주자

res.json 객체로 프론트엔드로 응답

오브젝트

success 키 값으로 false 반환

msg 키 값에 "로그인에 실패하셨습니다." 반환

 

app>src>public>js>home>login.js--------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(req),
    }).then((res) => console.log(res.json())); // ← 이 부분 promise
};

====================

cd app

npm start

 

192.168.1.65:3000/login

newstep

1234 입력하면

전송

 

웹-콘솔

Promise 가 나온다

 

res.json()의 반환 값은 Promise다.

기본 res의 반환 값은 Response 스트림인데,

".json()" 메서드를 통해 Response(응답) 스트림을 읽을 수 있다.

 

Response는 데이터가 모두 받아진 상태가 아니다.

".json()"으로 Response 스트림을 가져와 완료될 때까지 읽는다.

다 읽은 body의 텍스트를 Promise 형태로 반환한다.

 

app>src>public>js>home>login.js--------------------

'use strict'; //ecma script 준수하겠다
// 테스트하기위해서
// console.log("hello");
// console.log("bye");
// login 기능 구현 - 프론트 단 기능 구현
// 아이디와 비밀번호 입력 받고
// 로그인 버튼이 눌릴 때 server로 전달이 된다
// 아이디와 패스워드를 javascript로 처리해야 된다
const id = document.querySelector("#id"),
    psword = document.querySelector("#psword"),
    loginBtn = document.querySelector("button");
// console.log(id);
// console.log("hello");
loginBtn.addEventListener("click",login); // 두 번째 인수는 함수이다
function login(){
    // console.log("bye");
    // console.log(id.value);
    const req = {
        id: id.value,
        psword: psword.value,
    };
    // console.log(req); // 일반 req 리퀘스트 데이터와
    // console.log(JSON.stringify(req)); // JSON 형태로 감싼 req 리퀘스트 데이터 비교해 보자
    fetch("/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
        },
        body: JSON.stringify(req),
      })
      .then((res) => console.log(res.json())) // ← 이 부분 잘못됨
      .then((res) => console.log(res));
};

====================

undefined

 

app>src>public>js>home>login.js--------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(req),
    })
    .then((res) => res.json())        // ← 이 부분 수정하고
    .then((res) => console.log(res));
};

====================

cd app

npm start

 

192.168.1.65:3000/login

newstep

1234 입력하면

전송

 

웹-콘솔

{success: true}

 

좀 더 정리할 수 있다

 

app>src>public>js>home>login.js--------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(req),
    })
    .then((res) => res.json())
    .then(console.log);				// ← 이 부분 추가 축약
};

====================

파라미터를 넘기는 값을 어떤 함수 안에 다시 파라미터로 넘기면

파라미터를 생략 할 수 있다

 

cd app

npm start

 

192.168.1.65:3000/login

newstep

1234 입력하면

전송

 

웹-콘솔

{success: true}

 

서버 끄고 ctrl + C

 

git add .

git commit -m "백엔드에서 로그인 기능 구현"

git push origin master

 

다음 시간에 res 데이터를 받아서 success가 true 이면 /루트 화면으로 이동하고

false 이면 alert 경고창을 띄워보는 기능을 구현해보자

19[Node.js] 백엔드 맛보기 | 서버의 응답데이터 처리 in 프런트

서버에서 입력받은 데이터 처리해보자

app>src>public>js>home>login.js--------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(req),
    })
    .then((res) => res.json())
    .then((res) => {				// ← 여기 부분
      if(res.success){
        location.href = "/";		// 이동할 링크
      } else {
        alert(res.msg);				// 서버에서 전달한 메시지
      }
    });
};

====================

app>src>routes>home>home.ctrl.js----------

"use strict";
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
}
const users = {
    id: ["newstep", "miero", "김팀장"], // ← 서버 대신 데이터 가지고 테스트
    psword: ["1234","1234","123456"],
};
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        if (users.id.includes(id)) {			// id, psword 검증 해주자
            const idx = users.id.indexOf(id);
            if (users.psword[idx] === psword) {
                return res.json({
                    success: true,
                });
            }
        }
        return res.json({
            success: false,
            msg: "로그인에 실패하셨습니다.",
        });
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

일부러 로그인에 실패해보면

cd app

rpm start

 

192.168.1.65:3000/login

newstep

12

 

로그인에 실패하셨습니다

newstep

1234

 

여기는 루트 입니다

 

error 잡으려면 catch

app>src>public>js>home>login.js--------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(req),
    })
    .then((res) => res.json())
    .then((res) => {
      if(res.success){
        location.href = "/";
      } else {
        alert(res.msg);
      }
    })
    .catch((err) => {
      console.error(new Error("로그인 중 에러 발생"));
    });
};

====================

cd app

rpm start

 

192.168.1.65:3000/login

newstep

12

 

로그인에 실패하셨습니다

 

에러 어떻게 확인하는지 보려고 다음 라우터 콘트롤을 주석처리하면

app>src>routes>home>index.js--------------------

"use strict";
const express = require("express");
const router = express.Router();
const ctrl = require("./home.ctrl");
router.get("/", ctrl.output.hello);
router.get("/login", ctrl.output.hellologin);
// router.post("/login", ctrl.process.login); ← 일부러 주석처리
module.exports = router; // 외부로 넘겨 주기

====================

cd app

rpm start

 

192.168.1.65:3000/login

ne

12

 

웹-콘솔

POST http://192.168.1.65:3000/login 404 (Not Found)

Error: 로그인 중 에러 발생

 

app>src>routes>home>index.js--------------------

"use strict";
const id = document.querySelector("#id"),
  psword = document.querySelector("#psword"),
  loginBtn = document.querySelector("button");
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(req),
    })
    .then((res) => res.json())
    .then((res) => {
      if(res.success){
        location.href = "/";
      } else {
        alert(res.msg);
      }
    })
    .catch((err) => {
      // console.error(new Error("로그인 중 에러 발생"));
      console.error("로그인 중 에러 발생");
    });
};

====================

app>src>routes>home>index.js--------------------

"use strict";
const express = require("express");
const router = express.Router();
const ctrl = require("./home.ctrl");
router.get("/", ctrl.output.hello);
router.get("/login", ctrl.output.hellologin);
router.post("/login", ctrl.process.login);
module.exports = router; // 외부로 넘겨 주기

====================

ctrl + C

 

git add .

git commit -m "프런트 로그인 기능 구현"

git push origin master

 

다음 시간에는 콘트롤러를 모델로 변경한다

데이터를 콘트롤러가 가지고 있으면 안된다 절대 절대

데이터를 모델로 분리해주고

app>src>routes>home>home.ctrl.js 안에 ctrlprocess 도 분리해주자

20[Node.js] 백엔드 맛보기 | MVC의 모델(M) 만들기 | 객체지향프로그래밍(OOP) | UserStorage 클래스

모델은 2 가지가 있다

1.데이터를 가지고 있는 것

2.데이터를 가지고 있는 것을 조작,제어해주는 것

 

코드정리 - success: true, 

app>src>routes>home>home.ctrl.js--------------------수정 전

"use strict";
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
}
const users = {
    id: ["newstep", "miero", "김팀장"], // ← 서버 대신 데이터 가지고 테스트
    psword: ["1234","1234","123456"],
};
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        if (users.id.includes(id)) {			// id, psword 검증 해주자
            const idx = users.id.indexOf(id);
            if (users.psword[idx] === psword) {
                return res.json({
                    success: true,              // ← 이 부분을 변수로 따로 빼주자
                });
            }
        }
        return res.json({
            success: false,
            msg: "로그인에 실패하셨습니다.",
        });
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

json뒤에 넘어오는 파라미터를 변수로 따로 빼주자

app>src>routes>home>home.ctrl.js--------------------수정 후

"use strict";
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
}
const users = {
    id: ["newstep", "miero", "김팀장"], // ← 서버 대신 데이터 가지고 테스트
    psword: ["1234","1234","123456"],
};
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        const response = {};                    // ← 응답하는 오브젝트 만들어주자
        if (users.id.includes(id)) {
            const idx = users.id.indexOf(id);
            if (users.psword[idx] === psword) {
                response.success = true;        // ← 오브젝트의 key값에 true 주자
                // return res.json({
                    // success: true,              // ← 이 부분을 변수로 따로 빼주자
                // });
                return res.json(response);          // ←
            }
        }
        response.success = false;                       // ← 오브젝트의 key값에 false 주자
        response.msg = "로그인에 실패하셨습니다.";      // ← 오브젝트의 key값에 msg 주자
        // return res.json({
            // success: false,                     // ← 이 부분을 변수로 따로 빼주자
            // msg: "로그인에 실패하셨습니다.",    // ← 이 부분을 변수로 따로 빼주자
        // });
        return res.json(response);                  // ←
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

 

cd app

npm start

잘 동작됨

 

<이제 모델을 만들어주자>

app>src>routes>home>home.ctrl.js 안에 있는 데이터를 모델로 만들어주는 과정

 

app>src>models 폴더만들고

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {					// class명은 파일명과 동일하게 만들어주는게 좋다
    users = {					// app>src>routes>home.ctrl.js에서 가져오기 - 선언자 필요없음
        id: ["newstep", "miero", "김팀장"],	// app>src>routes>home.ctrl.js에서 가져오기
        psword: ["1234","1234","123456"],	// app>src>routes>home.ctrl.js에서 가져오기
    };						// app>src>routes>home.ctrl.js에서 가져오기
}
module.exports = UserStorage;				// class를 외부에서 사용할 수 있게

====================

클래스 안에 변수를 선언할 때는 선언자 필요없음

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const UserStorage = require("../../models/UserStorage");	// ← 최상단 UserStorage 가져와서
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {                         //  app>src>models>UserStorage.js로 별도파일로
//     id: ["newstep", "miero", "김팀장"], // ← 서버 대신 데이터 가지고 테스트
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        const userStorage = new UserStorage();	// ← UserSrorage를 인스턴스화하였으니까
        console.log(userStorage.users);		// ← userSgorage 인스턴스의 users에 접근할 수 있다
        const response = {};                    // ← 응답하는 오브젝트 만들어주자
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;        // ← 오브젝트에 true 주자
        //         return res.json(response);          // ←
        //     }
        // }
        response.success = false;                       // ← 오브젝트에 false 주자
        response.msg = "로그인에 실패하셨습니다.";      // ← 오브젝트에 msg 주자
        return res.json(response);                  // ←
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

여기서 해당 모듈을 불러오면

최상단에서 UserStorage 가져와서

const ctrlprocess 안에서 const userStorage 인스턴스로 가져오면

UserSgorage에 접근할 수 있게 된다

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        // const userStorage = new UserStorage();      // 데이터를 저장하고 있는 UserSgorage를 굳이 인스턴트화 안해도 좋다
        // console.log(userStorage.users);
        console.log(UserStorage.users);
        const response = {};                    // ← 응답하는 오브젝트 만들어주자
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;        // ← 오브젝트에 true 주자
        //         return res.json(response);          // ←
        //     }
        // }
        // response.success = false;                       // ← 오브젝트에 false 주자//임시로 개발하기 편하게 true 해주자
        response.success = true;                       // ← 오브젝트에 false 주자//임시로 true 해주자
        response.msg = "로그인에 실패하셨습니다.";      // ← 오브젝트에 msg 주자
        return res.json(response);                  // ←
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

데이터를 저장하고 있는 스토리지는 굳이 인스턴스화를 시켜주지 않아도 된다

다이렉트로 불러올 수 있게 console.log(UserStorage.users)

 

이렇게 하면

데이터를 가져올 수 없다

undefined

 

클래스에서 다이렉트로 UserStorage.users 바로 불러올려면

 

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static users = {						// static을 붙여줘야 class에서 변수로 접근가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
    };
}
module.exports = UserStorage;

====================

static 정적변수로 만들어줘야 한다★

이렇게 해주면 UserStorage클래스 자체에서

users 이 변수에 접근할 수 있게 된다.

 

저장

지금 또 웹 콘솔에서

로그인 중 에러 발생

 

왜 에러가 발생할까

app>src>public>js>login.js--------------------

'use strict'; //ecma script 준수하겠다
// 테스트하기위해서
// console.log("hello");
// console.log("bye");
// login 기능 구현 - 프론트 단 기능 구현
// 아이디와 비밀번호 입력 받고
// 로그인 버튼이 눌릴 때 server로 전달이 된다
// 아이디와 패스워드를 javascript로 처리해야 된다
const id = document.querySelector("#id"),
    psword = document.querySelector("#psword"),
    loginBtn = document.querySelector("button");
// console.log(id);
// console.log("hello");
loginBtn.addEventListener("click",login); // 두 번째 인수는 함수이다
function login(){
    // console.log("bye");
    // console.log(id.value);
    const req = {
        id: id.value,
        psword: psword.value,
    };
    // console.log(req); // 일반 req 리퀘스트 데이터와
    // console.log(JSON.stringify(req)); // JSON 형태로 감싼 req 리퀘스트 데이터 비교해 보자
    fetch("/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())        // ← 이 부분 수정하고
      .then((res) => {				// ← 여기 부분
        if(res.success){                                   // 개발하기쉽게 임시로 주석처리 20
          location.href = "/";		// 이동할 링크           // 개발하기쉽게 임시로 주석처리 20
        } else {
          alert(res.msg);				// 서버에서 전달한 메시지// 개발하기쉽게 임시로 주석처리 20
        }                                                // 개발하기쉽게 임시로 주석처리 20
      })
      .catch((err) => {
        console.error("로그인 중 에러 발생");
        // console.error(new Error("로그인 중 에러 발생"));
      });
};

====================

.catch((err)=>{console.error("로그인 중 에러 발생")

왜 에러 발생할까

그것은 콘트롤러에서

app>src>routes>home>home.ctrl.js에서 응답해주는게 없어서 그렇다

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {                         //  app>src>models>UserStorage.js로 별도파일로
//     id: ["newstep", "miero", "김팀장"], // ← 서버 대신 데이터 가지고 테스트
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        // const userStorage = new UserStorage();      // 데이터를 저장하고 있는 UserSgorage를 굳이 인스턴트화 안해도 좋다
        // console.log(userStorage.users);
        console.log(UserStorage.users);
        const response = {};                    // ← 응답하는 오브젝트 만들어주자
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;        // ← 오브젝트에 true 주자
        //         return res.json(response);          // ←
        //     }
        // }
        response.success = false;                       // ← 오브젝트에 false 주자
        response.msg = "로그인에 실패하셨습니다.";      // ← 오브젝트에 msg 주자
        return res.json(response);                  // ←
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

로그인에 실패하셨습니다

계속 alert 뜰테니까

임시로 개발하기 편하게 

app>src>public>js>home>login.js--------------------

'use strict'; //ecma script 준수하겠다
// 테스트하기위해서
// console.log("hello");
// console.log("bye");
// login 기능 구현 - 프론트 단 기능 구현
// 아이디와 비밀번호 입력 받고
// 로그인 버튼이 눌릴 때 server로 전달이 된다
// 아이디와 패스워드를 javascript로 처리해야 된다
const id = document.querySelector("#id"),
    psword = document.querySelector("#psword"),
    loginBtn = document.querySelector("button");
// console.log(id);
// console.log("hello");
loginBtn.addEventListener("click",login); // 두 번째 인수는 함수이다
function login(){
    // console.log("bye");
    // console.log(id.value);
    const req = {
        id: id.value,
        psword: psword.value,
    };
    // console.log(req); // 일반 req 리퀘스트 데이터와
    // console.log(JSON.stringify(req)); // JSON 형태로 감싼 req 리퀘스트 데이터 비교해 보자
    fetch("/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())        // ← 이 부분 수정하고
      .then((res) => {				// ← 여기 부분
        // if(res.success){                               // 개발하기쉽게 임시로 주석처리 20
        //   location.href = "/";		// 이동할 링크           // 개발하기쉽게 임시로 주석처리 20
        // } else {
        //   alert(res.msg);				// 서버에서 전달한 메시지// 개발하기쉽게 임시로 주석처리 20
        // }                                            // 개발하기쉽게 임시로 주석처리 20
      })
      .catch((err) => {
        console.error("로그인 중 에러 발생");
        // console.error(new Error("로그인 중 에러 발생"));
      });
};

====================

데이터만 출력된다

 

이제부터 복잡해질 수 있다

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        console.log(UserStorage.users);
        const response = {};                    // ← 응답하는 오브젝트 만들어주자
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;        // ← 오브젝트에 true 주자
        //         return res.json(response);          // ←
        //     }
        // }
        response.success = false;                       // ← 오브젝트에 false 주자//임시로 개발하기 편하게 true 해주자
        response.msg = "로그인에 실패하셨습니다.";      // ← 오브젝트에 msg 주자
        return res.json(response);                  // ←
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

===================

일단

app>src>routes>home>home.ctrl.js의 const ctrlprocess 안에 login 안에 console.log(UserStorage.users)

이렇게 받아올 수 있었던 이유는

app>src>models>UserStorage.js의 UserStoraged 안에 users변수를

static users로 static을 달아줘서 되는 것이다

그것은 #users로 만들어 주면 된다

이렇게 하면 users 변수를 public 변수에서 private 변수로 만들어 준다

이렇게 하면 외부에서 불러올 수 없게 됩니다

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // #users 하면 private변수로 바뀐다
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
    };
}
module.exports = UserStorage;

===================

cd app

npm start

 

undefined

외부에서 받아올 수 있게 해주어야 된다.

getUsers()함수를 만들어서

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
    };
    static getUsers(){
        return this.#users;
    }
};
module.exports = UserStorage;

===================

콘트롤러에서 getUsers메서드 호출해야 된다

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        console.log(UserStorage.getUsers());        // ← static 한 메서드 호출
        const response = {};
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;
        //         return res.json(response);
        //     }
        // }
        response.success = false;
        response.msg = "로그인에 실패하셨습니다.";
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

===================

정상적으로 가져온다

cd app

npm start

로그인 버튼

{
  id: [ 'newstep', 'miero', '김팀장' ],
  psword: [ '1234', '1234', '123456' ]
}

 

1 데이터를 은닉화 시켜주고

2 메서드로 전달해주어야 한다

 

또 하나를 해주려고 한다

이 스토리지 특성상

app>src>models>UserStorage.js에

#users 에는 id,psword만 있는게 아니다

여기에 name 있다고 하면

 

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers() {
        return this.#users;
    }
}
module.exports = UserStorage;

===================

호출하고 싶은 데이터는 id,psword 두 개인데

getUsers메서드를 호출하는 곳에서 정해줄 수 있도록 만들어주자

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {                         //  app>src>models>UserStorage.js로 별도파일로
//     id: ["newstep", "miero", "김팀장"], // ← 서버 대신 데이터 가지고 테스트
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
        // const userStorage = new UserStorage();      // 데이터를 저장하고 있는 UserSgorage를 굳이 인스턴트화 안해도 좋다
        // console.log(userStorage.users);
        console.log(UserStorage.getUsers("id","psword"));        // ← static 한 메서드 호출
        const response = {};                    // ← 응답하는 오브젝트 만들어주자
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;        // ← 오브젝트에 true 주자
        //         return res.json(response);          // ←
        //     }
        // }
        response.success = false;                       // ← 오브젝트에 false 주자
        response.msg = "로그인에 실패하셨습니다.";      // ← 오브젝트에 msg 주자
        return res.json(response);                  // ←
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

===================

id필드와 psword필드만 가져와줘

할려면

app>src>models>UserStorage.js 수정해주자

getUsers()파라미터를 두 개를 받았어요

메서드들을 만들기 위해서

우선 먼저 

app>src>routes>home>home.ctrl.js

몇 개의 변수가 올지 모른다

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...변수명){
        console.log(변수명);
        return this.#users;
    }
};
module.exports = UserStorage;

====================

여기 변수명에 파라미터로 넘긴 데이터들이 배열형태로 오게 된다

npm start

 

192.168.1.65:3000/login

전송 버튼

 

서버 가동
[ 'id', 'psword' ] =====================배열형태
{
  id: [ 'newstep', 'miero', '김팀장' ],
  psword: [ '1234', '1234', '123456' ],
  name: [ '뉴스텝', '미에로', '김팀장' ]
}

 

다시 

app>src>models>UserStorage.js-------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...fields){
        const users = this.#users
        const newUsers = fields.reduce((newUsers, field)=>{
            console.log(newUsers, field);
        }) // 배열의 메서드 순환하면서 하나씩 반환
        return;
    }
};
module.exports = UserStorage;

====================

우선 console로 출력해 보면

npm start

 

192.168.1.65:3000/login

로그인 버튼

 

서버 가동
id psword ←
undefined

 

fields.reduce((newUsers,field)에는 fields라는 배열의 초기값이  들어간다

다음 변수들은 fields.reduce((newUsers, field 여기에 들어온다

초기값을 마음대로 바꿀 수 있다

 

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...fields){
        const users = this.#users
        const newUsers = fields.reduce((newUsers, field)=>{ // newUsers 초기값은 마음대로 지정할 수 있다
            console.log(newUsers, field);
        },{}); // 배열의 메서드 순환하면서 하나씩 반환
        return;
    }
};
module.exports = UserStorage;

====================

빈 오브젝트 {}를 넣으면 빈 오브젝트{} 가 나온다

npm start

 

192.168.1.65:3000/login

전송 버튼

 

서버 가동
{} id
undefined psword
undefined

 

fields.reduce((newUsers, field 여기에 나머지 배열값들이 순회해서 들어오게 된다

두번째 field 값들은

배열fields의 값이 순회하게 된다

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
            UserStorage.getUsers("id","psword");        // ← 이 부분 수정
        const response = {};
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;
        //         return res.json(response);
        //     }
        // }
        response.success = false;
        response.msg = "로그인에 실패하셨습니다.";
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

 

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...fields){
        const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{ // newUsers 초기값은 마음대로 지정할 수 있다
            if(users.hasOwnProperty(field)){        // users에 해당하는 키 값이 있느냐
                newUsers[field] = users[field];
            };
            return newUsers;    // return 되는 newUsers가 다음 값으로 들어가게 된다
        },{}); // 배열의 메서드 순환하면서 하나씩 반환 // {} 초기값으로 빈 오브젝트
        // console.log(newUsers);
        return newUsers;
    }
};
module.exports = UserStorage;

====================

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
            console.log(UserStorage.getUsers("id","psword","name"));        // ← 이 부분 수정
        const response = {};
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;
        //         return res.json(response);
        //     }
        // }
        response.success = false;
        response.msg = "로그인에 실패하셨습니다.";
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

cd app

npm start

 

{
  id: [ 'newstep', 'miero', '김팀장' ],
  psword: [ '1234', '1234', '123456' ],
  name: [ '뉴스텝', '미에로', '김팀장' ]
}

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const id = req.body.id,
            psword = req.body.psword;
            const users = UserStorage.getUsers("id","psword");        // ← 이 부분 수정
        const response = {};
        if (users.id.includes(id)) {
            const idx = users.id.indexOf(id);
            if (users.psword[idx] === psword) {
                response.success = true;
                return res.json(response);
            }
        }
        response.success = false;
        response.msg = "로그인에 실패하셨습니다.";
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

 

app>src>public>js>home>login.js--------------------

'use strict'; //ecma script 준수하겠다
// 테스트하기위해서
// console.log("hello");
// console.log("bye");
// login 기능 구현 - 프론트 단 기능 구현
// 아이디와 비밀번호 입력 받고
// 로그인 버튼이 눌릴 때 server로 전달이 된다
// 아이디와 패스워드를 javascript로 처리해야 된다
const id = document.querySelector("#id"),
    psword = document.querySelector("#psword"),
    loginBtn = document.querySelector("button");
// console.log(id);
// console.log("hello");
loginBtn.addEventListener("click",login); // 두 번째 인수는 함수이다
function login(){
    // console.log("bye");
    // console.log(id.value);
    const req = {
        id: id.value,
        psword: psword.value,
    };
    // console.log(req); // 일반 req 리퀘스트 데이터와
    // console.log(JSON.stringify(req)); // JSON 형태로 감싼 req 리퀘스트 데이터 비교해 보자
    fetch("/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())        // ← 이 부분 수정하고
      .then((res) => {				// ← 여기 부분
        if(res.success){                                   // 개발하기쉽게 임시로 주석처리 20
          location.href = "/";		// 이동할 링크           // 개발하기쉽게 임시로 주석처리 20
        } else {
          alert(res.msg);				// 서버에서 전달한 메시지// 개발하기쉽게 임시로 주석처리 20
        }                                                // 개발하기쉽게 임시로 주석처리 20
      })
      .catch((err) => {
        console.error("로그인 중 에러 발생");
        // console.error(new Error("로그인 중 에러 발생"));
      });
};

====================

git add .

git commit -m "UserStorage 모델 구현"

git push origin master

 

21[Node.js] 백엔드 맛보기 | User 모델 만들기 | 객체지향 프로그래밍 | 인스턴스화

로그인 기능을 하는 모델을 만들어 볼려고 하는데 그 전에

지금까지 한걸 조금만 돌아보면

 

app이라는 폴더에 모든 소스코드를 몰아두었고

 

app.js라는 메인파일을 통해서 node라는 서버에 기본 설정들이 이루어지게 된다.

이 서버의 실행파일은 bin 안에 있고

src에는 MVC 디자인 패턴데로 분류해 두었다

M-model

V-views

C-control

app>src>routes>home>home.ctrl.js

app>src>routes>home>home.ctrl.js에서 콘트롤러 구현

     UserStorage.getUsers에서 user 데이터를 가져와서

     if문으로 user를 검증하는 로직

이 검증하는 if문 로직을 분리함으로써

가독성, 생산성, 재사용성, 유지보수성도 좋은 코드로 바꾸어 보자

모델을 하나 추가하자-로그인,회원가입 기능을 담당

app>src>models>User.js--------------------

"use strict";
class User{
    // 생성자
}
module.exports = User;

====================

궁극적인 모양 먼저 보면

app>src>routes>home>home.ctrl.js--------------------아직 실제 코드 아님

"use strict";
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        users.login();				// ← 궁극적으로 이렇게 만들려고
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================아직 실제 코드 아님

users.login만 하면 되게 하려면

app>src>models>User.js에 User라는 클래스를 만들었는데

User라는 클래스를 만들 때 인스턴스로 만들거다

그래서 new User()로 만들게 될거고

변수로 const user로 받게 되고

const user = new User(); 여기의 인스턴스를 만들 때

클라이언트가 전달한 req 리퀘스트의 body데이터를 기본적으로 갖고 있게 만들거다

const user = new User(req.body);

왜 그러냐 하면

이 user는 클라이언트의 user특성을 갖게 만들거다

무슨 말인가하면

내가 user 인데 아이디와 비밀번호를 입력하고 서버에게 전달하면

전달한 데이터를 갖고 있는 const user를 하나 만들고

이 유저가 로그인을 하면 user.login();

로그인을 처리하고

어떠한 리스폰스를 받아서 const response=user.login();

이 리스폰스를 콘트롤러가 res 제이슨으로 처리하게 만들어 줄거다 return res.json(response)

그러면 여기서 UserStorage도 빠졌다

UserStorage는 User.js 안에서 호출하게 된다 2:44

app>src>models>User.js--------------------

"use strict";
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
}
module.exports = User;

====================

생성자를 통해서 body를 만들거다

생성자의 body는 언제 넘기냐

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const User = require("../../models/User");
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

app>src>routes>home>home.ctrl.js에서

new User라고 생성을 하면서 req.body를 넘긴다

new User(req.body);

이 body가

app>src>models>User.js--------------------

"use strict";
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    login(){
        //
    }
}
module.exports = User;

====================

app>src>models>User.js에 User 클래스의 constructor 생성자의 body로 들어온다

constructor(body){

그러면 this.body=body;

this.body가 된다

그러면 app>src>routes>home>home.ctrl.js의 인스턴스로 만들수 있게 되었다

const user = new User(req.body);

다시 app>src>models>User.js에 class User 클래스에 메서드를 하나 만들자

login(){

또 app>src>routes>home>home.ctrl.js 콘트롤러에서

user.login()을 해서

어떠한 리스폰스를 받을거고

const response = user.login();

이 response를 클라이언트에게 json의 형태로 응답해 줄거다

return res.json(response);

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const User = require("../../models/User");
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = user.login();
        return res.json(response);
        // const id = req.body.id,
        //     psword = req.body.psword;
        //     const users = UserStorage.getUsers("id","psword");        // ← 이 부분 수정
        // const response = {};
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;
        //         return res.json(response);
        //     }
        // }
        // response.success = false;
        // response.msg = "로그인에 실패하셨습니다.";
        // return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

일단 app>src>models>User.js의

class User클래스에서

app>src>models>UserStorage.js안에 접근해서 데이터를 가져와야 된다

app>src>models>User.js의 상단에

const UserStorage로 가져와서

const UserStorage = require("./UserStorage");

class User안에 login()메서드에

const users = UserStorage.getUsers("id","psword");로 아이디와 비밀번호를 받을 수 있지만

오브젝트로 바로 받자

const { id, psword } = UserStorage.getUsers("id","psword"); 변수로 바로 받자

여기서 전달되는 필드는 2개 이다 "id"필드,"psword"필드

2개의 필드로 들어오는데 변수에 바로 전달

console.log(id,psword) 바로 찍어보면

app>src>models>User.js--------------------

"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    login(){
        const { id, psword } = UserStorage.getUsers("id","psword");
        console.log(id,psword);
    }
}
module.exports = User;

====================

cd app

npm start

로그인 버튼

 

서버 가동
[ 'newstep', 'miero', '김팀장' ] [ '1234', '1234', '123456' ]

 

아이디, 비밀번호 검증하는 코드 여기에 넣으면 되는데

그렇게 하지 않고4:50

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...fields){
        const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{ // newUsers 초기값은 마음대로 지정할 수 있다
            if(users.hasOwnProperty(field)){        // users에 해당하는 키 값이 있느냐
                newUsers[field] = users[field];
            };
            return newUsers;    // return 되는 newUsers가 다음 값으로 들어가게 된다
        },{}); // 배열의 메서드 순환하면서 하나씩 반환 // {} 초기값으로 빈 오브젝트
        // console.log(newUsers);
        return newUsers;
    }
    static getUserInfo(id){
        const users = this.#users;
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
};
module.exports = UserStorage;

====================

스토리지에서 가져온 id랑 클라이언트가 입력한 아이디가 같고

스토리지에서 가져온 psword랑 클라이언트가 입력한 패스워드가 같은지만 보자

여기서 데이터가 json형태로

[ 'newstep', 'miero', '김팀장' ] [ '1234', '1234', '123456' ]

이렇게 날아오니까

로직으로 처리할 수가 없다

그래서

 

< UserStorage에 요청한 id에 해당하는 데이터만 가져오는 메서드를 만들자>

static getUserInfo에 id 파라미터를 받을 건데

이렇게 하는 이유는

app>src>models>User.js에서

login(){

const { id, psword } = UserStorage.getUserInfo("아이디 값");

아이디 값을 던지면

이 아이디에 해당하는 miero 1234 미에로

이 세가지를 오브젝트로 전달하는 메서드를 만들거다

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...fields){
        const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{ // newUsers 초기값은 마음대로 지정할 수 있다
            if(users.hasOwnProperty(field)){        // users에 해당하는 키 값이 있느냐
                newUsers[field] = users[field];
            };
            return newUsers;    // return 되는 newUsers가 다음 값으로 들어가게 된다
        },{}); // 배열의 메서드 순환하면서 하나씩 반환 // {} 초기값으로 빈 오브젝트
        // console.log(newUsers);
        return newUsers;
    }
    static getUserInfo(id){
        const users = this.#users;
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
};
module.exports = UserStorage;

====================

static getUserInfo

스토리지에서 id,psword,name을 받아와서 

users의 key값들만 usersKeys에 담고

그러면 [id, psword, name] 이러한 배열이 만들어진다

이 배열을 reduce로 순회하면서

초기값으로는 {}오브젝트를 넣어주었고

그러면

newUser[id]=users[id][0]

최종적으로 return userInfo에 들어간다

userInfo를 app>src>models>User.js에서 출력해보면

app>src>models>User.js--------------------

"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    login(){
        // const { id, psword } = UserStorage.getUsers("id","psword");
        const a = UserStorage.getUserInfo("miero");
        console.log(a);
    }
}
module.exports = User;

====================

User.js의 login은 

app>src>routes>home>home.ctrl.js컨트롤러에서 호출했으니까 실행이 될거다

const ctrlprocess안에 login안에 const response = user.login();

 

cd app

npm start

로그인 버튼

 

{ id: 'miero', psword: '1234', name: '미에로' }

7:42

오브젝트로 날아왔으니까

로그인 검증할 때는 id와 psword만 있으면 되니까

app>src>models>User.js

const { id, psword } = UserStorage.getUserInfo("miero")

 

내가 전달한 id인 "miero"가 UserStorage에 있으면

if (id) {

클라이언트의 this.id와 UserStorage의 id가 같은지 비교

if (id===this.body.id&&psword===this.body.psword) {

비밀번호도 비교해서

오브젝트형태로 아이디가 같으면 return { success: true };

아이디는 있는데 비밀번호가 다르면

return { success: false, msg: "비밀번호가 틀렸습니다. }

만약 아이디가 존재하지 않을 경우에는

return { success: false, msg: "존재하지 않는 아이디 입니다." }

app>src>models>User.js--------------------

"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    login(){
        // const { id, psword } = UserStorage.getUsers("id","psword");
        // const a = UserStorage.getUserInfo("miero");
        // console.log(a);
        // const { id, psword } = UserStorage.getUsers("miero");
        const body = this.body;
        const { id, psword } = UserStorage.getUserInfo(body.id);
        if(id){
            if ( id === body.id && psword === body.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
}
module.exports = User;

====================

 

app>src>routes>home>home.ctrl.js컨트롤러에서 user.login()함수를 실행할 때 return 값을 던졌으니까

반환값을 const response가 받을것이다

반환값을 console로 찍어보면

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const User = require("../../models/User");
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = user.login();
        console.log(response);
        // return res.json(response);      // 잠시 주석처리
        // const id = req.body.id,
        //     psword = req.body.psword;
        //     const users = UserStorage.getUsers("id","psword");        // ← 이 부분 수정
        // const response = {};
        // if (users.id.includes(id)) {
        //     const idx = users.id.indexOf(id);
        //     if (users.psword[idx] === psword) {
        //         response.success = true;
        //         return res.json(response);
        //     }
        // }
        // response.success = false;
        // response.msg = "로그인에 실패하셨습니다.";
        // return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

그런데 this.body가 중복이 많이 되니까

하나의 변수에 담아주자 const body = this.body

app>src>models>User.js--------------------9:15

"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    login(){
        // const { id, psword } = UserStorage.getUsers("id","psword");
        // const a = UserStorage.getUserInfo("miero");
        // console.log(a);
        // const { id, psword } = UserStorage.getUsers("miero");
        const body = this.body;
        const { id, psword } = UserStorage.getUserInfo(body.id);
        if(id){
            if ( id === body.id && psword === body.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
}
module.exports = User;

====================

cd app

npm start

 

아무것도 입력안하고 

로그인 버튼

 

서버 가동
{ success: false, msg: '존재하지 않는 아이디 입니다.' }

 

아이디에 miero 입력
{ success: false, msg: '비밀번호가 틀렸습니다.' }

패스워드에 1234 입력

{ success: true }

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const User = require("../../models/User");
const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = user.login();
        console.log(response);
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

app>src>routes>home>home.ctrl.js의

컨트롤러ctrlprocess는

const UserStorage에 접근하지 않는다

// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
 
const ctrlprocess = {
login:(req,res)=>{
const user = new User(req.body); 유저라는 클래스를 인스턴스화 할 때
클라이언트가 전달한 req리퀘스트 데이터를 넣어서 인스턴스화를 하게 되고
const user라는 애는 app>src>models>User.js의 해당하는 body 데이터를 계속 들고 다니게 된다
app>src>routes>home>home.ctrl.js에서 user유저가 login 메서드를 호출하면 user.login();
app>src>models>User.js에서 this.body를 가져와서
그 body의 id값 즉 클라이언트가 입력한 id값을
스토리지에 getUserInfo메서드로 전달을 한다
body.id에 해당하는 정보를 UserStorage 클래스가 반환해 줄거다
받아올 때는 id와 psword만 받아왔고
 
app>src>models>User.js--------------------
"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    login(){
        // const { id, psword } = UserStorage.getUsers("id","psword");
        // const a = UserStorage.getUserInfo("miero");
        // console.log(a);
        // const { id, psword } = UserStorage.getUsers("miero");
        const body = this.body;
        const { id, psword } = UserStorage.getUserInfo(body.id);
        if(id){
            if ( id === body.id && psword === body.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
}
module.exports = User;
====================
 
아이디가 존재하고
if(id){
스토리지의 id와 클라이언트의 id가 같고 스토리지의 psword가 클라이언트의 psword가 같으면
return { success: true }

다르면

return 비밀번호가 틀렸다

 

id도 존재하지 않으면

return 존재하지 않는 아이디입니다.

 

// 어려우면 두 번, 세 번 계속 보면 된다

한 가지만 고치자

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = user.login();
        // console.log(response);
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

클라이언트에 던져주면 된다

cd app

npm start

 

alert 정상 작동

 

git add .

git commit -m "User 모델 구현"

git push origin master

 

다음 시간에는 login 화면 예쁘게 만들자

그 다음 회원가입 기능

 

22[Node.js] 백엔드 맛보기 | 로그인 화면 꾸미기 | 오픈소스 사용해보기 | 코드펜(codepen

codepen.io

login

Flat HTML

하단에 comments

스크롤 최하단 License ...

app>src>views>home>login.ejs

하단에 주석으로 달아주자

HTML 소스 복사

 

body 안에 넣어주자

app>src>views>home>login.ejs--------------------

<!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">
    <script src="/js/home/login.js" defer></script> <!-- defer 추가 -->
    <title>Document</title>
</head>
<body>
    <div class="login-page">
        <div class="form">
          <!-- <form class="register-form">
            <input type="text" placeholder="name"/>
            <input type="password" placeholder="password"/>
            <input type="text" placeholder="email address"/>
            <button>create</button>
            <p class="message">Already registered? <a href="#">Sign In</a></p>
          </form> -->
          <form class="login-form">
            <input id="id" type="text" placeholder="아이디"/>
            <input id="psword" type="password" placeholder="패스워드"/>
            <button>LOGIN</button>
            <p class="message">Not registered? <a href="/register">Create an account</a></p>
          </form>
        </div>
      </div>
</body>
</html>
<!-- Copyright (c) 2022 by Aigars Silkalns (https://codepen.io/colorlib/pen/rxddKy) -->

====================

css복사

app>src>public>css>home>login.css--------------------

@import url(https://fonts.googleapis.com/css?family=Roboto:300);
.login-page {
  width: 360px;
  padding: 8% 0 0;
  margin: auto;
}
.form {
  position: relative;
  z-index: 1;
  background: #FFFFFF;
  max-width: 360px;
  margin: 0 auto 100px;
  padding: 45px;
  text-align: center;
  box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
  font-family: "Roboto", sans-serif;
  outline: 0;
  background: #f2f2f2;
  width: 100%;
  border: 0;
  margin: 0 0 15px;
  padding: 15px;
  box-sizing: border-box;
  font-size: 14px;
}
.form button {
  font-family: "Roboto", sans-serif;
  text-transform: uppercase;
  outline: 0;
  background: #4CAF50;
  width: 100%;
  border: 0;
  padding: 15px;
  color: #FFFFFF;
  font-size: 14px;
  -webkit-transition: all 0.3 ease;
  transition: all 0.3 ease;
  cursor: pointer;
}
.form button:hover,.form button:active,.form button:focus {
  background: #43A047;
}
.form .message {
  margin: 15px 0 0;
  color: #b3b3b3;
  font-size: 12px;
}
.form .message a {
  color: #4CAF50;
  text-decoration: none;
}
.form .register-form {
  display: none;
}
.container {
  position: relative;
  z-index: 1;
  max-width: 300px;
  margin: 0 auto;
}
.container:before, .container:after {
  content: "";
  display: block;
  clear: both;
}
.container .info {
  margin: 50px auto;
  text-align: center;
}
.container .info h1 {
  margin: 0 0 15px;
  padding: 0;
  font-size: 36px;
  font-weight: 300;
  color: #1a1a1a;
}
.container .info span {
  color: #4d4d4d;
  font-size: 12px;
}
.container .info span a {
  color: #000000;
  text-decoration: none;
}
.container .info span .fa {
  color: #EF3B3A;
}
body {
  background: #76b852; /* fallback for old browsers */
  background: -webkit-linear-gradient(right, #76b852, #8DC26F);
  background: -moz-linear-gradient(right, #76b852, #8DC26F);
  background: -o-linear-gradient(right, #76b852, #8DC26F);
  background: linear-gradient(to left, #76b852, #8DC26F);
  font-family: "Roboto", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;      
}
/* Copyright (c) 2022 by Aigars Silkalns (https://codepen.io/colorlib/pen/rxddKy) */

====================

login.css 파일이랑 login.ejs 파일 연결해줘야 된다

link rel="stylesheet" href="/css/home/login.css"

app>src>views>home>login.ejs--------------------

<!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">
    <link rel="stylesheet" href="/css/home/login.css">
    <script src="/js/home/login.js" defer></script> <!-- defer 추가 -->
    <title>Document</title>
</head>
<body>
    <div class="login-page">
        <div class="form">
          <!-- <form class="register-form">
            <input type="text" placeholder="name"/>
            <input type="password" placeholder="password"/>
            <input type="text" placeholder="email address"/>
            <button>create</button>
            <p class="message">Already registered? <a href="#">Sign In</a></p>
          </form> -->
          <form class="login-form">
            <input id="id" type="text" placeholder="아이디"/>
            <input id="psword" type="password" placeholder="패스워드"/>
            <button>LOGIN</button>
            <p class="message">Not registered? <a href="/register">Create an account</a></p>
          </form>
        </div>
      </div>
</body>
</html>
<!-- Copyright (c) 2022 by Aigars Silkalns (https://codepen.io/colorlib/pen/rxddKy) -->

====================

form class="register-form" 도 있는데

css파일에서 안보이게 설정되어 있다

.form .register-form { display: none; }

회원가입 폼

app>src>views>home>login.ejs--------------------

<!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">
    <link rel="stylesheet" href="/css/home/login.css">
    <script src="/js/home/login.js" defer></script> <!-- defer 추가 -->
    <title>Document</title>
</head>
<body>
    <div class="login-page">
        <div class="form">
          <form class="login-form">
            <input id="id" type="text" placeholder="아이디"/>			// ← 수정
            <input id="psword" type="password" placeholder="패스워드"/>		// ← 수정
            <button>LOGIN</button>
            <p class="message">Not registered? <a href="/register">Create an account</a></p>// ← 수정
          </form>
        </div>
      </div>
</body>
</html>
<!-- Copyright (c) 2022 by Aigars Silkalns (https://codepen.io/colorlib/pen/rxddKy) -->

====================

회원가입 부분 지워주고

 

git add .

git commit -m "로그인화면 꾸미기"

git push origin master

23[Node.js] 백엔드 맛보기 | 회원가입 화면 만들기&꾸미기 | 오픈소스 사용해보기 | 코드펜(codepen)

회원가입화면 만들기

app>src>views>home>login.ejs에

a hef="/register"

라우팅 설정

app>src>routes>home>index.js--------------------

"use strict"; //ecma script 준수하겠다
const express = require("express");
const router = express.Router(); // 라우터를 사용할려면 express의 Router를 불러와주어야 한다
const ctrl = require("./home.ctrl");
// app.js 라우팅 부분 잘라오기
// app.get("/",(req,res)=>{
    //     res.render("home/index");
    // });
    // app.get("/login",(req,res)=>{
        //     res.render("home/login");
// });
router.get("/",ctrl.ctrloutput.ctrlindex);
router.get("/login",ctrl.ctrloutput.ctrllogin); // 아랫줄 post 추가해서 login 중복이 발생
router.get("/register",ctrl.ctrloutput.register); // 아랫줄 post 추가해서 login 중복이 발생
router.post("/login",ctrl.ctrlprocess.ctrllogin); // post 추가 // process로 수정 // ← error catch 일부러 주석처리
module.exports = router; // 외부파일에서 사용할 수 있도록 보내기

====================

/register로 get 요청이 들어오면 해당함수 ctrl.ctrloutput.regiser가 실행되게 해주자

register함수를 만들어줘야 하는데

여기는 서버단에서 구현되고 있는 거다

이것의 컨트롤러 파일로 이동하면

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        res.render("home/register"); // views\home // ← 이 부분 만들어줘야 한다
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = user.login();
        // console.log(response);
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

ctrloutput 그냥 화면 출력부분이다

register: 추가해주고

app>src>views>home>register.ejs 만들어 줘야 하는데

app>src>views>home>login.ejs 복사해서 붙여넣기 해주자1:21

app>src>views>home>register.ejs--------------------

<!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">
    <link rel="stylesheet" href="/css/home/login.css">
    <script src="/js/home/login.js" defer></script> <!-- defer 추가 -->
    <title>Document</title>
</head>
<body>
    <div class="login-page">
        <div class="form">
          <form class="login-form">
            <input id="id" type="text" placeholder="아이디"/>
            <input id="name" type="text" placeholder="이름"/>
            <input id="psword" type="password" placeholder="비밀번호"/>
            <input id="confirm-psword" type="password" placeholder="비밀번호 확인"/>
            <button>SIGN UP</button>
            <p class="message">이미 회원 가입을 하셨습니까? <a href="/login">login</a></p>
          </form>
        </div>
      </div>
</body>
</html>
<!-- Copyright (c) 2022 by Aigars Silkalns (https://codepen.io/colorlib/pen/rxddKy) -->

====================

 

git add .

git commit -m "회원가입 페이지 구현"

git push origin master

 

 

24[Node.js] 백엔드 맛보기 | 회원가입 요청 구현 in 프런트 | fetch | ajax

프론트에서 회원가입 기능 만들어보기

app>src>public>js>home>login.js 복사해서 붙여넣기

app>src>public>js>home>register.js--------------------

'use strict'; //ecma script 준수하겠다
const id = document.querySelector("#id"),
    psword = document.querySelector("#psword"),
    loginBtn = document.querySelector("button");
console.log("hello register");	// ← 테스트 위해서 찍어보자
loginBtn.addEventListener("click",login);
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())
      .then((res) => {
        if(res.success){
          location.href = "/";
        } else {
          alert(res.msg);
        }
      })
      .catch((err) => {
        console.error("로그인 중 에러 발생");
      });
};

====================

html파일이랑 연결해주어야 하니까

app>src>views>home>register.ejs--------------------

<!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">
    <link rel="stylesheet" href="/css/home/login.css">
    <script src="/js/home/register.js" defer></script>	// ← register.js
    <title>Document</title>
</head>
<body>
    <div class="login-page">
        <div class="form">
          <form class="login-form">
            <input id="id" type="text" placeholder="아이디"/>
            <input id="name" type="text" placeholder="이름"/>
            <input id="psword" type="password" placeholder="비밀번호"/>
            <input id="confirm-psword" type="password" placeholder="비밀번호 확인"/>
            <!-- <button>SIGN UP</button> -->
            <p id="button">SIGN UP</p>
            <p class="message">이미 회원 가입을 하셨습니까? <a href="/login">login</a></p>
          </form>
        </div>
      </div>
</body>
</html>
<!-- Copyright (c) 2022 by Aigars Silkalns (https://codepen.io/colorlib/pen/rxddKy) -->

====================

cd app

npm start

 

192.168.1.65:3000/register

콘솔 창 ctrl+shift+i

 

hello register

app>src>views>home>register.ejs =잘 연결됨= app>src>public>js>home>register.js

 

app>src>public>js>home>register.js--------------------

'use strict'; //ecma script 준수하겠다
const id = document.querySelector("#id"),
    name = document.querySelector("#name"),	// ←
    psword = document.querySelector("#psword"),
    confirmPsword = document.querySelector("#confirm-psword"),	// ←
    registerBtn = document.querySelector("#button");	// ← 회원가입 button
registerBtn.addEventListener("click", register); // ←
function register(){ // ←
    const req = {
        id: id.value,
        name: name.value,         // ←
        psword: psword.value,
        confirmPsword: confirmPsword.value,         // ←
    };
    console.log(req);	// ← 테스트 위해서 찍어보자
    // fetch("/register", {
    //     method: "POST",
    //     headers: {
    //       "Content-Type": "application/json",
    //     },
    //     body: JSON.stringify(req),
    //   })
    //   .then((res) => res.json())
    //   .then((res) => {
    //     if(res.success){
    //       location.href = "/";
    //     } else {
    //       alert(res.msg);
    //     }
    //   })
    //   .catch((err) => {
    //     console.error("로그인 중 에러 발생");
    //     // console.error(new Error("로그인 중 에러 발생"));
    //   });
};

====================

app>src>public>js>home>register.js 수정해주자

console.log 지워주고

login 모두 바꾸기

ctrl + d 여러번

register 로 바꾸기

 

name

confirmPsword

fetch 우선 주석처리

 

cd app

npm start

 

192.168.1.65:3000/register

입력

SIGN UP

 

{id: 'new', name: '임정', psword: '1234', confirmPsword: '1234'}

문제점 - 나왔다가 바로 사라짐

-SIGN UP 누를 때마다 사이트가 새로고침 된다

왜 그렇냐 하면

app>src>views>home>register.ejs--------------------보자

<!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">
    <link rel="stylesheet" href="/css/home/login.css">
    <script src="/js/home/register.js" defer></script> <!-- defer 추가 -->
    <title>Document</title>
</head>
<body>
    <div class="login-page">
        <div class="form">
          <form class="login-form">
            <input id="id" type="text" placeholder="아이디"/>
            <input id="name" type="text" placeholder="이름"/>
            <input id="psword" type="password" placeholder="비밀번호"/>
            <input id="confirm-psword" type="password" placeholder="비밀번호 확인"/>
            <!-- <button>SIGN UP</button> -->
            <p id="button">SIGN UP</p>
            <p class="message">이미 회원 가입을 하셨습니까? <a href="/login">login</a></p>
          </form>
        </div>
      </div>
</body>
</html>
<!-- Copyright (c) 2022 by Aigars Silkalns (https://codepen.io/colorlib/pen/rxddKy) -->

====================

button을 감싸고 있는 태그가 form태그여서 그런것이다

form태그는 기본적으로 form 안에 있는 button을 submit 해주는 기능을 가지고 있다

따라서 button이 form 안에 있을 때 button을 클릭하면 페이지가 리로드된다

그래서 button태그를 p태그로 바꾸어 주고 id도 "button"이라고 부여해주자

app>src>public>js>home>register.js--------------------파일수정

'use strict'; //ecma script 준수하겠다
const id = document.querySelector("#id"),
    name = document.querySelector("#name"),
    psword = document.querySelector("#psword"),
    confirmPsword = document.querySelector("#confirm-psword"),
    registerBtn = document.querySelector("#button");	// ← id로 불러오자
registerBtn.addEventListener("click", register);
function register(){
    // console.log("bye");
    // console.log(id.value);
    const req = {
        id: id.value,
        name: name.value,
        psword: psword.value,
        confirmPsword: confirmPsword.value,
    };
    console.log(req);   // ← 테스트
    // fetch("/register", {
    //     method: "POST",
    //     headers: {
    //       "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
    //     },
    //     body: JSON.stringify(req),
    //   })
    //   .then((res) => res.json())        // ← 이 부분 수정하고
    //   .then((res) => {				// ← 여기 부분
    //     if(res.success){                                   // 개발하기쉽게 임시로 주석처리 20
    //       location.href = "/";		// 이동할 링크           // 개발하기쉽게 임시로 주석처리 20
    //     } else {
    //       alert(res.msg);				// 서버에서 전달한 메시지// 개발하기쉽게 임시로 주석처리 20
    //     }                                                // 개발하기쉽게 임시로 주석처리 20
    //   })
    //   .catch((err) => {
    //     console.error("로그인 중 에러 발생");
    //     // console.error(new Error("로그인 중 에러 발생"));
    //   });
};

====================

app>src>public>css>home>login.css--------------------파일수정

@import url(https://fonts.googleapis.com/css?family=Roboto:300);
.login-page {
  width: 360px;
  padding: 8% 0 0;
  margin: auto;
}
.form {
  position: relative;
  z-index: 1;
  background: #FFFFFF;
  max-width: 360px;
  margin: 0 auto 100px;
  padding: 45px;
  text-align: center;
  box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
  font-family: "Roboto", sans-serif;
  outline: 0;
  background: #f2f2f2;
  width: 100%;
  border: 0;
  margin: 0 0 15px;
  padding: 15px;
  box-sizing: border-box;
  font-size: 14px;
}
.form #button {
  font-family: "Roboto", sans-serif;
  text-transform: uppercase;
  outline: 0;
  background: #4CAF50;
  width: 80%;
  border: 0;
  margin: 0 auto;
  padding: 15px;
  color: #FFFFFF;
  font-size: 14px;
  -webkit-transition: all 0.3 ease;
  transition: all 0.3 ease;
  cursor: pointer;
}
.form #button:hover,.form #button:active,.form #button:focus {
  background: #43A047;
}
.form .message {
  margin: 15px 0 0;
  color: #b3b3b3;
  font-size: 12px;
}
.form .message a {
  color: #4CAF50;
  text-decoration: none;
}
.form .register-form {
  display: none;
}
.container {
  position: relative;
  z-index: 1;
  max-width: 300px;
  margin: 0 auto;
}
.container:before, .container:after {
  content: "";
  display: block;
  clear: both;
}
.container .info {
  margin: 50px auto;
  text-align: center;
}
.container .info h1 {
  margin: 0 0 15px;
  padding: 0;
  font-size: 36px;
  font-weight: 300;
  color: #1a1a1a;
}
.container .info span {
  color: #4d4d4d;
  font-size: 12px;
}
.container .info span a {
  color: #000000;
  text-decoration: none;
}
.container .info span .fa {
  color: #EF3B3A;
}
body {
  background: #76b852; /* fallback for old browsers */
  background: -webkit-linear-gradient(right, #76b852, #8DC26F);
  background: -moz-linear-gradient(right, #76b852, #8DC26F);
  background: -o-linear-gradient(right, #76b852, #8DC26F);
  background: linear-gradient(to left, #76b852, #8DC26F);
  font-family: "Roboto", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;      
}
/* Copyright (c) 2022 by Aigars Silkalns (https://codepen.io/colorlib/pen/rxddKy) */

====================

.form #button { width:80%; margin: 0 auto; 가운데정렬

.form #button:hover,.form #button:active,.form #button:focus {

id로 접근하자

app>src>views>home>login.ejs--------------------수정

<!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">
    <link rel="stylesheet" href="/css/home/login.css">
    <script src="/js/home/login.js" defer></script> <!-- defer 추가 -->
    <title>Document</title>
</head>
<body>
    <div class="login-page">
        <div class="form">
          <form class="login-form">
            <input id="id" type="text" placeholder="아이디"/>
            <input id="psword" type="password" placeholder="패스워드"/>
            // <button>LOGIN</button>
            <p id="button">LOGIN</p>
            <p class="message">Not registered? <a href="/register">Create an account</a></p>
          </form>
        </div>
      </div>
</body>
</html>
<!-- Copyright (c) 2022 by Aigars Silkalns (https://codepen.io/colorlib/pen/rxddKy) -->

====================

이 파일과 연결된 자바스크립트도 수정

app>src>public>js>home>login.js--------------------

'use strict'; //ecma script 준수하겠다
const id = document.querySelector("#id"),
    psword = document.querySelector("#psword"),
    loginBtn = document.querySelector("#button");	// ←
loginBtn.addEventListener("click",login); // 두 번째 인수는 함수이다
function login(){
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())        // ← 이 부분 수정하고
      .then((res) => {				// ← 여기 부분
        if(res.success){                                   // 개발하기쉽게 임시로 주석처리 20
          location.href = "/";		// 이동할 링크           // 개발하기쉽게 임시로 주석처리 20
        } else {
          alert(res.msg);				// 서버에서 전달한 메시지// 개발하기쉽게 임시로 주석처리 20
        }                                                // 개발하기쉽게 임시로 주석처리 20
      })
      .catch((err) => {
        console.error("로그인 중 에러 발생");
        // console.error(new Error("로그인 중 에러 발생"));
      });
};

====================

cd app

npm start

 

192.168.1.65:3000/register

입력

SIGN UP

 

{id: 'new', name: '임정', psword: '1234', confirmPsword: '1234'}

app>src>public>js>home>register.js--------------------

'use strict'; //ecma script 준수하겠다
// 테스트하기위해서
// console.log("hello");
// console.log("bye");
// register 기능 구현 - 프론트 단 기능 구현
// 아이디와 비밀번호 입력 받고
// 로그인 버튼이 눌릴 때 server로 전달이 된다
// 아이디와 패스워드를 javascript로 처리해야 된다
const id = document.querySelector("#id"),
    name = document.querySelector("#name"),
    psword = document.querySelector("#psword"),
    confirmPsword = document.querySelector("#confirm-psword"),
    registerBtn = document.querySelector("#button");
// console.log(id);
// console.log("hello");
// console.log("hello register");              // ← 테스트
registerBtn.addEventListener("click", register); // 두 번째 인수는 함수이다
function register(){
    // console.log("bye");
    // console.log(id.value);
    const req = {
        id: id.value,
        name: name.value,         // ←
        psword: psword.value,
        confirmPsword: confirmPsword.value,         // ←
    };
    // console.log(req); // 일반 req 리퀘스트 데이터와
    // console.log(JSON.stringify(req)); // JSON 형태로 감싼 req 리퀘스트 데이터 비교해 보자
    console.log(req);   // ← 테스트
    fetch("/register", {
        method: "POST",
        headers: {
          "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
        },
        body: JSON.stringify(req),	// ← 프론트에서 입력한 데이터 여기 담아서 전달
      })
      .then((res) => res.json())        // ← 서버로부터 응답이 오면
      .then((res) => {				// ← 여기 부분
        if(res.success){                                   // 개발하기쉽게 임시로 주석처리 20
          location.href = "/";		// 이동할 링크           // 개발하기쉽게 임시로 주석처리 20
        } else {
          alert(res.msg);				// 서버에서 전달한 메시지// 개발하기쉽게 임시로 주석처리 20
        }                                                // 개발하기쉽게 임시로 주석처리 20
      })
      .catch((err) => {
        console.error("회원가입 중 에러 발생");	// ←
        // console.error(new Error("로그인 중 에러 발생"));
      });
};

====================5:45

body: JSON.stringify(req), // ← 프론트에서 입력한 데이터 여기 담아서 전달

POST 로 전달

.then((res) => res.json())        // ← 서버로부터 응답이 오면 json메서드를 호출을 해서

응답이 다받아지는 순간 promise 객체를 반환하게 되고

promise객체를 반환했으니까 두 번째 then으로 접근

res.success를 받아와서

true이면 로그인 페이지로 이동 location.href="/login"

실패했으면 alert(res.msg)

 

아직 서버에서 POST로 데이터를 받을 상태가 아니다

 

다음 시간에 해당 API를 서버에 만들어 주게 하자

 

사실 프론트 개발전에 백엔드가 먼저 만들어져 있어야 한다

 

다음시간에 회원가입API를 만들으로써 

 

git add .

git commit -m "회원가입 요청 구현"

git push origin master

 

25[Node.js] 백엔드 맛보기 | 회원가입 라우팅&기능구현 in 서버 | 깃 버전 관리 | tag

서버에서 실제 유저의 정보를 받아서 회원가입을 처리해주는 로직 구현

해당 API 먼저 만들어주자

 

app>src>routes>index.js--------------------

"use strict"; //ecma script 준수하겠다
const express = require("express");
const router = express.Router();
const ctrl = require("./home.ctrl");
router.get("/",ctrl.ctrloutput.ctrlindex);
router.get("/login",ctrl.ctrloutput.ctrllogin);
router.get("/register",ctrl.ctrloutput.register);
router.post("/login",ctrl.ctrlprocess.ctrllogin);
router.post("/register",ctrl.ctrlprocess.register); // ← 
module.exports = router;

====================

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        res.render("home/register"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = user.login();
        // console.log(response);
        return res.json(response);
    },
    register: (req,res)=>{
        const user = new User(req.body);
        const response = user.register(); // ←
        // console.log(response);
        return res.json(response);
    }
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

User 클래스로 이동해보면

app>src>models>User.js--------------------

"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {
        this.body = body;
    }
    login(){
        const client = this.body;	// ←
        const { id, psword } = UserStorage.getUserInfo(client.id);	// ←
        if(id){
            if ( id === client.id && psword === client.psword){	// ←
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() { // ← 
        const client = this.body; // ← constructor의 body를 그대로 던져주자
        UserStorage.save(client); // ← 
    } // ← 
}
module.exports = User;

====================

User 클래스에 register 메서드를 만들어서

이 User는 단순하게 UserStorage의 save라는 메서드를 호출해서 데이터를 저장해주도록 한다

저장될 데이터를 스토리지에 던져줘야 하니까

constructor에서 받은 body를 그대로 던져주도록 하겠습니다

login메서드에서 const client = this.body로 해주고

밑부분 다 수정

이제 UserStorage에 저장하는 해당 메서드를 UserStorage 안에 구현해주도록 하자

데이터를 저장하기위해서는 UserStorage에 저장하면 안된다

한 번 살펴보자

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...fields){
        const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        const users = this.#users;
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
    static save(){	// ←
    }
};
module.exports = UserStorage;

====================

static save라는 메서드를 만들고

 

app>src>models>User.js

register메서드 보면

UserStorage에 save메서드로 파라미터로 client를 던지는데

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...fields){
        const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        // console.log(newUsers);
        return newUsers;
    }
    static getUserInfo(id){
        const users = this.#users;
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
    static save(userInfo){	// ←
    }
};
module.exports = UserStorage;

====================

static save함수는 

app>src>models>User.js의 register안에 UserStorage.save(client) 해당 데이터가

유저의 정보이니까

app>src>models>UserStorage.js안에

userInfo로 받아주자

static save(userInfo) 받고

해당 데이터를 

위에 static #users에 저장해주어야 되니까

이 로직을 구현하기전에 

먼저

static #users에 정상적으로

데이터가 저장 될 수 있는지 테스트 해보자

app>src>models>UserStorage.js안에

const users = this.#users 를 넣어주었고

단순하게 

users.id.push()

파라미터로 넘어온 userInfo.id 클라이언트의 id를 저장해보자

users.id.push(userInfo.id)

users.name.push(userInfo.name)

users.psword.push(userInfo.psword)

우리의 의도는 

users오브젝트안에 해당 데이터들이 저장되어야 한다.

클라이언트에서 데이터를 전달을 하면

정상적으로 동작하는지 보면

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...fields){
        const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{ // newUsers 초기값은 마음대로 지정할 수 있다
            if(users.hasOwnProperty(field)){        // users에 해당하는 키 값이 있느냐
                newUsers[field] = users[field];
            };
            return newUsers;    // return 되는 newUsers가 다음 값으로 들어가게 된다
        }, {}); // 배열의 메서드 순환하면서 하나씩 반환 // {} 초기값으로 빈 오브젝트
        // console.log(newUsers);
        return newUsers;
    }
    static getUserInfo(id){
        const users = this.#users;
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);               // [id,psword,name] 이러한 배열이 만들어짐
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
    static save(userInfo){
        const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
    }
};
module.exports = UserStorage;

====================

console.log(users) 찍어보자

cd app

npm start

 

192.168.1.65:3000/register

new, 정new, 1234

 

서버 가동
{
  id: [ 'newstep', 'miero', '김팀장', 'new' ],
  psword: [ '1234', '1234', '123456', '1234' ],
  name: [ '뉴스텝', '미에로', '김팀장', '정new' ]
}

콘솔에는 정상적으로 찍혔다

그런데 정상이 아니다

로그인 페이지로 이동해서 

192.168.1.65:3000/login

new 1234

 

여기는 루트입니다

 

정상적으로 로그인이 됩니다

 

<그런데 왜 이렇게 하지 말라는 걸까>

여기서 서버를 껐다 켜보자

ctrl+c

npm start

192.168.1.65:3000/login

new 1234

존재하지 않는 아이디 입니다.

 

app>src>models>UserStorage.js 안에는

#users 데이터가 또 3개 밖에 없게 된다

npm start

192.168.1.65:3000/register

SIGN UP 만 클릭해보면

 

서버 가동
{
  id: [ 'newstep', 'miero', '김팀장', '' ],
  psword: [ '1234', '1234', '123456', '' ],
  name: [ '뉴스텝', '미에로', '김팀장', '' ]
}

공백저장으로 나온다

아무것도 입력 안했으니까

조금전의 new는 저장이 안되는것이다

 

문제점

서버를 껐다 켰을 때

다 없어지게 되니까

 

데이터는 파일안에 저장해야 되는데

파일에 저장하는 로직을 구현해보자

 

파일에 저장하는 것은 별도 주제로 다루겠다

 

이번 시간에는 무엇을 했나

app>src>routes>home>index.js에

해당 라우팅 구현 router.post("/register",ctrl.ctrlprocess.register)

 

app>src>routes>home>home.ctrl.js에

해당 register기능을 하는 함수를 만들어 주었고

 

app>src>models>User.js에

register라는 메서드를 만들어 주었고

 

app>src>models>UserStorage.js에

클라이언트에서 전달한 데이터를 static save함수를 만들었다

 

정상 작동하는지 보기위해서

app>src>models>UserStorage.js에서

console.log(users)지우고

return { success: true } 오브젝트를 던져주자

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static #users = {                        // 변수에 static을 붙여줘야 class에서 변수로 접근 가능
        id: ["newstep", "miero", "김팀장"],
        psword: ["1234","1234","123456"],
        name: ["뉴스텝","미에로","김팀장"],
    };
    static getUsers(...fields){
        const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{ // newUsers 초기값은 마음대로 지정할 수 있다
            if(users.hasOwnProperty(field)){        // users에 해당하는 키 값이 있느냐
                newUsers[field] = users[field];
            };
            return newUsers;    // return 되는 newUsers가 다음 값으로 들어가게 된다
        }, {}); // 배열의 메서드 순환하면서 하나씩 반환 // {} 초기값으로 빈 오브젝트
        // console.log(newUsers);
        return newUsers;
    }
    static getUserInfo(id){
        const users = this.#users;
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);               // [id,psword,name] 이러한 배열이 만들어짐
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
    static save(userInfo){
        const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

해당 오브젝트를 반환하니까

User클래스로 넘어가서

app>src>models>User.js에

const response로 받아서

response 값 반환

app>src>models>User.js--------------------

"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {
        this.body = body;
    }
    login(){
        const client = this.body;
        const { id, psword } = UserStorage.getUserInfo(client.id);
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client);	// ←
        return response;	// ←
    }
}
module.exports = User;

====================

콘트롤러파일에가서

app>src>routes>home>home.ctrl.js에서

const response = user.register()에 레지스트의 반환값을 받아서

json메서드를 통해서 클라이언트로 응답을 해주게 된다

return res.json(response)

 

이 상태에서 로그인과 회원가입이 정상 동작하는지 보자

192.168.1.65:3000/register

jjj 정정정 1234 1234

SIGN UP

하면 로그인페이지로 이동을 한다

jjj 1234

여기는 루트 입니다

정상 작동을 한다

문제점은 서버가 재가동 되면 데이터가 유실된다는 것이다

 

비밀번호 확인하기 기능 추가하기

프론트엔드의 자바스크립트파일 안에

confirmPsword: confirmPsword.value, 를 보내면 안된다.

왜냐하면 서버에서 필요한 데이터는 id, name, psword 만이다

이 로직은 프론트엔드에서만 처리해주면 된다.

app>src>public>js>home>register.js--------------------

'use strict'; //ecma script 준수하겠다
const id = document.querySelector("#id"),
    name = document.querySelector("#name"),
    psword = document.querySelector("#psword"),
    confirmPsword = document.querySelector("#confirm-psword"),
    registerBtn = document.querySelector("#button");
registerBtn.addEventListener("click", register);
function register(){
    if (psword.value !== confirmPsword){	// ←
      return alert("비밀번호가 일치하지 않습니다.");	// ←
    }
    const req = {
        id: id.value,
        name: name.value,
        psword: psword.value,
        // confirmPsword: confirmPsword.value,         // ←
    };
    console.log(req);
    fetch("/register", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())
      .then((res) => {
        if(res.success){
          location.href = "/login";
        } else {
          alert(res.msg);
        }
      })
      .catch((err) => {
        console.error("회원가입 중 에러 발생");
      });
};

====================

if (psword.value 같지않으면 !== confirmPsword)

 

cd app

npm start

 

192.168.1.65:3000/register

aaa 정 1 1234

SIGN UP

 

비밀번호가 일치하지 않습니다

 

아이디는 입력하도록 해주자

if (!id.value) 아이디가 비어있으면

app>src>public>js>home>register.js--------------------

'use strict'; //ecma script 준수하겠다
const id = document.querySelector("#id"),
    name = document.querySelector("#name"),
    psword = document.querySelector("#psword"),
    confirmPsword = document.querySelector("#confirm-psword"),
    registerBtn = document.querySelector("#button");
registerBtn.addEventListener("click", register);
function register(){
    if (!id.value) return alert("아이디를 입력해주십시오.");
    if (psword.value !== confirmPsword) return alert("비밀번호가 일치하지 않습니다.");
    const req = {
        id: id.value,
        name: name.value,
        psword: psword.value,
    };
    fetch("/register", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())
      .then((res) => {
        if(res.success){
          location.href = "/login";
        } else {
          alert(res.msg);
        }
      })
      .catch((err) => {
        console.error("회원가입 중 에러 발생");
      });
};

====================

cd app

npm start

192.168.1.65:3000/register

아무것도 입력안하고

SIGN UP

 

아이디를 입력해 주십시오.

 

ctrl + c

git add .

git commit -m "회원가입 라우팅 구현"

git push origin master

 

깃허브에 버전으로 기록해보자

깃허브에가면

github/jeongyongman/nodejs-backend 에 가서

master 삼각형 Tags 누르면 아직 아무것도 없는 상태

 

 

git tag v0.1.0-notDB

git tag

git log --oneline

q

git push origin v0.1.0-notDB

 

깃허브에서 새로고침

master 삼각형

Tags

v0.1.0-notDB 클릭

 

src폴더도 올라와 있다 왜 올라왔지 9:33

 

vscode 에 app폴더 밖에 src폴더 있으면 지우고

git add .

git status

아무것도 안올라간다

위에서 . 은 현재폴더를 의미한다

git add --all

git status

git commit -m "루트의 src폴더 삭제"

git push origin master

 

기존에 tag삭제해주자

git push origin : v0.1.0-notDB

git log --oneline

아직 로컬에 태그가 남아 있다

git tag -d v0.1.0-notDB

태그 다시 부여

git tag v0.1.0-notDB

git log --oneline

git push origin v0.1.0-notDB

 

깃허브에서 새로고침

master 삼각형

Tags

v0.1.0-notDB

View all tag 누르면 

zip 파일로 다운 받을 수 있다

 

26[Node.js] 백엔드 맛보기 | 데이터 파일로 관리하기 | fs(파일시스템) | json

파일로 데이터를 관리해보자

파일에 어떻게 데이터를 저장하는지 보자

app>src>models>UserStorage.js에 static #users 데이터를 잘라내서

app>src>models>UserStorage.js--------------------

"use strict";
class UserStorage {
    static getUsers(...fields){
        const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        const users = this.#users;
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
        });
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

 

app>src>databases>users.json--------------------붙여넣자

{
    "id": ["newstep", "miero", "김팀장"],   // shift + "
    "psword": ["1234","1234","123456"],	// "필드": ["데이터"]
    "name": ["뉴스텝","미에로","김팀장"]
}

====================

문자열 처리 shift+"

UserStorage.js 으로 이동을 해서

users.json 앞으로 유저스 테이블이라 부르자 2:46

UserStorage.js에서 users.json에 접근해서 해당 데이터를 읽어 올 수 있어야 된다.

그러기 위해서는 fs파일시스템이라는 걸 불러와야 된다.

fs를 이용해서 해당 파일에 접근을 해보자

로그인 부터 처리를 해보자

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");	// ←
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

테스트를 위해서 #users 입력 안할거니까

에러난다 const users=this.#users

#users가 없으니까

const users=this.#users 모두 주석처리

192.168.1.65/login

잘 나온다@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

과거로 돌아가서 생각을 다시 해보자3:27

LOGIN 버튼을 누르면

app>src>routes>home>index.js--------------------

"use strict"; //ecma script 준수하겠다
const express = require("express");
const router = express.Router();
const ctrl = require("./home.ctrl");
router.get("/",ctrl.ctrloutput.ctrlindex);
router.get("/login",ctrl.ctrloutput.ctrllogin);
router.get("/register",ctrl.ctrloutput.register);
router.post("/login",ctrl.ctrlprocess.ctrllogin); // ← 
router.post("/register",ctrl.ctrlprocess.register);
module.exports = router;

====================

서버에 POST로 요청이 간다

router.post("/login", ctrl.ctrlprocess.login)

ctrl.ctrlprocess의 login함수 실행되었다

로그인 경로로 요청이 갔다 3:32

컨트롤러 파일에 가보면

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const User = require("../../models/User");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index");
    },
    ctrllogin: (req,res)=>{
        res.render("home/login");
    },
    register: (req,res)=>{
        res.render("home/register");
    },
};
const ctrlprocess = {
    ctrllogin: (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = user.login();	// ←
        // console.log(response);
        return res.json(response);
    },
    register: (req,res)=>{
        const user = new User(req.body);	// ←
        const response = user.register(); // ←
        return res.json(response);
    }
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

const process

register:

const user=new User(req.body)

여기서 유저인스턴스를 만들어서

const response=user.login()

user에 login메서드를 실행을 시켰다 3:41

 

유저클래스로 가서

app>src>models>User.js--------------------

"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {
        this.body = body;
    }
    login(){	// ←
        const client = this.body;
        const { id, psword } = UserStorage.getUserInfo(client.id);
        console.log(UserStorage.getUserInfo(client.id));
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client);
        return response;
    }
}
module.exports = User;

====================

login메서드가 실행이 되었으니까

const {id,psword}=UserStorage.getUserInfo(client.id) 메서드가 실행을 하고

 

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

getUserInfo 유저의 정보를 가져와서 Users.js로 반환을 해주었는데

해당 로직에서 구현해보자

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        fs.readFile("./package.json", (err,data)=>{	// ←
            if (err) throw err;
            console.log(data);
        });
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

fs.readFile("./") 현재 경로는 app.js가 있는 경로를 의미한다

그러면 여기서 package.json을 읽어보자

fs.readFile("./package.json")

두 번째 파라미터로 (err,data)

에러와 파일의 데이터를 읽어올 수 있다

이것은 콜백함수이다

에러가 나면

if (err) throw err;

해당 데이터를 출력해보자

console.log(data) 찍으면

LOGIN 버튼을 누르면 실행이 된다 4:37

 

서버 가동
ReferenceError: users is not defined

밑부분 주석처리해주자

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        fs.readFile("./package.json", (err,data)=>{
            if (err) throw err;
            console.log(data);
        });
        // const idx = users.id.indexOf(id);	// ← 주석처리
        // const usersKeys = Object.keys(users);
        // const userInfo = usersKeys.reduce((newUser, info)=>{
        //     newUser[info] = users[info][idx];
        //     return newUser;
        // },{});
        // return userInfo;
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

LOGIN 버튼을 누르면 실행이 된다

서버 가동
TypeError: Cannot destructure property 'id' of 'UserStorage.getUserInfo(...)' as it is undefined.

    at User.login

에러 난 부분이 User.login 이다

app>src>models>User.js파일에 가서

반환해주는게 없으니까 

const {id,psword}=UserStorage.getUserInfo(client.id)

따라서 UserStorage.getUserInfo(client.id) 이렇게 앞부분 받는거 없애주고

밑에 if문도 주석처리

app>src>models>User.js--------------------

"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    login(){
        const client = this.body;
        // const { id, psword } = UserStorage.getUserInfo(client.id);
        UserStorage.getUserInfo(client.id);
        // console.log(UserStorage.getUserInfo(client.id));
        // if(id){
        //     if ( id === client.id && psword === client.psword){
        //         return { success: true};
        //     }
        //     return { success: false, msg: "비밀번호가 틀렸습니다."};
        // }
        // return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client);
        return response;
    }
}
module.exports = User;

====================

LOGIN 버튼 누르면

서버 가동
<Buffer 7b 0a 20 20

 

이 버퍼데이터는 UserStorage.js 클래스에서

package.json 파일을 읽어서

fs.readFile("./package.json", (err, data) => {

파일을 읽어서 그 안에 들어있는 data

readFile로 읽어오면 데이터는 16진수로 표기되어 있다

데이터는 2진수로 읽게 되는데

우리한테만 16진수로 보여준다

해당 데이터를 조작해야 되는데

이 buffer데이터로는 조작할 수 없다

 

따라서 우리가 읽을 수 있는 형태로 가져와야 되는데

우리가 읽은 파일이 JSON파일이어서

package.json파일도 JSON형태로 되어있다

따라서 

console.log(JSON.parse(data)

해당 파일을 우리가 볼 수 있는 형태로 만들어주자

 

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        fs.readFile("./package.json",(err,data)=>{
            if (err) throw err;
            console.log(JSON.parse(data));	// ←
        });
        // const idx = users.id.indexOf(id);
        // const usersKeys = Object.keys(users);
        // const userInfo = usersKeys.reduce((newUser, info)=>{
        //     newUser[info] = users[info][idx];
        //     return newUser;
        // },{});
        // return userInfo;
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

cd app

npm start

192.168.1.65:3000/login

LOGIN

 

서버 가동
{
  dependencies: { 'body-parser': '^1.19.1', ejs: '^3.1.6', express: '^4.17.2' },
  name: 'login-lecture',
  version: '1.0.0',
  main: 'app.js',
  bin: { 'login-lecture': 'www.js' },
  scripts: {
    start: 'nodemon ./bin/www.js',
    test: 'echo "Error: no test specified" && exit 1'
  },
  keywords: [],
  author: '',
  license: 'MIT',
  description: ''
}

우리의 package.json 파일을 잘 읽어 올 수 있게 되었다

이렇게 파일을 읽어 오면 되는구나 알면 된다

 

데이터를 조작할 수 있게 되었다

 

그런데 우리가 읽어들여야 파일은 

fs.readFile("./package.json",

이 아니다

 

app>src>models>users.json

users.json 유저테이블을 읽어야 한다

이 파일에 접근할 수 있게 해주자

fs.readFile("./

이 경로 는 app>app.js가 있는 경로이다

fs.readFile("./src/databases/users.json,

MySQL 로 예를 들면

database명/table명

users.json 테이블이다

fs.readFile("./src/databases/users.json,여기의 파일을 읽어보자

여기부터@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        fs.readFile("./src/databases/users.json", (err,data)=>{
            if (err) throw err;
            console.log(JSON.parse(data));
        });
        // const idx = users.id.indexOf(id);
        // const usersKeys = Object.keys(users);
        // const userInfo = usersKeys.reduce((newUser, info)=>{
        //     newUser[info] = users[info][idx];
        //     return newUser;
        // },{});
        // return userInfo;
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

cd app

npm start

192.168.1.65:3000/login

LOGIN 버튼 클릭

서버 가동
{
  id: [ 'newstep', 'miero', '김팀장' ],
  psword: [ '1234', '1234', '123456' ],
  name: [ '뉴스텝', '미에로', '김팀장' ]
}

 

이 데이터를 통해서 로그인 로직을 처리해주면 된다

console.log(JSON.parse(data))를

const users=JSON.parse(data) 에 담고

밑 부분을 주석을 풀어주면

 

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        fs.readFile("./src/databases/users.json",(err,data)=>{
            if (err) throw err;
            const users = JSON.parse(data);
        });
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

cd app

npm start

192.168.1.65:3000/login

LOGIN 버튼

서버 가동
ReferenceError: users is not defined

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        fs.readFile("./src/databases/users.json", (err,data)=>{
            if (err) throw err;
            const users = JSON.parse(data);
            const idx = users.id.indexOf(id);
            const usersKeys = Object.keys(users);
            const userInfo = usersKeys.reduce((newUser, info)=>{
                newUser[info] = users[info][idx];
                return newUser;
            },{});
            return userInfo;
        });
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

cd app

npm start

192.168.1.65:3000/login

LOGIN 버튼

서버 가동
undefined

 

설명하기에 앞서서 app>src>models>User.js에 가서

UserStorage.getUserInfo(client.id)가 반환하는 게 뭔지 한 번 보자

app>src>models>User.js--------------------

"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {
        this.body = body;
    }
    login(){
        const client = this.body;
        console.log(UserStorage.getUserInfo(client.id));	// ←
        // if(id){
        //     if ( id === client.id && psword === client.psword){
        //         return { success: true};
        //     }
        //     return { success: false, msg: "비밀번호가 틀렸습니다."};
        // }
        // return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client);
        return response;
    }
}
module.exports = User;

====================

cd app

npm start

192.168.1.65:3000/login

LOGIN 버튼

서버 가동
undefined

 

왜 아무것도 반환하는 것이 없는가

실제 반환하는게 없다

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        fs.readFile("./src/databases/users.json", (err,data)=>{	// ← 콜백함수 시작
            if (err) throw err;
            const users = JSON.parse(data);
            const idx = users.id.indexOf(id);
            const usersKeys = Object.keys(users);
            const userInfo = usersKeys.reduce((newUser, info)=>{
                newUser[info] = users[info][idx];
                return newUser;
            },{});
            return userInfo;
        });	// ← 콜백함수 끝
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

const userInfo=만들어서

return userInfo 로 반환한다고 하는데

그것을 반환하는 것은 콜백함수이다

콜백함수 안에서 리턴해주는 것이다

따라서 getUserInfo가 리턴하는 걸 갖고 있어야 하는데

그러면 fs파일시스템이 가지고 있는 것을 리턴하면 될까

return fs.readFile...

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        // const users = this.#users;
        return fs.readFile("./src/databases/users.json", (err,data)=>{	// ←
            if (err) throw err;
            const users = JSON.parse(data);
            const idx = users.id.indexOf(id);
            const usersKeys = Object.keys(users);
            const userInfo = usersKeys.reduce((newUser, info)=>{
                newUser[info] = users[info][idx];
                return newUser;
            },{});
            return userInfo;
        });
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

cd app

npm start

192.168.1.65:3000/login

LOGIN 버튼

 

서버 가동
undefined

 

보면 콜백함수가 반환하는 거지

fs.readFile메서드가 반환하는 것은 아니다

어떻게 처리해야 될까

 

우선 주석부분 삭제하고

const users=this.#users 삭제

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs");
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        return fs.readFile("./src/databases/users.json", (err,data)=>{
            if (err) throw err;
            const users = JSON.parse(data);
            const idx = users.id.indexOf(id);
            const usersKeys = Object.keys(users);
            const userInfo = usersKeys.reduce((newUser, info)=>{
                newUser[info] = users[info][idx];
                return newUser;
            },{});
            return userInfo;
        });
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

이제부터가 어려울 수 있다 8:39

promise async await 이론들이 나온다

27[Node.js] 백엔드 맛보기 | 파일 DB로 로그인 구현 | promise와 async await 으로 비동기 최적화

app>src>models>UserStorage.js안에

static getUserInfo안에

return fs.readFile("./src/databases/users.json",(err,data)=>{

readFile 자체에서 promise를 제공하고 있다

그것을 받아와 올게요
const fs=require("fs")
                      이 파일 시스템을 require 할 때 여기에 점을

찍고 요 promise 라는 것을 불러 오면 되요

const fs=require("fs").promises

자 그러면 이제 이 파일 시스템은 promise를 반환을 하게 되는데요
static getUserInfo
return fs.readFile
유지보수 하기도 좋아지고 요 코드를 좀 더 읽기 좋은 코드 로 바꿔 주거든요

Promise는 약속이라는 의미로 Promise가 수행하는 동작이 끝남과 동시에

상태를 알려주기 때문에 비동기 처리에 아주 효과적입니다

일단은 이거를 promise를 반환 형태로 바꿔 볼게요
콜백 함수가 전체에 다 사라지고 요 일단은
여 첫번째 파라미터에 서 소 가로 로 분리 해 주고 이 밑에서 여기서
리턴 도 없애 줄게요 일단은 그리고 이게 프로미스 를 반 한다고 했잖아요
그러면 한번 커서를 찍어 볼게요 여건을 주석 처리를 해 주겠습니다
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;	// ←
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        console.log(fs.readFile("./src/databases/users.json"));	// ←
        // , (err,data)=>{
        //     if (err) throw err;
        //     const users = JSON.parse(data);
        //     const idx = users.id.indexOf(id);
        //     const usersKeys = Object.keys(users);
        //     const userInfo = usersKeys.reduce((newUser, info)=>{
        //         newUser[info] = users[info][idx];
        //         return newUser;
        //     },{});
        //     return userInfo;
        // });
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;
====================
cd app
npm start
 
서버 가동
Promise { <pending> }
undefined
저장을 하시고 새로운 팀에서 로그인을 누르면 Promise라는 것을 반환을 하죠
이 <panding>에 대해서는 이따 설명드릴께요 프로미스 를 반환하고
이 undefined
이 유저 클래스에서 콘솔 에서 나오는 겁니다
app>src>models>User.js 안에 
login
console.log(UserStorage.getUserInfo(client.id))
 
일단은 console.log 지워줄게요
app>src>models>User.js--------------------
"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    login(){
        const client = this.body;
        // const { id, psword } = UserStorage.getUserInfo(client.id);
        UserStorage.getUserInfo(client.id);	// ←
        // if(id){
        //     if ( id === client.id && psword === client.psword){
        //         return { success: true};
        //     }
        //     return { success: false, msg: "비밀번호가 틀렸습니다."};
        // }
        // return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client);
        return response;
    }
}
module.exports = User;
====================
그리고 사실 이동을 해서
app>src>models>UserStorage.js 안에
static getUserInfo 안에
fs.readFile 메서드가 프로세스를 반환한다라는 걸 알았어요
이전에도 말씀 드렸었는데 promise를 반환을 하게되면 then이라는
메서드의 접근 할 수 있게 되요
fs.readFile("./
.then()
그리고 마찬가지로 promise를 반환하는
것에 대한 오류 처리는 catch 라는 걸로 해 줄 수 가 있었어요
fs.readFile("./
.then()
.catch()
그렇죠 그 fetch api의 기억하시나요
프론트엔드 에서 서버에게 데이터 요청할 때 했던
fetch api 기억하시죠 이 fetch api 가 바로 promise를 반환했는데요
그거랑 동일하다고 보시면 되요
 
일단 then은요 해당을 로직이 성공했을 때 실행되는 애구요
 
catch는 실패했을 때 에러가 났을 때 실행되는 애에요
 
자 그러면 이걸 주석 풀어서 한 번 볼게요
 
이전에 readFile에서 두번째 파라미터로 넘겼던 애인데요
 
여기에 에러와 데이터를 콜백으로 넘겼어요
 
근데 promise는 에러가 발생할 때의 catch가 실행되고
성공적일 때는then이 실행되기 때문에 에러를 catch해서 일단 받을 수가 있어요
그래서 애
러 해서 여기서는 console.error로 에러를 던져 볼게요
.catch((err)=>console.error(err))
근데 말씀드렸다시피 함수를 실행시키는 데 파라미터로 넘어온 변수를 실행시키는
함수로 똑같이 넘기게 되면 은 이거는 생략을 해줄 수가 있다고 했죠
.catch(console.error)
이처럼 생략을 해줄 수 있구요
그리고 이 data는 
,(err,data)=>{
이 then 에서 받아요
fs.readFile(
.then()
성공적인 때 실행되는 거니까요 데이터를 받아서요
. then((data)=>{
이 해당 로직을 일단 로직을 복사
해서 가져올게요 들여쓰기 정리해 주시고 밑에는 것은 삭제 해 주도록
할게요 저장해 보시면은 우리 없이 잘 가동이 되죠
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        fs.readFile("./src/databases/users.json")
            .then((data)=>{
                const users = JSON.parse(data);
                const idx = users.id.indexOf(id);
                const usersKeys = Object.keys(users);
                const userInfo = usersKeys.reduce((newUser, info)=>{
                    newUser[info] = users[info][idx];
                    return newUser;
                },{});
                return userInfo;
            })
            .catch(console.error);
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;
====================
아까보다는 훨씬 깔끔해 보여요 가독성이 좋아졌을 뿐 퇴행 않은 동작에는 변함이 없거든요
서버를 제가 동화 시공 부품을 로그인을 눌러 보면
지금 에러가 나오네요
서버 가동
ReferenceError: id is not defined
at User.login
에러가 났어요
그러면 유저 클래스를 가볼게요
app>src>models>User.js안에
clase User 클래스에서
UserStorage.getUserInfo(client.id)
이 UserStorage.getUserInfo 메서드가 반환하는 게 뭔지 한번 볼게요
console.log(UserStorage.getUserInfo(client.id))
에서 보면은
app>src>models>User.js--------------------
"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    login(){
        const client = this.body;
        console.log(UserStorage.getUserInfo(client.id));
        // if(id){
        //     if ( id === client.id && psword === client.psword){
        //         return { success: true};
        //     }
        //     return { success: false, msg: "비밀번호가 틀렸습니다."};
        // }
        // return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client);
        return response;
    }
}
module.exports = User;
====================
LOGIN 을 눌렀을 때 undifined 가 나와요
아 반환을 하지 않았죠
일단 UserStorage.js로 넘어가서 파일 시스템을 반영을 해 줄게요
static getUserInfo(id){
return fs.readFile(
 
아까 말씀드렸다시피
이 readFile은 이제 promise를 부여를 해줬기
const fs=require("fs").promises 제일 윗부분
때문에 promise를 반환하는 애가 됐어요
저장을 해서 로그인을 누르면
dl getUserInfo(id) 가 반환하는 애가 프로미스 라는 걸 알게 됐어요
return fs
저희가 원하는 것은 이 만들어진
const userInfo=
데이터가 있잖아요
이 userInfo 데이터를 반환 하고 싶어요
console.log(userInfo)를 출력을해 볼게요 저장하고
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;	// ←
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        return fs	// ←
        .readFile("./src/databases/users.json")
        .then((data)=>{
            const users = JSON.parse(data);
            const idx = users.id.indexOf(id);
            const usersKeys = Object.keys(users);
            const userInfo = usersKeys.reduce((newUser, info)=>{	// ←
                newUser[info] = users[info][idx];
                return newUser;
            },{});
            console.log(userInfo);	// ←
            return userInfo;
        })
        .catch(console.error);
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;
====================
홀로그램 들으면 점하고 로그인을 누르면 지금
npm start
서버 가동
Promise { < pending >}
{id:undefined,psword:undefined,name:undefined}
가 나오는데
그래서 아이디miero를 입력하고 로그인을 누르면 이 해당 데이터를 파일에서 읽어와서 반환을 해 주잖아요
그래서 이 데이터를 반환을 해주고 싶은데 이 promise는 객체만 단순하게 반환을 해주고 있어요
자 이제는 이 < pending >에 대해서 설명을 드릴 때가 되는데요
이 < pending >은 요
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        return fs
        .readFile("./src/databases/users.json")
        .then((data)=>{
            const users = JSON.parse(data);
            const idx = users.id.indexOf(id);
            const usersKeys = Object.keys(users);
            const userInfo = usersKeys.reduce((newUser, info)=>{
                newUser[info] = users[info][idx];
                return newUser;
            },{});
            console.log(userInfo);
            return userInfo;
        })
        .catch(console.error);
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;
====================
데이터를 전부 읽어보지 못했다 라는 뜻이에요
다시 유저 스스로 넘어 갈게요
app>src>models>User.js
promise 라는 것을 반환하는 에는 요
console.log(UserStorage.getUserInfo(client.id))
일반적으로 시간이 다소 소요가 되요
따라서 그 promise 데이터를 다 읽어 오지 못했다 라고 말씀을 드렸는데요
어떻게 이 파일 시스템이 해당 파일을 읽어서 반환하는
return userInfo있잖아요 userInfo를 반환하기 전에
app>src>models>User.js의
이 class User 클래스가
login(){
console.log
콘솔로 console.log(UserStrorage.getUserInfo(client.id)
얘를 찍어 버린 거에요
 
그러니까 이 데이터를 반환 하지 않았는데 출력이 된거죠
이게 바로 비동기적으로 동작하기 때문인데요
node.js의 장점 인거죠
여러분 그러면 데이터를 다 읽어 올 때까지 이것들이 실행
되면 안되잖아요
console.log(UserStrorage.getUserInfo(client.id)
따라서 데이터를 다 읽어 올 때까지 기다리라고 얘기를 해줘야 되요
이 코드 한테 어떻게 하냐 그거 한 바로 await 이라는 걸 해줄 수 있는데요
console.log(await UserStorage.getUserInfo(client.id))
이 await 같은 경우는 항상 promise를 반환 하는 애한테 만 해 줄 수 있어요
그 기억하세요
Promise를 반환하기 때문에
.then()으로도 접근하여 데이터를 가져올 수 있습니다.
await을 사용해준 이유는 "가독성" 입니다.
fs파일시스템에서도 await으로 가져올 수 있습니다.
본인의 개발 성향에 맞춰 해주시면 됩니다
await은 promise를 반환하는 애 한테 주는 옵션이 구나 라고 생각하세요
console.log(await UserStorage.getUserInfo(client.id))
그런데 이 상태로 저장을 하면 요 오류가 나요 왜냐 왜냐하면
이 await 같은 경우는 아무데서나 쓸 수가 없어요 쓸 수 있는 것이 한정적입니다
그것은 바로 async 라는 함수 안에서만 사용을 할 수 있는데요
따라서 이 login이 라는 함수 안에서 사용할 거기 때문에 이 함수를 async 하게 바꿔 줘야 돼요
async login()
app>src>models>User.js--------------------
"use strict";
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {
        this.body = body;
    }
    async login(){	// ←
        const client = this.body;
        console.log(await UserStorage.getUserInfo(client.id));	// ←
        // if(id){
        //     if ( id === client.id && psword === client.psword){
        //         return { success: true};
        //     }
        //     return { success: false, msg: "비밀번호가 틀렸습니다."};
        // }
        // return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client);
        return response;
    }
}
module.exports = User;
====================
지금 그 async 함수로 비동기 함수 로 바꿔 줘야 돼요
제 상태를 저장을 하면
이제 문제없이 서버 가동이 되죠
cd app
npm start
 
서버 가동
{ id: 'miero', psword: '1234', name: '미에로' }
{ id: 'miero', psword: '1234', name: '미에로' }
 
새로고침 하고 우린 miero 로그인 딱 눌렀을 때 해당 데이터를 잘 가져오는 것을 알 수가 있죠
팝업창 undefined
이 undefined는 이 async login()함수가 반환하는 애가 없어서 뜨는 겁니다
자 이제 됐으니까
이 console.log 를 버려 줄게요
await UserStorage.getUserInfo(client.id)
앞에다가 처음에 있던 const {id,psword}로 이 해당 데이터들을 가져보도록 할게요
const {id,psword}=await UserStorage.getUserInfo(client.id)
밑에 if문을 주석 풀어주며 는 정상적으로 동작하겠네요
app>src>models>User.js--------------------
"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");	// ???
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){	// ←
        const client = this.body;
        const {id,psword} = await UserStorage.getUserInfo(client.id);	// ←
        if(id){	// ← 주석 풀고
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client);
        return response;
    }
}
module.exports = User;
====================
 
새로고침

서버 가동
{ id: 'miero', psword: '1234', name: '미에로' }

그래서 miero를 누르면 undefined가 또 출력이 되요 왜일까요
왜냐하면 이 컨트롤러 때문인데요 app>src>routes>home>home.ctrl.js
자 일단 이 유저를 나눠서 볼게요 app>src>models>User.js
두 개로
이렇게 나눠서 보고  app>src>models>User.js에
이 async login에 저희는 이 getUserInfo는 메서드가
const {id,psword}=await UserStorage.getUserInfo(client.id)
시간이 오래걸려서 getUserInfo애가 다 수행될 때까지 기다려 라고 해 줬어요
근데 정작 그렇다면 이 async login() 함수가 실행되는 데에도 시간이 오래 걸리겠죠
따라서 이 async login()을 실행하는 애한테 도 async await을 걸어줘야 되요
얘를 실행하는 애는 이 app>src>routes>home>home.ctrl.js컨트롤러의
const process={
login:
const response=user.login()
얘 잖아요
그래서 얘한테 await을 걸어줘야 되요
const response=await user.login()
async await함수는 자체적으로 Promise를 반환해주도록 되어있습니다.
따라서 await을 적용해 줄 수 있는 것입니다.
그리고 await은 async 함수 안에서만 동작한다 있으니까 async도 걸어줘야 합니다
app>src>routes>home>home.ctrl.js--------------------
"use strict";
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login");
    },
    register: (req,res)=>{
        res.render("home/register");
    },
};
const ctrlprocess = {
    ctrllogin: async (req,res)=>{	// ←
        const user = new User(req.body);
        const response = await user.login();	// ←
        return res.json(response);
    },
    register: (req,res)=>{
        const user = new User(req.body);
        const response = user.register();
        return res.json(response);
    }
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};
====================
함수 앞에서 걸어줘야 되요 자 이렇게 걸어 주고요 저장 누르고 다시 한번 보겠습니다 
cd app
npm start
 
192.168.1.65:3000/login
miero 1234
LOGIN 누르면 

서버 가동
{ id: 'miero', psword: '1234', name: '미에로' }

이제는 정상적으로 저희가 원했던 거 나옵니다
없는 id입력하면 로그인 하면 존재하지 않는 아이디라고 나오죠
miero 1234
로그인을 해 볼게요 정상적으로 처리가 됐습니다
 
지금 이제 콘솔로 계속 시작되니까 이 커널을 출력했던 애가
app>src>models>UserStorage.js잖아요
거기서 console을 지워 주도록 할게요
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        return fs
        .readFile("./src/databases/users.json")
        .then((data)=>{
            const users = JSON.parse(data);
            const idx = users.id.indexOf(id);
            const usersKeys = Object.keys(users);
            const userInfo = usersKeys.reduce((newUser, info)=>{
                newUser[info] = users[info][idx];
                return newUser;
            },{});
            // console.log(userInfo);	// ←
            return userInfo;
        })
        .catch(console.error);
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;
 ====================
이 UserStorage 에 해당 코드를 보면 뭔가 지저분 하죠
조금 가독성 좋은 코드로 만들어 줄게요
then부분을 하나의 함수로 빼겠습니다
잘라내기 해주시고요
 
return으로 바로 해당 값을 반환을 해줄 건데
그 해당 값을 반환하는 함수를 만들어 줄게요
저희는 static으로 은닉화된 변수를 만들게요
이렇게 static #getUserInfo 변수명은 동일하게 해줬구요
 
그리고 여기다 복사 붙여 넣기 해 줄게요 들여쓰기 맞춰주시고
static #getUserInfo얘가 반환하는 애는
return userInfo 가 될거니까
static getUserInfo(){
return fs
.readFile
.then((data)=>{
return this.#getUserInfo()
return에서 여기서 this.이렇게 은닉화된 메서드를 호출을 할 거에요

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs").promises;
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        return fs
        .readFile("./src/databases/users.json")
        .then((data)=>{
            return this.#getUserInfo();	// ←
        })
        .catch(console.error);
    }
    static #getUserInfo() {	// ←
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;
 ====================
static getUserInfo얘랑 static #getUserInfo얘는 다른 애입니다
단순히 가독성을 좋게 하기 위해서 분리를 해 준 거에요
지금 보면 은 이 static #getUserInfo()함수에서 실제 데이터를 만들어서 던져 주니까요
static getUserInfo(id){
return fs
.readFile
.then((data)=>{
data까지 던져 줘야죠
return this.#getUserInfo(data)
data 던져 주고
id 값도 던져 줘야죠 
static getUserInfo(id){
이 파라미터 클라이언트의 id 값이
.then((data)=>{
return this.#getUserInfo(data,id)
저거 또 던져줘야 합니다 그래서 동일하게 받을 수 있도록
static #getUserInfo(data,id){하고요
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){	// ←
        return fs
        .readFile("./src/databases/users.json")
        .then((data)=>{
            return this.#getUserInfo(data, id);	// ←
        })
        .catch(console.error);
    }
    static #getUserInfo(data, id) {	// ←
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;
====================
이 상태로 실행을 하면 동일하게 동작합니다 동작을 하죠
이렇게 해가지고 조금 가독성 있게 바꿔줬는데요
이렇게 private한 변수나 메서드는 요 항상 최상단에 올려 줘야 돼요
클래스의 이렇게 최상단으로 올려 주겠습니다
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static getUsers(...fields){
        // const users = this.#users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            };
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUserInfo(id){
        return fs
        .readFile("./src/databases/users.json")
        .then((data)=>{
            return this.#getUserInfo(data, id);
        })
        .catch(console.error);
    }
    static save(userInfo){
        // const users = this.#users;
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        return { success: true };
    }
};
module.exports = UserStorage;

====================

이것이 컨벤션 이에요 코딩 문화죠 암묵적으로 수많은 개발자들이 이렇게 개발을 하고 있습니다
다음 시간에는 이 파일 시스템을 이용해서 회원과의 로직을 처리해 보도록 할게요
지금까지 한거 저장 해 주시고 서버 꺼주시고 깃허브에 업로드할게요
git add .
git commit -m "fs모듈을 통한 로그인 기능 구현"
git push origin master
 
 

28[Node.js] 백엔드 맛보기 | 파일 DB로 회원가입 구현 | promise와 async await 으로 비동기 최적화

데이터가 초기화 되지 않기 때문에 실제 데이터베이스와 유사하게
데이터를 저장할 수가 있게 됩니다
이번 시간에는 요 프론트브라우저에서 해당 데이터를 정상적으로 입력하고 SIGN UP을 누르게 될 때 서버 에서
이 해당 데이터를 파일에 저장하는 회원가입 로직을 구현을 해볼건데요
이 SIGN UP을 버튼을 누르게 될 때 포스트로 요청이 가게 되잖아요
192.168.1.65:3000/register
해당 라우팅을 살펴볼게요 app>src>routes>home>index.js를 보면요
app>src>routes>home>index.js--------------------
"use strict"; //ecma script 준수하겠다
const express = require("express");
const router = express.Router();
const ctrl = require("./home.ctrl");
router.get("/",ctrl.ctrloutput.ctrlindex);
router.get("/login",ctrl.ctrloutput.ctrllogin);
router.get("/register",ctrl.ctrloutput.register);
router.post("/login",ctrl.ctrlprocess.ctrllogin);
router.post("/register",ctrl.ctrlprocess.register); // ←
module.exports = router;
====================
 
router.post("/register", ctrl.ctrlprocess.register)
여기에 레지스터 경우에 퍼스트 를 요청해 오면
해당 ctrl.ctrlprocess.register함수가 실행이 되도록 되어 있구요
 
컨트롤러 폴더 이동을 했어요
app>src>routes>home>home.ctrl.js 안에 레지스트 함수를 보면
app>src>routes>home>home.ctrl.js--------------------
"use strict";
const User = require("../../models/User");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index");
    },
    ctrllogin: (req,res)=>{
        res.render("home/login");
    },
    register: (req,res)=>{
        res.render("home/register");
    },
};
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.login();
        return res.json(response);
    },
    register: (req,res)=>{
        const user = new User(req.body);
        const response = user.register(); // ←
        return res.json(response);
    },
};
module.exports = {
    ctrloutput,
    ctrlprocess,
};
====================
const ctrlprocess = {
login:
register:(req,res)=>{
const response=user.register()
클래스 안에 레지스터 메서드user.register()가 실행되도록 되어 있습니다
 
다시 유저 클래스를 가서요
app>src>models>User.js 안에
app>src>models>User.js--------------------
"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        const {id,psword} = await UserStorage.getUserInfo(client.id);
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client); // ←
        return response;
    }
}
module.exports = User;
====================
레지스터 메소드를 보면
register(){
여기서 UserStorage에 save 메서드를 호출하도록 되어 있습니다
const response=UserStorage.save(client)
마지막으로 app>src>models>UserStorage에서 보면은
app>src>models>UserStorage--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUsers(data, isAll, fields);
             })
            .catch(console.error);
            // const users = JSON.parse(data);
            // if (isAll) return users;
    }
    static getUserInfo(id){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUserInfo(data, id);
            })
            .catch(console.error);
    }
    static save(userInfo){
        // ←
    }
}
module.exports = UserStorage;
====================
이 세이브 로직이 수행이 되는데요
static save(userInfo){
해당 로직은 필요없으니까 다 지워져 도록 하겠습니다
이제 실제 로직을 구현 할껀데요 파일에 데이터를 쓰기 위해서는
fs.writeFile()이 라는게 있어요
첫번째 파라미터로 는 저장을 파일의 경로를 입력해 주시면 되고요
두번째 파라미터로 는 저장할 데이터를 입력해 주시면 됩니다
fs.writeFile("./src/databases/users.json",data)
일단은 이 테이터 안에 a 라는 문제 얼만 넣어볼게요
const data="a"
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUsers(data, isAll, fields);
             })
            .catch(console.error);
    }
    static getUserInfo(id){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUserInfo(data, id);
            })
            .catch(console.error);
    }
    static save(userInfo){
        const data = "a";  // ←
        fs.writeFile("./src/databases/users.json", data);  // ←
    }
}
module.exports = UserStorage;
====================
주의 하셔야 될 게 있는데요
이렇게 해서 a 라는 문자열을 저장을 하게 되면요
이 app>src>databases>users.json라는 파일에 "a" 가 전체가 다 쓰여져서 이 "a"만 저장이 되요
일단 확인만 좀 해볼게요 이 파일이 어떻게 변화 되는지 보자구요
cd app
npm start
192.168.1.65:3000/register
일단은 데이터를 입력을 하고요 비밀번호 1234 1234 입력을 했더니 비밀번호가 일치하지 않대요
저도 똑같이 입력 했거든요 근데 일치하지 않는다고 해요
 
왜 그런지 찾아봤는데요
이 프런트 엔드 자바스크립트 파일에서 제가 조금 실수한 게 있더라구요
app>src>public>js>home>register.js 파일에 보면 이 psword란 confirmPsword를

app>src>public>js>home>register.js--------------------

'use strict';
const id = document.querySelector("#id"),
    name = document.querySelector("#name"),
    psword = document.querySelector("#psword"),
    confirmPsword = document.querySelector("#confirm-psword"),
    registerBtn = document.querySelector("#button");
registerBtn.addEventListener("click", register);
function register(){
    if (!id.value) return alert("아이디를 입력해주십시오.");
    if (psword.value !== confirmPsword.value)	// ←
      return alert("비밀번호가 일치하지 않습니다.");
    const req = {
        id: id.value,
        name: name.value,
        psword: psword.value,
    };
    fetch("/register", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())
      .then((res) => {
        if(res.success){
          location.href = "/login";
        } else {
          alert(res.msg);
        }
      })
      .catch((err) => {
        console.error("회원가입 중 에러 발생");
      });
};

====================

비교하는데 지금 이 태그 자체를 비교하고 있어요
따라서 이 태그 안에 에 입력된 value를 비주얼 해주도록 처리를 해 주도록 할게요
이렇게 저장을 해 줬구요
다시 따라서 이 파일이 이젠 동작을 할 거에요
어떻게 변화되고 인지 보자구요 프런트 엔드의 자바스크립트 파일을 반영을 했었으니까요
새로고침 을 해주셔야 되요
nextlevel을 저장해볼게요 1234 1234
SIGN UP
화면은 지금 동작 했어요
a 가 완전 덮어씌워 같잖아요
app>src>databases>users.json--------------------
a​
====================
다시 돌릴 게요
app>src>databases>users.json--------------------
{
    "id":["newstep","miero","nextlevel"],
    "psword":["1234","1234","123456"],
    "name":["뉴스텝","미에로","넥스트레벨"]
}​
====================
 
이처럼 바로 데이터를 넣어 버리면 안되요
어떻게 해야되냐
app>src>databases>users.json이라는 파일에 데이터를 읽어 온 다음에
그 데이터에 저희가 추가하고 싶은 데이터를 추가한 뒤에 데이터를 넣어 줘야 합니다
따라서 그 과정을 해 줄 건데요
저희는 이미 유저 쓰라는 데이터를 모두 다 불러오는 메서드를 만들었어요
이 app>src>models>UserStorage.js 안에 static getUsers라는 메서드를 만들었잖아요
저희는 이 static getUsers메서드를 이용해주도록 할게요
app>src>models>UserStorage.js--------------------
    static getUsers(...fields){
        const newUsers = fields.reduce((newUsers, field) => {
            if (users.hesOwnProperty(field)) {
                newUsers[field] = users[field];
            }
            return newUsers;
       }, {});
       return newUsers;
    }
	static getUserInfo(id){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUserInfo(data, id);
            })
            .catch(console.error);
    }
    static save(userInfo){
        const users = this.getUsers("id","psword","name");  // ←
        // 데이터 추가
        fs.writeFile("./src/databases/users.json", users);  // ←
    }
====================
컨 스트릿 열쇠라고 하구요 거기에 캔유 절 스 라는
메서드에서 모든 파라미터를 모든 파라미터를 다 바다와 주도록 할게요
이렇게 하면 데이터를 오브젝트 형태로 반환 해서 애가 가지고 있을 거에요
거기에 데이터를 추가한 다음에 추가된 유저 c 데이터를 여기에 넣어줘야
해요
작은데 지금이 메써드 를 보면요 파일 시스템으로 접근하는 게 아니잖아요

 

따라서 그렇게 바꿔서 개요
저희가 지난 시간에 만졌던 이 static getUserInfo로직을 그대로 복사해서
 
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUsers(data, isAll, fields);
             })
            .catch(console.error);
            // const users = JSON.parse(data);
            // if (isAll) return users;
    }
    static getUserInfo(id){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUserInfo(data, id);
            })
            .catch(console.error);
    }
    static async save(userInfo){
        // const users = await this.getUsers("id","psword","name");  // ←
        const users = await this.getUsers(true);  // ←
        console.log(users);
        // 데이터 추가
        fs.writeFile("./src/databases/users.json", JSON.stringify(users));  // ←
        // fs.writeFile("./src/databases/users.json", data);  // ←
    }
}
module.exports = UserStorage;
====================
여기에

 

복사 해 주도록 하겠습니다 그리고 프라이빗한 메소드를 하나 더 만들어 줄
건데요 캔 유저 쓰 열고 만들어 주고요
맥스 들을 추가해 줄게요 프라이빗한 걸로 만들어 주시구요
static #getUsers
로직이 수행 되는것은 얘 니까요 예를 그대로 복사해서 이건 숙제 하고요

 

여기에 차갑게 해 주겠습니다 그리고 이제 파라미터를 던져야 되는데
데이터를 던지게 있구요 이 id 가 아니라 세일즈 를 넘겨야 되니깐
쉬지를 넘길 께요
그리고 동일하게 파라미터를 받아올 수 있도록 처리해 주시고 지금 이
데이터 라는 변수의 담겨 있는 값은 버퍼 데이터에 요 따라서 여기서
이처럼 데이터 e 파라미터에 데이터를 하씨 회사 우리가 다르신 등 데이터
로 바뀐 것을 유절 사안에 넣었구요 이제 정상적으로 동작을 할 거에요
저장을 하시고 여기 유절 쇠 뭐가 담게 된 지 보도록 하겠습니다 쌓인 업
누르시면 은 매력 아 떴는데
이 에러는 일단 무시 하시구요 지금 프로 미스를 애가 가지고 있어요 져
씨가 내 팬 딩 상태 잖아요 아직 데이터를 다 읽어보지 못했다 라는거
라고 말씀을 드렸었죠 따라서 여기서도 oa 3 걸어 주시고요
여기서도 이제 이어 회의에서 너 싱크 함수 안에서만 동작이 가능하다 고
말씀 드렸잖아요 따라서 세이브 에 터치 잉크를 다 주도록 할게요
이렇게 한 저장을 하고 다시 한번 사이즈를 누르면 이번에는 데이터를 잘
가져왔어요
어 그런데 지금 타입 에러가 발생을 했는데요 읽어보니까 데이터 인자는
되어야만 한다
문제 10 타입과 문자열 타입 혹은 버퍼 비슷한 스타일이 되어야 한데요
따라서 이 유저수 오브젝트를 문제 10 타입으로 바꿔 줄 건데 오브젝트를
재미있은 형태로 저장을 할 거니까요 제이스 점
3d 파이로 문자열 형태로 바꿔 주도록 하겠습니다 자 이제 데이터가 잘
저장이 될 건데요 저장되는 확인하게 전에 2캔 유저수 메서드를 조금 더
바꿔 줄게요
이처럼 모든 필드에 데이터를 다 가져오고 싶을 때가 있잖아요 그럴때 마다
이렇게 모든 필드 명을 다 입력하게 는 귀찮으니까 그냥 파라미터로 틀어
라고 입력을 해 주게 되면 모든 데이터를 가져오도록 바꿔 줄게요
어 그럼 여기서 파라미터를 하나도 받을 건데요 첫 번째 파라미터로 록 2
10월 이라고 하고요
자 e 절이라 한 벌을 받아 보고요 이제 오늘도 똑같이 던져 주는데
두번째 파라미터로 던져 줄게요 그래서 이제 올 이렇게 떠나 줬구요 그리고
여기서도 마찬가지로 데이터를 받아 봐야 겠죠
이즈 뭘 이렇게 받아오고 요 이수로 이제 우리 투르 면 바로 리턴을
생각했기
요 유절 쇠를 이렇게 만들면 여기서 호출할때 개 뉴스에 툴을 넣어 줬잖아
요 그러면은 모든 모든 값을 다 가져오게 따라 는 의미인 거구요 해서
모든 데이터를 답안을 해줄 거에요
다시한번 유저 스 데이터를 볼게요 저자는 에서 서버 재가동 해주시고
컨설로그의 유저 스 데이터가 담게 된 지 확인을 해 볼게요 자 일단 타
담겨져 이 담겨질 거에요 그리고 지금 제이슨의 스트링 디파이 문자열로
저장을 하니까 실제 데이터도 저장이 될 겁니다
자 그러면 이 유저 쓰 테이블이 데이터가 어떻게 변화 되는지 안 보자구요
싸인 아베 눌러 붙게 123 어때요 지금 데이터가 타 낀 거에요
바뀐 겁니다06:07
 
근데 제가 읽어 들인 데이터를 그대로 저장 했기 때문에
데이터가 똑같이 저장이 된 건데요 지금 저장이 되는 순간 이 users.json파일들이
한줄로 표시가 됐는데
저같은 경우는 익스텐션을 설치 해 가지고
어떠한 단축키를 누르면 이렇게 바로 이쁘게 정렬이 되어 이것도 있다가
설명을 드릴게요 없다는 유저 스토리지로 다시 넘어 가셔서요
app>src>models>UserStorage.js--------------------
 
====================

 

여기 이유 절세의 이번엔 데이터를 추가해 보도록 하겠습니다
2% 유절 스의 id 필드에 먼저 클라이언트가 입력한 데이터가
데이터베이스 유저수 테이블에 존재하는 id 인지를 봐 줄게요
자 따라서 이렇게 해 주시고요 그러면은 클라이언트가 입력한 유저 정보의
아이디가 이 데이터베이스에 아이리 안에 포함되어 있지 않으면 파일에
데이터를 저장 해 주도록 하겠습니다
이렇게요 자 이제 저장을 해줘야 겠죠 이런식으로 해주면 되는데요
4 더 작성이 완료 되었구요 이 테이블에 있는 id 필드에 유저인 후에
id 값을 저장하고 네임은 내 임 저장하고 이런식으로 패스워드 까지
저장을 하게 됩니다 실제로 이렇게 저장이 되고 나왔어 저장된 데이터를
유저 스르르 케이스 스트링에 파일을 통해서 저장하게 되는 거고요
이 저장이 완료되면 은 이 메서드는 아무것도 판단하지 않아요 오류가 났을
때만 에러를 그냥 던져 버립니다
따라서 여기서 반환 을 해 주도록 할게요 성공하면 은 썩 섹스의 툴을
반환 해 주도록 하고 데이터베이스에 이미 존재하는 id 1 경우에는
위치를 좀 바꿔 줄까요 이거를 그냥 조건문 밖으로 빼 줄게 그리고 자 이
낫을 없애서 유저 안에 이미 id 가 존재하며 는 여기서 리턴 6 에러를

 

이렇게 에러를 만들어서 요 바다는 해 주도록 하겠습니다

app>src>models>UserStorage.js--------------------

"use strict";
const fs = require("fs").promises;
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUsers(data, isAll, fields);
             })
            .catch(console.error);
            // const users = JSON.parse(data);
            // if (isAll) return users;
    }
    static getUserInfo(id){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUserInfo(data, id);
            })
            .catch(console.error);
    }
    static async save(userInfo){
        // const users = await this.getUsers("id","psword","name");  // ←
        const users = await this.getUsers(true);  // ←
        if (users.id.includes(userInfo.id)){
            return new Error("이미 존재하는 아이디입니다.");
        }
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        fs.writeFile("./src/databases/users.json", JSON.stringify(users));  // ←
        return { success: true };
    }
}
module.exports = UserStorage;
====================
 
자 그리고 다시
app>src>databases>users.json 파일 왔어요
여기서 이 aaa라는 아이디로 저장을 해 볼게요
SIGN UP 누르면 지금 aaa 추가가 됐죠
이제 정리 해서 볼게요
aaa 라는게 저의 추가됐습니다
app>src>databases>users.json--------------------
{"id":["newstep","miero","nextlevel","aaa"],"psword":["1234","1234","123456","1234"],"name":["뉴스텝","미에로","넥스트레벨","에에에"]}
====================
 
자 이제 여러분한테 더 이거 깔끔하게 볼 수 있는 익스텐션을 알려드릴게요
자 여기 익스텐션 으로 가시면 요
여기에 JSON Pretty라고 입력을 하시면 여기 JSON Pretty Printer 라고 있어요

이거 를 인스톨 해 줘 보세요 그런 다음에 바로 되는게 아니에요

이것을 설정을 해줘야 되는데 자 데이터가 이렇게 있을 때요 ctrl + p
windows는 ctrl + p 를 누르면 여러 한창 이 나오고요 ctrl + shift + p 를 눌러도 나옵니다
약간 조금씩 다르긴 한데 설명해드릴께요 여기 설정 창에 가셔서 하셔도
되요 이 맨위에 command palette 있죠
여걸 눌러 보셔도 이렇게 나오는데요 지금 여기 꺽쇠 의 표시가 있잖아요
그냥 이 화면에서 커맨드 에피를 누르면 꺽쇠 표시가 없는 걸로 나와요
상관없습니다 저희가 입력하면 되요
그래서 저희가 설치한 익스텐션 json pretty print를 선택을 해 줄 건데요
이처럼 나오지 않으시는 분은 입력하면 되요 json pretty print 이렇게 입력하면 나오니까요
이건 선택을 하시면 이처럼 적용이 됩니다 저는 단축키로 설정을 해 줬는데요 어떻게 하자면요
json pretty print 에서 이 설정 아이콘을 클릭을 하셔서 요
여기서 이 연필(+)을 눌러주세요 이제 이 상태에서 단축키를 눌러 주시면 되는데
저는 바로 ctrl + shift + j 를 눌러 줬어요
 
여러분들이 원하는
단축키를 입력하시면 되고 엔터 눌러주시면 여기 단축키가 등록이 된겁니다
네 이제 그 단축키 눌러보시면 커맨드 시프트 키 누르면 이처럼 익스텐션
이 잘 적용이 됩니다
다시 app>src>models>UserStorage.js로 왔어요
app>src>models>UserStorage.js--------------------
 
====================
데이터가 정산 저장이 되고 나면 은 파일의
해당 데이터를 저장을 하게 되죠 그리고 싹 쓱 틀어 라는 오브젝트를 반환
을 해주게 됩니다 저희가 베러 핸들링을 해줘야 하는데요 어떻게 해주는지
알려드릴게요 반값으로 에러를 던지고 요 또 여기서 에러가 발생할 때
여기서 처리를 해줄 수도 있는데 저는 2
그저 해서 해 줄게요 어떻게 하냐면 에러 처리 해 주려고 보니까 지금
여기에 await 처리가 안되어 있네요

app>src>models>User.js--------------------

"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        const {id,psword} = await UserStorage.getUserInfo(client.id);
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    register() {
        const client = this.body;
        const response = UserStorage.save(client);
        return response;
    }
}
module.exports = User;
====================
2 해당 데이터를 스토리지에 저장하는 데 그 시간이 오래 걸리니까 요
모두 저장할 때까지 기다리라고 await의 이슬 얘도 덜어 줘야 합니다
그리고 얘도 async register 걸어 주시구요 
app>src>models>User.js--------------------
"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        const {id,psword} = await UserStorage.getUserInfo(client.id);
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    async register() {
        const client = this.body;
        const response = await UserStorage.save(client);
        return response;
    }
}
module.exports = User;
====================
마찬가지로 컨트롤러로 가셔서 얘도 async register
 
5 해주죠 왜 이 그리구 어제 크를 걸어 주도록 하겠습니다 이렇게 하면
되구요
app>src>routes>home>home.ctrl.js--------------------
"use strict";
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {
    ctrlindex: (req,res)=>{
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        res.render("home/register"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = await user.login();
        // console.log(response);
        return res.json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register(); // ←
        // console.log(response);
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};
====================

에러 처리는 어떻게 하냐면 요

이런 async await 같은 경우는 try-catch 로 할 수 있어요
그리고 catch해서 에러를 잡을 수 있는데요 파라미터로 에러를 적 핥던
지구요
그리고 단순하게 컨설 을 에러 출력 해 볼게요
app>src>models>User.js--------------------
"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        const {id,psword} = await UserStorage.getUserInfo(client.id);
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);
            return response;
        } catch (err) {
            console.error(err);
        }
    }
}
module.exports = User;
====================
이렇게 있구요
저희가 지금 이렇게 코드를 구현 했을 때 의도한 바는 뭐냐면요
app>src>models>UserStorage.js에서 중복된 아이디를
클라이언트가 입력해서 회원 가입을 눌렀을 때
이미 존재하는 아이디입니다 라는거 에러를 만들어서
이 app>src>models>User.js에게 반환을 했구요
그 에러가 잡혔을 때 이 catch 에서 에러를 출력해 주길 원해요
자 그런데 지금 SIGN UP을 누르면 아무 반응이 없어요 왜냐
지금 그 에러를 받는 애는 const response거든요 따라서 얘를 console.log로 찍어 볼게요
 
app>src>models>User.js--------------------
"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        const {id,psword} = await UserStorage.getUserInfo(client.id);
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);
            console.log(response);
            return response;
        } catch (err) {
            console.error(err);
        }
    }
}
module.exports = User;
====================
 
인스턴스 를 찍어서 다시 한번 확인을 해보면
자 이제는 이 에러가 출력이 되는 것을 알 수 있죠
npm start
서버 가동
192.168.1.65:3000/register
aaa
에에에
1234
1234

Error: 이미 존재하는 아이디입니다.
다시 유저 스트리트를 넘어가서요
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUsers(data, isAll, fields);
             })
            .catch(console.error);
            // const users = JSON.parse(data);
            // if (isAll) return users;
    }
    static getUserInfo(id){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUserInfo(data, id);
            })
            .catch(console.error);
    }
    static async save(userInfo){
        // const users = await this.getUsers("id","psword","name");
        const users = await this.getUsers(true);
        if (users.id.includes(userInfo.id)){
            return new Error("이미 존재하는 아이디입니다.");    // ←
        }
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        fs.writeFile("./src/databases/users.json", JSON.stringify(users));
        return { success: true };
    }
}
module.exports = UserStorage;
====================
return new Error를 이렇게 throw Error를 해줘야 하는 겁니다
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUsers(data, isAll, fields);
             })
            .catch(console.error);
            // const users = JSON.parse(data);
            // if (isAll) return users;
    }
    static getUserInfo(id){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUserInfo(data, id);
            })
            .catch(console.error);
    }
    static async save(userInfo){
        // const users = await this.getUsers("id","psword","name");
        const users = await this.getUsers(true);
        if (users.id.includes(userInfo.id)){
            throw Error("이미 존재하는 아이디입니다.");    // ←
        }
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        fs.writeFile("./src/databases/users.json", JSON.stringify(users));
        return { success: true };
    }
}
module.exports = UserStorage;

====================

이 상태에서 SIGN UP을 눌러 볼게요

서버 가동
Error: 이미 존재하는 아이디입니다.
이 에러로 나오구요 이미 존재하는 id 입니다 라고 잘 출력이 됩니다
이렇게 해줬구요
 
app>src>models>User.js에서
try {
console.log
다시 지워 볼게요
app>src>models>User.js--------------------
"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        const {id,psword} = await UserStorage.getUserInfo(client.id);
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);	// ←
            return response;
        } catch (err) {
            console.error(err);
        }
    }
}
module.exports = User;

====================

저장하시고 한번 더 보면은
 
서버 가동
Error: 이미 존재하는 아이디입니다.
 
에러가 잘 잡히죠 이제 스러움 에서 에러를 잡을 수 있게 됐습니다
 
그리고 이제 이 에러를 저희는 오브젝트로 던질 건데요
리턴 이렇게 오브젝트를 만들어 섰던 지고 싶어요
app>src>models>User.js--------------------
"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        const {id,psword} = await UserStorage.getUserInfo(client.id);
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);
            return response;
        } catch (err) {
            const a = { success: false, msg: err };
            console.log(a.msg);
            return a;
        }
    }
}
module.exports = User;
====================
근데 이렇게 하게 되면요 이제 어떻게 나오냐 면 이거를 저희가 일단은
그냥 a 라는 변수에 담아 볼게요
const a = { success: false, msg: err }
우리가 의도한 것은 a.msg 라고 했을때 메시지가 출력 되는 거예요
출력은 될 것 같은데 출력은 되요 출력은 되는데 이게 지금 타입을 한번 볼게요
typeof에서 타입을 보면 SIGN UP해서 보면 지금 object로 나오죠
그 말은 지금 err이 에러가 object에 라는 거예요
} catch (err) {
const a = { success: false, msg: err }
이렇게 해버리면 은 어떤 일이 생기냐 자 일단 한번 해볼게요 이 a 를 return 해볼게요
리턴하고

app>src>models>User.js--------------------

"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        const {id,psword} = await UserStorage.getUserInfo(client.id);
        if(id){
            if ( id === client.id && psword === client.psword){
                return { success: true};
            }
            return { success: false, msg: "비밀번호가 틀렸습니다."};
        }
        return { success: false, msg: "존재하지 않는 아이디 입니다."};
    }
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);
            return response;
        } catch (err) {
            return { success: false, msg: err };
        }
    }
}
module.exports = User;
====================
SIGN UP 누르면 지금이 콘솔 창의 object라고 나와 버려요12:04
저희는 문자열을 출력하고 싶잖아요 따라서 에러를 던져줄 때 이거는 그냥
} catch (err) {
return { success: false, msg: err }
이대로 넣어 주겠구요
이 app>src>models>UserStorage.js에서 이 New Error가 아닌 그냥 throw Error 라고 해서 문자열을 에러 쓰라고 해도 하도록 해 주도록 하겠습니다
app>src>models>UserStorage.js--------------------
"use strict";
const fs = require("fs").promises;
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUsers(data, isAll, fields);
             })
            .catch(console.error);
            // const users = JSON.parse(data);
            // if (isAll) return users;
    }
    static getUserInfo(id){
        return fs
            .readFile("./src/databases/users.json")
            .then((data)=>{
                return this.#getUserInfo(data, id);
            })
            .catch(console.error);
    }
    static async save(userInfo){
        // const users = await this.getUsers("id","psword","name");
        const users = await this.getUsers(true);
        if (users.id.includes(userInfo.id)){
            throw "이미 존재하는 아이디입니다.";    // ←
        }
        users.id.push(userInfo.id);
        users.name.push(userInfo.name);
        users.psword.push(userInfo.psword);
        fs.writeFile("./src/databases/users.json", JSON.stringify(users));
        return { success: true };
    }
}
module.exports = UserStorage;
====================
cd app
npm start
192.168.1.65:3000/register
 
그럼 이제 쌓인 업 을 누르면 이미 존재하는 아이디 라고 잘 의도했던 대로 잘 출력이 됐습니다
User.js도 잘 됐구요 home.ctrl.js도 문제없이 잘 됐습니다
자 이제 app>src>databases>users.json 파일의 모든 로직이 잘 동작하는지 만 보도록 할게요
아이디는 구독과 이렇게 좋아요
비밀번호은 1234 1234
SIGN UP을 하면 지금 id 구독과 이름은 좋아요 로 잘 저장이 됐죠
비밀번호도 1234 로 잘 저장이 됐습니다
app>src>databases>users.json--------------------
{"id":["newstep","miero","nextlevel","aaa","구독"],"psword":["1234","1234","123456","1234","1234"],"name":["뉴스텝","미에로","넥스트레벨","에에에","좋아요"]}
====================
이걸 나온걸 로그인을 해 볼게 아 이게 구독과 비밀번호도 1 2 3 4이거에요
정상적으로 데이터가 잘 처리가 됩니다 이렇게 구성을 하게 되거든요
서버 를 껐다가 키 더라도 이처럼 제가 동 하더라도 다시 한번 제가 더 해볼게요
재가동 하더라도 데이터가 초기화 되지 않기 때문에 실제 데이터베이스와 유사하게
데이터를 저장할 수가 있게 됩니다13:10
 
정말 그런지 로그인 페이지에서 다시 한번 아까 저장한 것으로 로그인을 해 볼게요
구독과 1 2 3 4 로그인 정상적으로 로그인이 되죠
이런 식으로 파일로 데이터를 관리할 수 있겠구요
지금이 테이블 User.js라는 테이블을 보시면
id 라는 필드에 데이터는 요렇게
그리고 패스워드 필드는 요렇게
네임 이라는 필드는 요렇게 되어있어요
이제 이런 것들을 데이터베이스로 만들어 볼 건데요
그 전에 저희가 백엔드를 조금 더 개발하기 쉽게 끔 도와주는 도구들이 있거든요
 
api 테스트 도구 라고 이 있는데 그것들을 다음 시간에 한번 알려 드려 보겠습니다
저희가 이렇게 api 를 만들고 나서 이 api 텍스트를 이 브라우저에서 했단 말이에요
프론트엔드 로 이게 사실은 현업에서 말이 안되는게 백엔드에서 api 를 개발을 하고 나서 요
app>src>routes>home>index.js
router.post("/register", ctrl.ctrlprocess.register)
프론트엔드 에게 api 개발 했으니까 잘 동작하는지 테스트 좀 해 줘 라고 할 순 없잖아요
그래서 이제 백엔드가 독단적으로 테스트할 수 있는 도구들이 있는데요
그런 것들을 한번 다음 시간에 알려져 보도록 하겠습니다
어려운 내용임에도 불구하고 잘 따라 오셨고 요
지금까지 잘 따라오신 여러분들께 박수 보내 드리도록 하겠습니다
끝내기 전에 요 github 에 먼저 저장을 해줘야 하잖아요
제가 실수로 동영상 녹화를 종료하고 혼자 떠들면서 기타 그의 저장을 했거든요

git add .

git commit -m "fs모듈을 통한 회원가입 기능 구현"

git push origin master

일단 컵 메세지는 요렇게 8 시스템 모델을 통한 회원가입 끼는
구현 이라고 있었으니까요
이렇게 저장을 해주시면 되구요 그리고 푸쉬 해석이 톱에 업로드 해주시면
됩니다
이렇게 튜터 베 저당을 완료 해주시고 파일 시스템을 통해서 데이터베이스
까지 구현을 해 봤으니까요
지금까지 한 내용들을 버전으로 한번 더 저장을 해 줄게요
git tag v0.2.0-fileDB 해줬구요 그리고 파일
db 라고 추가 명시해 좋습니다 저장 해 주시고 음
git log --oneline
으로 보시면 지금 이 fs 모듈 을 청화산 밝기는 구현은
태그 해서 이렇게 명시가 됐고요
데이터베이스 없이 9 행한 것들은 이렇게나 띠 비롯해 그가 설명이 되어
있죠
q
이 태그를 저희는 github 에 업로드 시켜 주도록 할게요
오리진 오리진 이렇게 버전 명 표시 해 주시고
git push origin v0.2.0-fileDB
새로운 태그가 잘 github에 잘 로드 된것을 알 수 있고요
이 링크로 이동을 해 볼게요
자 이동을 했구요 여기서 이 master 눌러서
태그 이동하시면 0.2 2.0 버전이 올라온 것을 알 수 있죠
와 아 점점 뭔가 좀 만들어 지고 있는것 같아요
이상으로 찐 으로 멋지게 있구요 다음 시간에 뵙겠습니다 감사합니다

29서버 API 테스트 도구 | Postman | curl

api 를 테스트할 수 있는 방법에 대해서 알려드리겠습니다
테스트 도구 에는 여러가지가 있겠는데 요 두가지를 알려드릴게요
하나는 curl 라는거 고요
하나는 퍼스트 맨 이라는 건데요
퍼스트 맨 일반적으로 가장 많이 사용되고 있고요
curl 같은 경우는 리눅스나 유닉스 기반 운영체제에는 기본적으로 지원되는 명령 인데요
윈도우는 아마 설치를 해줘야 되는 것으로 알고 있어요
이 curl은 http 나 ftp 등등 에 대한 프로토콜로 통신을 할 수 있는 명령어구요

 

curl 라는 명령으로 서버 있는 파일의 다운로드받아 오기도 하고
뭐 그런식으로 사용되고 있기도 합니다
이것을 사용해서 는 테스트 해볼게요 테스트하기 위해서 먼저 서버가 열려
있어야 하잖아요
따라서 서버를 열어 줄게요
npm start
서버를 열어주었구요
테스트할 터미널을 하나 더 생각해 줄게요 주 타면 을 눌러서 깔끔하게
클리어 해 주시고
그리고 여기서 curl 그냥 보기만 하셔도 될 것 같아요
이런게 있구나 하고 넘어가면 될 것 같습니다
curl http://localhost:3000/login
해당 경로로 요청을 할게요
이 상태로 요청을 하게 되면 그냥 일반 get 메서드로 요청하게 되구요
요청하게 되면
서버에서 렌더링 해줬던 html이 ejs 파일이 고대로
이렇게 이렇게 응답 받은 것을 알 수가 있죠
아 이렇게 동작을 하는거구나 라는거 하시면 되구요
자 그럼 post로 요청을 어떻게 하는 잘볼게요 로그인에서 ajax 라는
걸로 포스트를 지정해 주면 되는데요
curl http://localhost:3000/login -X POST
이렇게 하면은 지금 데이터를 아무것도 전달 하지 않았잖아요
따라서 서버 에서 그냥 존재하지 않는 id 라고 JSON 객체만 전달을 해 준 것을 알 수 있고요
그러면 실제 로그인을 해보기 위해서 저희는 테이터를 입력해보세요 d

 

curl http://localhost:3000/login -X POST -d '{"id":"miero","psword":"1234"}
태그를 입력을 하시면 되고요
제이슨 데이터를 날려야 되는데 j 쓰는 다 문자로 되어 있으니까 문제
안에 넣어 줄게요
키는 아이린은 우림이 쑤어 드는 1234 였죠
이러한 데이터로 전달을 해 보겠습니다 이렇게 요청을 하게 되면 존재하지 않는 아이들아
아 내가 요청하는 데이터가 어떤건지 헤더로 도 명시를 해 줘야 되요
그래서 헤더 라는 옵션을 이용하시고 여기서 이렇게 컨텐트 타입 으로 내가
이거 참 않은 데이터에 타입을 명시 해 줬습니다 JSON 타입이라고
curl http://localhost:3000/login -X POST -d '{"id":"miero","psword":"1234"}' -H "Content-Type: application/json"
한번 엔터 눌러 볼게요 자 이렇게 하면은
{"success":true}% 라고 잘 출력이 되는 것을 알 수가 있죠
그러면은 이번에는 회원가입을 한 번 해볼게요 경로를 /register로 바꿨고 이렇게 데이터를 d 옵션을 줘서 데이터를 입력할 때는 포트가 자동으로 POST를 인식하기 때문에 이것은 없어도 됩니다

curl http://localhost:3000/register -X -d '{"id":"miero123","psword":"1234"}' -H "Content-Type: application/json"

이렇게 하고 아이디는 miero123 그리고 비밀번호는 1234 이렇게 하겠습니다
상태로 엔터 누르면

{"success":true}% 가 되었구요

정상적으로 반영이 됐는지 이 파일 하면 4k 소스 아내 테이터 비싼 의
브라우저를 아무거나 열어주시고 postman 이라고 입력을 해 보세요
입력하시면 
이렇게 Download Postman 있는데 이거 를 눌러주세요
여기서 다운로드를 눌러주시면 설치가 될 겁니다
설치 하는 건 어렵지 않으니까요 정상적으로 설치 하시고 애플리케이션을
실행 하시면 이런 식으로 나오는데요
요건 그냥 무시하시고 x 를 눌러주세요 그럼 이처럼 깔끔한 화면이 나오게
되는데요 여기서 어떻게 a 페이 테스트를 하냐면 이거는 요 참 애써
여기에다가 주소를 입력해주시면 되요
GET 다음 칸에
http://localhost:3000/login
로그인을 해 볼게요 로그인을 get으로 요청을 하게 되면은 Send를 보내 보면
html 문서가 그대로 응답이 된것을 알수가 있죠
이번에는 POST를 요청을 해 볼게요 그래서 POST 눌러주시고 Body에
눌러서 이 TEXT를 JSON 으로 바꿔 주시고
저희는 테제 있음 데이터를 번 해볼게요
{
"id": "miero",
"psword": "1234"
}
이렇게 데이터를 던져 보겠습니다
아 없는 것을 입력해서 센터를 하면은 존재하지 않는 아이들 고음을 잘
{
    "success"false,
    "msg""존재하지 않는 아이디 입니다."
}
출력이 됩니다
이런 걸로 이제 api 를 테스트해 볼 수 있고요
한가지만 더 해볼게요
POST
http://localhost:3000/register로 이거는 id 를 살짝 바꿔서 
{
    "id""miero123",
    "psword""1234"
}

4:32

이렇게 아이디 만들었구요
Send 보내면 true 라고 됐어요 
{
    "success"true
}
이런식으로 api 를 테스트할 수 있고 실제로 동작까지 하게 됩니다
그리고 여기 History 탭에 보면 은 저희가 요청했던 노력들을 확인할 수 있구요
이렇게 일일이 모든 경로를 왔다갔다 하면서 테스트하는 번거롭지 않아요
해서 여기 플러스 버튼을 눌러서 이렇게 여러가지를 테스트 해 줄 수
있어요 근데 이것도 나중에 되면 엄청 많이 쌓이거든요
이것도 번거로우니까 Collections을 이용해서요
여기에 폴더를 하나 만들어 볼게요
내용은 login-lecture라고 하겠구요
크레이트 화면에 러브 내쳐 풀러 가는 생겨요 여기서 어이 록 을 외쳐 를
눌러보세요 그리고 베드의 캐스트 눌러 보시고
여기서 이제 어떤 요청을 할껀지 이름의 정해 주시면 되요
이러는 그인 요청 로 1st 이렇게 해 줄게요 저장할 폴더를 선택을 해 주시고요
누군 렉쳐 선택해서 세이브 투 룩 내처 라고 해주시면 됩니다
그러면 1루 그 내처 1 생기죠 이거를 토스트로 바꾸고 요 이렇게 수정을
한 다음에 여기 Body 에서도 데이터를
자 이렇게 해서요 실제 로그인 텐데 다시 한번 볼게요
이렇게 보면 아까 회원 가입했던 아이디로 잘 로그인이 됐습니다
이런식으로 되고 이것을 SAVE 눌러주시면 지금 여기 갯수로 되어 있던게
해당 요청 url 과 메서드로 바뀌어 있어요
따라서 이런 식으로 컬렉션으로 많이 사용되는 의 api 는 이렇게 저장을
해두고 계속 반복해서 테스트해볼 수 있습니다
그래서 curl 보다는 이게 훨씬 많이 사용되고 있다는 거 알고 계시면 되고요
그리고 여러분도 실제 api 테스트 할 때 이걸 쓰게 될 거에요 이거에
최대한 익숙해지시면 될것 같습니다
이상으로 api 테스트 도구에 대해서 알아 봤구요
이제는 본격적으로 클라우드 의 데이터베이스를 이용해 볼 거예요
이제 다룰 내용들은 사실 이전 껏 보다는 더 어려워요
 

30AWS RDS 대여 | 과금 안되도록 주의하기 | 클라우드 | MySQL

31AWS RDS 한글 설정 | 파라미터 옵션 | 클라우드 | MySQL

https://www.youtube.com/watch?v=0PXdDPgXVEc 

32MySQL workbench | AWS RDS와 연동

33[Node.js] 백엔드 맛보기 | AWS RDS로 DB 구축하기 | 로그인 구현 | MySQL

app>src>config>db.js--------------------

const mysql = require("mysql");
const db = mysql.createConnection({
    host: "m-login-lecture.czklehwhqkvy.ap-northeast-2.rds.amazonaws.com",
    user: "admin",
    password: "**********",
    database: "login_lecture",
});
db.connect();
module.exports = db;

====================

app>src>models>UserStorage.js--------------------

"use strict";
const db = require("../config/db");	// ←
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
    }
    static getUserInfo(id){
        db.query("SELECT * FROM users", (err, data) => {	// ←
            console.log(data);	// ←
        });	// ←
    }
    static async save(userInfo){
    }
}
module.exports = UserStorage;

====================

https://www.youtube.com/watch?v=JcniLVmzzyY 

2분 35초 부터 보시면 될겁니다^^

app>src>models>User.js--------------------

"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {
        this.body = body;
    }
    async login(){
        const client = this.body;
        try {	// ←
            const {id, psword} = await UserStorage.getUserInfo(client.id);	// ←
            if(user){	// ←
                if ( user.id === client.id && user.psword === client.psword){	// ←
                    return { success: true};	// ←
                }
                return { success: false, msg: "비밀번호가 틀렸습니다."};	// ←
            }	// ←
            return { success: false, msg: "존재하지 않는 아이디 입니다."};	// ←
        } catch (err) {	// ←
            return { success: false, err };	// ←
        }	// ←
    }	// ←
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);
            return response;
        } catch (err) {
            return { success: false, msg: err };
        }
    }
}
module.exports = User;

====================

cd app

npm start

192.168.1.65:3000/login

LOGIN 클릭

 

서버 가동
[
  RowDataPacket {
    id: 'asyouasi',
    name: '에즈유에즈아이',
    psword: '1234',
    in_date: 2022-03-14T23:54:39.000Z
  },
  RowDataPacket {
    id: 'i1683u',
    name: '아이1683유',
    psword: '123456',
    in_date: 2022-03-14T23:54:39.000Z
  },
  RowDataPacket {
    id: 'miero',
    name: '미에로',
    psword: '1234',
    in_date: 2022-03-14T23:54:39.000Z
  },
  RowDataPacket {
    id: 'miero123',
    name: '미에로123',
    psword: '1234',
    in_date: 2022-03-14T23:54:39.000Z
  },
  RowDataPacket {
    id: 'mieronewstep',
    name: '미에로뉴스텝',
    psword: '1234',
    in_date: 2022-03-14T23:54:39.000Z
  },
  RowDataPacket {
    id: 'newstep',
    name: '뉴스텝',
    psword: '1234',
    in_date: 2022-03-14T23:54:39.000Z
  }
]

 

app>src>models>UserStorage.js--------------------

"use strict";
const db = require("../config/db");
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
    }
    static getUserInfo(id){
        db.query("SELECT * FROM users WHERE id = ?", [id], (err, data) => {	// ←
            console.log(data);
        });
    }
    static async save(userInfo){
    }
}
module.exports = UserStorage;

====================

miero 입력

LOGIN

 

서버 가동
[
  RowDataPacket {
    id: 'miero',
    name: '미에로',
    psword: '1234',
    in_date: 2022-03-14T23:54:39.000Z
  }
]

5:08

app>src>models>UserStorage.js--------------------

"use strict";
const db = require("../config/db");
class UserStorage {
    static #getUserInfo(data, id) {
        const users = JSON.parse(data);
        const idx = users.id.indexOf(id);
        const usersKeys = Object.keys(users);
        const userInfo = usersKeys.reduce((newUser, info)=>{
            newUser[info] = users[info][idx];
            return newUser;
        },{});
        // console.log(userInfo);
        return userInfo;
    }
    static #getUsers(data, isAll, fields){
        const users = JSON.parse(data);
        if (isAll) return users;
        const newUsers = fields.reduce((newUsers, field)=>{
            if(users.hasOwnProperty(field)){
                newUsers[field] = users[field];
            }
            return newUsers;
        }, {});
        return newUsers;
    }
    static getUsers(isAll, ...fields){
    }
    static getUserInfo(id){
        return new Promise((resolve, reject) => {
            db.query("SELECT * FROM users WHERE id = ?", [id], (err, data) => {
                if (err) reject(err);
                resolve(data[0]);	// ←
            });
        });
    }
    static async save(userInfo){
    }
}
module.exports = UserStorage;

====================

8:06

함수는 한 가지 기능만 수행하도곡 구현해줘야 합니다.

Promise로 만들어주지 않으면 하나의 함수에서 DB를 조회하고,

로그인 정보를 검증하고,

클라이언트에 응답까지 해주는 

"이도 저도 아닌 코드"가 만들어 집니다.

 

클래스는 User와 UserStorage처럼 각자의 역할을 분명하게 구분 시켜주는 것이 좋습니다.

UserStorage에서는 DB를 CRUD(생성,읽기,수정,삭제) 역할만 수행하고,

해당 데이터를 가지고 검증 및 조작하는 것은 User가 수행하도록 역할을 구분해준 것이죠.

34[Node.js] 백엔드 맛보기 | AWS RDS로 회원가입 구현 | 웹서버와 WAS | MySQL

app>src>models>UserStorage.js--------------------

"use strict";
const db = require("../config/db");
class UserStorage {
    static getUsers(isAll, ...fields){	// ←
    }
    static getUserInfo(id){
        return new Promise((resolve, reject) => {
            const query = "SELECT * FROM users WHERE id = ?;";
            db.query(query, [id], (err, data) => {
                if (err) reject(err);
                resolve(data[0]);
            });
        });
    }
    static async save(userInfo){
        return new Promise((resolve, reject) => {
            const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";	// ←
            db.query(query, [userInfo.id, userInfo.name, userInfo.psword], (err) => {	// ←
                if (err) reject(err);	// ←
                resolve({ success: true });	// ←
            });
        });
    }
}
module.exports = UserStorage;

====================

cd app

npm start

192.168.1.65/register

ccc

씨씨씨

1234

1234

SIGN UP

 

MySQL Workbench 에서 확인

show databases;

쿼리 실행 단축키Ctrl+Enter

use login_lecture;

show tables;

select * from users;

 

혹시 쿼리문 잘못짜면 에러-object반환하니까 수정하자

app>src>models>UserStorage.js--------------------

"use strict";
const db = require("../config/db");
class UserStorage {
    static getUsers(isAll, ...fields){
    }
    static getUserInfo(id){
        return new Promise((resolve, reject) => {
            const query = "SELECT * FROM users WHERE id = ?;";
            db.query(query, [id], (err, data) => {
                if (err) reject(`${err}`);	// ←
                resolve(data[0]);
            });
        });
    }
    static async save(userInfo){
        return new Promise((resolve, reject) => {
            const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";
            db.query(query, [userInfo.id, userInfo.name, userInfo.psword], (err) => {
                if (err) reject(`${err}`);	// ←
                resolve({ success: true });
            });
        });
    }
}
module.exports = UserStorage;

====================

MySQL Workbench 에서 확인

select * from users;

쿼리 실행 단축키Ctrl+Enter

 

로그인도 try catch 문으로 처리

app>src>models>User.js--------------------

"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        try {
            const {id, psword} = await UserStorage.getUserInfo(client.id);
            if(user){
                if ( user.id === client.id && user.psword === client.psword){
                    return { success: true};
                }
                return { success: false, msg: "비밀번호가 틀렸습니다."};
            }
            return { success: false, msg: "존재하지 않는 아이디 입니다."};
        } catch (err) {
            return { success: false, msg:err };
        }
    }
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);
            return response;
        } catch (err) {
            return { success: false, msg: err };	// ←
        }
    }
}
module.exports = User;

====================

app>src>models>User.js--------------------

"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        try {
            const user = await UserStorage.getUserInfo(client.id);	// ←
            if(user){
                if ( user.id === client.id && user.psword === client.psword){
                    return { success: true};
                }
                return { success: false, msg: "비밀번호가 틀렸습니다."};
            }
            return { success: false, msg: "존재하지 않는 아이디 입니다."};
        } catch (err) {
            return { success: false, err };	// ←
        }
    }
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);
            return response;
        } catch (err) {
            return { success: false, err };	// ←
        }
    }
}
module.exports = User;

====================

4:50

Web Server & WAS(Web Application Server)

35[Node.js] 백엔드 맛보기 | 환경 변수 관리 | 보안 향상 | dotenv

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");	// ←
dotenv.config();	// ←
const app = express();
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

app>.env--------------------

PORT=3000

====================

app>bin>www.js--------------------

'use strict';
// 이 www.js 파일에서는 app 이라는 부분을 찾을 수 없어서 연결해주자
const app = require("../app");
const PORT = process.env.PORT || 3000;	// ←
// app.js 서버 가동 부분 잘라서 가져오고
app.listen(PORT, ()=>{
    console.log("서버 가동");
});

====================

app>.env--------------------

PORT=3000
DB_HOST="miero-login-lecture.czklehwhqkvy.ap-northeast-2.rds.amazonaws.com"
DB_USER="admin"
DB_PSWORD="**********"
DB_DATABASE="login_lecture"

====================

app>src>config>db.js--------------------

const mysql = require("mysql");
const db = mysql.createConnection({
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PSWORD,
    database: process.env.DB_DATABASE,
});
db.connect();
module.exports = db;

====================

git add .

git commit -m "AWS RDS와 연동 & dotenv로 환경변수 등록"

git log --oneline

q

git tag "v0.3.0-cloudDB"

git log --oneline

q

git pusth origin master

git push origin v0.3.0-cloudDB

36[Node.js] 백엔드 맛보기 | 로그 관리 | morgan (1/4)

cd app

npm i morgan -s

app>app.js--------------------

'use strict';
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");	// ←
const app = express();
dotenv.config();	// ←
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home");
// 앱 세팅
app.set("views", "./src/views");
app.set("view engine", "ejs");
app.use(express.static(`${__dirname}/src/public`));
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("tiny"));	// ←
app.use(morgan(":method :url :status :res[content-length] - :response-time ms"));	// ←
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

cd app

npm start

 

서버 가동

192.168.1.65:3000/login

GET /login 304 - - 6.583 ms

 

192.168.1.65:3000/register

GET /register 200 1130 - 11.488 ms

 

192.168.1.65:3000/login
GET /login 304 - - 1.387 ms

 

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan("dev"));	// ←
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

서버 가동
GET /login 304 6.651 ms - -

 

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan("combined"));	// ←
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

서버 가동
::ffff:192.168.1.65 - - [17/Mar/2022:06:22:55 +0000] "GET /login HTTP/1.1" 304 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36"

 

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const accessLogStream = fs.createWriteStream(`{루트경로}/log/access.log`, { flags: 'a' })	// ←
const accessLogStream = fs.createWriteStream(`{__dirname}/log/access.log`, { flags: 'a' })	// ←
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan("dev"),{ stream: 스트림 });	// ←
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const accessLogStream = fs.createWriteStream(`{루트경로}/log/access.log`, { flags: 'a' })
const accessLogStream = fs.createWriteStream(`{__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("dev"),{ stream: accessLogStream });	// ←
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const fs = require("fs");
const app = express();
dotenv.config();
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })	// ←
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("dev",{ stream: accessLogStream }));	// ←
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

https://www.npmjs.com/package/morgan

 

morgan

HTTP request logger middleware for node.js. Latest version: 1.10.0, last published: 2 years ago. Start using morgan in your project by running `npm i morgan`. There are 7638 other projects in the npm registry using morgan.

www.npmjs.com

morgan

Tokens

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const fs = require("fs");
const app = express();
dotenv.config();
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan(":method :date[web]",{ stream: accessLogStream }));	// ←
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

app>log>access.log--------------------

GET /login 304 6.579 ms - -
GET /register 304 1.203 ms - -
GET
GET Thu, 17 Mar 2022 07:06:10 GMT

====================

morgan으로 log를 파일에 저장하지않고 mongoDB에 저정할려면

npm 사이트에서

mongose morgan 검색

아쉽게도 npm에 MySql은 없는거 같다

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan(":method :date[web]",{ stream: accessLogStream }));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

 

app>src>log.js--------------------

const fs = require("fs");
const appRoot = require("app-root-path");
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' });
const accessLogStream = fs.createWriteStream(`${appRoot}/log/access.log`, { flags: 'a' });
module.exports = accessLogStream;

====================

npm i -S app-root-path

 

npm start

 

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("tiny",{ stream: accessLogStream }));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("dev"));	// ←
app.use(morgan("tiny",{ stream: accessLogStream }));	// ←
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

37[Node.js] 백엔드 맛보기 | 로그 관리 | winston (2/4)

app>src>config>logger.js--------------------

const winston = require("winston");

====================

cd app

npm i winston -S

 

app>src>config>logger.js--------------------

const winston = require("winston");
const logger = winston.createLogger({
    transports: [new winston.transports.Console({})],
});
module.exports = logger;

====================

 

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home");
const logger = require("./src/config/logger");	// ←
logger.log("info","Hello 구독자님들.");	// ←
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("dev"));
app.use(morgan("common",{ stream: accessLogStream }));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

npm start

 

{"level":"info","message":"Hello 구독자님들."}
서버 가동

 

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
const logger = require("./src/config/logger");
// logger.log("info","Hello 구독자님들.");
logger.info("Hello 구독자님들.");	// ←
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("dev"));
app.use(morgan("common",{ stream: accessLogStream }));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

 

Logging

const levels = {

error: 0,

warn: 1,

info: 2,

http: 3,

verbose: 4,

debug: 5,

silly: 6

}; 

app>src>config>logger.js--------------------

const winston = require("winston");
const logger = winston.createLogger({
    transports: [new winston.transports.Console({
        // level: "error",
        level: "http",	// ←
    })],
});
module.exports = logger;

====================

 

app>src>config>logger.js--------------------

const winston = require("winston");
const logger = winston.createLogger({
    transports: [new winston.transports.Console({
        // level: "error",
        level: "info",	// ←
        format: winston.format.simple(),	// ←
    })],
});
module.exports = logger;

====================

info: Hello 구독자님들.
서버 가동

 

컬러라이징

app>src>config>logger.js--------------------

const winston = require("winston");
const logger = winston.createLogger({
    transports: [new winston.transports.Console({
        // level: "error",
        level: "info",
        format: winston.format.combine(	// ←
            winston.format.colorize(),	// ←
            winston.format.simple()),
    })],
});
module.exports = logger;

====================

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
const logger = require("./src/config/logger");
// logger.log("info","Hello 구독자님들.");
// logger.info("Hello 구독자님들.");
logger.error("Hello 구독자님들.");	// ←
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("dev"));
app.use(morgan("common",{ stream: accessLogStream }));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

error: Hello 구독자님들.
서버 가동

 

app>src>config>logger.js--------------------

const winston = require("winston");
const logger = winston.createLogger({
    transports: [new winston.transports.Console({
        // level: "error",
        level: "info",
        format: winston.format.combine(
            winston.format.colorize(),
            // winston.format.simple()),
            winston.format.json()),	// ←
    })],
});
module.exports = logger;

====================

{"level":"\u001b[31merror\u001b[39m","message":"Hello 구독자님들."}
서버 가동

 

app>src>config>logger.js--------------------

const winston = require("winston");
const logger = winston.createLogger({
    transports: [new winston.transports.Console({
        // level: "error",
        level: "info",
        format: winston.format.combine(
            // winston.format.colorize(),
            // winston.format.simple()),
            winston.format.json()),	// ←
    })],
});
module.exports = logger;

====================

{"level":"error","message":"Hello 구독자님들."}
서버 가동

app>src>config>logger.js--------------------

const winston = require("winston");
const logger = winston.createLogger({
    transports: [new winston.transports.Console({
        // level: "error",
        level: "info",
        format: winston.format.combine(
            // winston.format.colorize(),
            // winston.format.simple()),
            winston.format.timestamp(),	// ←
            winston.format.json()),
    })],
});
module.exports = logger;

====================

{"level":"error","message":"Hello 구독자님들.","timestamp":"2022-03-17T09:25:37.851Z"}
서버 가동

app>src>config>logger.js--------------------

const winston = require("winston");
const logger = winston.createLogger({
    transports: [new winston.transports.Console({
        // level: "error",
        level: "info",
        format: winston.format.combine(
            // winston.format.colorize(),
            // winston.format.simple()),
            winston.format.timestamp({
                format: "YYYY-MM-DD HH:mm:dd"	// ←
            }),
            winston.format.json()),
    })],
});
module.exports = logger;

====================

{"level":"error","message":"Hello 구독자님들.","timestamp":"2022-03-17 18:27:04"}
서버 가동

9:51

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");	// ←
const logger = createLogger({	// ←
    transports: [new transports.Console({	// ←
        // level: "error",
        level: "info",
        format: format.combine(	// ←
            // winston.format.colorize(),
            // winston.format.simple()),
            format.timestamp({	// ←
                format: "YYYY-MM-DD HH:mm:dd"
            }),
            format.json()),
    })],
});
module.exports = logger;

====================

cd app

npm start

 

{"level":"error","message":"Hello 구독자님들.","timestamp":"2022-03-21 15:36:01"}
서버 가동

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize } = format;
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: combine(
            // winston.format.colorize(),
            // winston.format.simple()),
            timestamp({
                format: "YYYY-MM-DD HH:mm:dd"
            }),
            json()),
    })],
});
module.exports = logger;

====================

combine을 따로 빼자

const printLogFormat

 

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize } = format;
const printLogFormat = combine(	// ←
    // winston.format.colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    json()
    );
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: printLogFormat,	// ←
    })],
});
module.exports = logger;

====================

{"level":"error","message":"Hello 구독자님들.","timestamp":"2022-03-21 15:45:01"}
서버 가동

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize } = format;
const printLogFormat = combine(
    // winston.format.colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    simple()	// ←
    );
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

error: Hello 구독자님들. {"timestamp":"2022-03-21 15:46:01"}
서버 가동

 

그래도 마음에 안든다

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf } = format;
const printLogFormat = combine(
    // winston.format.colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printf(({ timestamp }) => {
        return `${timestamp} 미에로 화이팅!!`;
    })
    );
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

12:29

2022-03-21 15:52:01 미에로 화이팅!!
서버 가동

문제점 app>app.js 의 logger.error("Hello 구독자님들,") 가 안 나온다

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf } = format;
const printLogFormat = combine(
    // winston.format.colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printf(({ timestamp, message }) => {
        return `${timestamp} ${message}`;	// ←
    })
    );
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf } = format;
const printLogFormat = combine(
    // winston.format.colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printf(({ timestamp, level, message }) => {	// ←
        return `${timestamp}  ${level} ${message}`;	// ←
    })
    );
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf } = format;
const printLogFormat = combine(
    // winston.format.colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printf(({ timestamp, level, message }) => {
        return `${timestamp}  ${level} : ${message}`;	// ←
    })
    );
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

2022-03-21 16:05:01  error : Hello 구독자님들.
서버 가동

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf, label } = format;	// ←
const printLogFormat = combine(
    label({	// ←
        label: "백엔드 맛보기"	// ←
    }),	// ←
    // winston.format.colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printf(({ timestamp, label, level, message }) => {	// ←
        return `${timestamp}  ${label}  ${level} : ${message}`;	// ←
    })
    );
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

2022-03-21 16:09:01  백엔드 맛보기  error : Hello 구독자님들.
서버 가동

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf, label } = format;
const printLogFormat = combine(
    label({
        label: "백엔드 맛보기"
    }),
    colorize(),	// ←
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printf(({ timestamp, label, level, message }) => {
        return `${timestamp}  [${label}]  ${level} : ${message}`;	// ←
    })
    );
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

2022-03-21 16:13:01  [백엔드 맛보기]  error : Hello 구독자님들.
서버 가동

 

printf 까지 분리하자

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf, label } = format;
const printFormat = printf(({ timestamp, label, level, message }) => {
    return `${timestamp}  [${label}]  ${level} : ${message}`;
});
const printLogFormat = combine(
    label({
        label: "백엔드 맛보기"
    }),
    colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printFormat	// ←
    );
const logger = createLogger({
    transports: [new transports.Console({
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

38[Node.js] 백엔드 맛보기 | 로그 관리 | winston (3/4)

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf, label } = format;
const printFormat = printf(({ timestamp, label, level, message }) => {
    return `${timestamp}  [${label}]  ${level} : ${message}`;
});
const printLogFormat = combine(
    label({
        label: "백엔드 맛보기"
    }),
    // colorize(),	// ←
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printFormat
    );
const logger = createLogger({
    // transports: [new transports.Console({
    transports: [new transports.File({	// ←
        filename: "access.log",	// ←
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

access.log 파일 자동 생성됨

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf, label } = format;
const printFormat = printf(({ timestamp, label, level, message }) => {
    return `${timestamp}  [${label}]  ${level} : ${message}`;
});
const printLogFormat = combine(
    label({
        label: "백엔드 맛보기"
    }),
    // colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printFormat
    );
const logger = createLogger({
    // transports: [new transports.Console({
    transports: [new transports.File({
        filename: "./logs/access.log",	// ←
        dirname: "./logs",	// ←
        // level: "error",
        level: "info",
        format: printLogFormat,
    })],
});
module.exports = logger;

====================

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf, label } = format;
const printFormat = printf(({ timestamp, label, level, message }) => {
    return `${timestamp}  [${label}]  ${level} : ${message}`;
});
const printLogFormat = combine(
    label({
        label: "백엔드 맛보기"
    }),
    // colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printFormat
    );
const logger = createLogger({
    transports: [
        new transports.File({
        filename: "./logs/access.log",
        dirname: "./logs",
        // level: "error",
        level: "info",
        format: printLogFormat,
    }),
    	new transports.Console({	// ←
        level: "info",	// ←
        format: printLogFormat,	// ←
    }),	// ←
],
});
module.exports = logger;

====================

실제 서비스 중인 서버인지

개발 중인 서버인지에 따라서

환경변수에 접근을 해서

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf, label } = format;
const printFormat = printf(({ timestamp, label, level, message }) => {
    return `${timestamp}  [${label}]  ${level} : ${message}`;
});
const printLogFormat = combine(
    label({
        label: "백엔드 맛보기"
    }),
    // colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printFormat
    );
const logger = createLogger({
    transports: [
        new transports.File({
            filename: "./logs/access.log",
            dirname: "./logs",
            // level: "error",
            level: "info",
            format: printLogFormat,
        }),
    ],
});
if (process.env.NODE_ENV !== "production") {	// ←
    logger.add(	// ←
        new transports.Console({	// ←
            level: "info",	// ←
            format: printLogFormat,	// ←
        })	// ←
    );	// ←
}	// ←
module.exports = logger;

====================

NODE_ENV 환경변수 만들어주자

app>.env--------------------

NODE_ENV="dev"	// ←
PORT=3000
DB_HOST="miero-login-lecture.czklehwhqkvy.ap-northeast-2.rds.amazonaws.com"
DB_USER="admin"
DB_PSWORD="**********"
DB_DATABASE="login_lecture"

====================

2022-03-21 17:01:01  [백엔드 맛보기]  error : Hello 구독자님들.
서버 가동

app>.env--------------------

NODE_ENV="production"	// ←
PORT=3000
DB_HOST="miero-login-lecture.czklehwhqkvy.ap-northeast-2.rds.amazonaws.com"
DB_USER="admin"
DB_PSWORD="**********"
DB_DATABASE="login_lecture"

====================

서버 가동

app>.env--------------------

NODE_ENV="dev"	// ←
PORT=3000
DB_HOST="miero-login-lecture.czklehwhqkvy.ap-northeast-2.rds.amazonaws.com"
DB_USER="admin"
DB_PSWORD="**********"
DB_DATABASE="login_lecture"

====================

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf, label } = format;
const printFormat = printf(({ timestamp, label, level, message }) => {
    return `${timestamp}  [${label}]  ${level} : ${message}`;
});
const printLogFormat = combine(
    label({
        label: "백엔드 맛보기"
    }),
    // colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    // simple()
    printFormat
    );
const opts = {	// ←
    file: new transports.File({	// ←
        filename: "./logs/access.log",	// ←
        dirname: "./logs",	// ←
        // level: "error",	// ←
        level: "info",	// ←
        format: printLogFormat,	// ←
    }),	// ←
    console: new transports.Console({	// ←
        level: "info",	// ←
        format: printLogFormat,	// ←
    })	// ←
}	// ←
const logger = createLogger({
    transports: [opts.file],	// ←
});
if (process.env.NODE_ENV !== "production") {
    logger.add(opts.console);	// ←
}
module.exports = logger;

====================

2022-03-21 17:11:01  [백엔드 맛보기]  error : Hello 구독자님들.
서버 가동

5:16

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, json, simple, colorize, printf, label } = format;
const printFormat = printf(({ timestamp, label, level, message }) => {
    return `${timestamp}  [${label}]  ${level} : ${message}`;
});
const printLogFormat = {	// ←
    file: combine(	// ←
    label({	// ←
        label: "백엔드 맛보기"
    }),
    // colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    printFormat
    ),
    console: combine(	// ←
        colorize(),	// ←
        simple()	// ←
    ),
};
const opts = {
    file: new transports.File({
        filename: "./logs/access.log",
        dirname: "./logs",
        // level: "error",
        level: "info",
        format: printLogFormat.file,	// ←
    }),
    console: new transports.Console({
        level: "info",
        format: printLogFormat.console,	// ←
    })
}
const logger = createLogger({
    transports: [opts.file],
});
if (process.env.NODE_ENV !== "production") {
    logger.add(opts.console);
}
module.exports = logger;

====================

error: Hello 구독자님들.
서버 가동

app>bin>www.js--------------------

'use strict'; //ecma script 준수하겠다
// 이 www.js 파일에서는 app 이라는 부분을 찾을 수 없어서 연결해주자
const app = require("../app"); // 상위폴더에 있는 app.js
const logger = require("../src/config/logger");	// ←
const PORT = process.env.PORT || 3000;
// app.js 서버 가동 부분 잘라서 가져오고
app.listen(PORT, ()=>{
    // console.log("서버 가동");
    logger.info("서버 가동");	// ←
});

====================

error: Hello 구독자님들.
info: 서버 가동

app>bin>www.js--------------------

'use strict'; //ecma script 준수하겠다
// 이 www.js 파일에서는 app 이라는 부분을 찾을 수 없어서 연결해주자
const app = require("../app"); // 상위폴더에 있는 app.js
const logger = require("../src/config/logger");
const PORT = process.env.PORT || 3000;
// app.js 서버 가동 부분 잘라서 가져오고
app.listen(PORT, ()=>{
    // console.log("서버 가동");
    logger.info(`${PORT} 포트에서 서버가 가동되었습니다.`);	// ←
});

====================

error: Hello 구독자님들.
info: 3000 포트에서 서버가 가동되었습니다.

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, simple, colorize, printf, label } = format;	// ← json삭제
const printFormat = printf(({ timestamp, label, level, message }) => {
    return `${timestamp}  [${label}]  ${level} : ${message}`;
});
const printLogFormat = {
    file: combine(
    label({
        label: "백엔드 맛보기"
    }),
    // colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    printFormat
    ),
    console: combine(
        colorize(),
        simple()
    ),
};
const opts = {
    file: new transports.File({
        filename: "./logs/access.log",
        dirname: "./logs",
        // level: "error",
        level: "info",
        format: printLogFormat.file,
    }),
    console: new transports.Console({
        level: "info",
        format: printLogFormat.console,
    })
}
const logger = createLogger({
    transports: [opts.file],
});
if (process.env.NODE_ENV !== "production") {
    logger.add(opts.console);
}
module.exports = logger;

====================

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const morgan = require("morgan");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const logger = require("./src/config/logger");
// logger.log("info","Hello 구독자님들.");
// logger.info("Hello 구독자님들.");
// logger.error("Hello 구독자님들.");
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("dev"));
app.use(morgan("common",{ stream: accessLogStream }));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

info: 3000 포트에서 서버가 가동되었습니다.

로그파일은 일자별로 분리해서 저장되어야 한다

npmjs.com

winston-daily-rotate-file

 

git add .

git commit -m "로그 관리 모듈 winston 등록 및 설정"

git push origin master

39[Node.js] 백엔드 맛보기 | 로그 관리 | 프로젝트 적용 | winston & morgan (4/4)

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger"); // ←
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {    // get 메서드에 해당
    ctrlindex: (req,res)=>{
        logger.info(`GET / 200 "홈 화면으로 이동"`); // ←
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 200 "로그인 화면으로 이동"`); // ←
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        logger.info(`GET /register 200 "회원가입 화면으로 이동"`); // ←
        res.render("home/register"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = await user.login();
        // console.log(response);
        return res.json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register();
        // console.log(response);
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

192.168.1.65:3000/login

 

info: GET /login 200 "로그인 화면으로 이동"
app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger");
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {    // get 메서드에 해당
    ctrlindex: (req,res)=>{
        logger.info(`GET / 200 "홈 화면으로 이동"`);
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 200 "로그인 화면으로 이동"`);
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        logger.info(`GET /register 200 "회원가입 화면으로 이동"`);
        res.render("home/register"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = await user.login();
        // console.log(response);
        logger.info(	// ←
            `POST / 200 Response: "success: ${response.success}, msg: ${response.msg}"`	// ←
        );	// ←
        return res.json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register(); // ←
        // console.log(response);
        logger.info(	// ←
            `POST /register 200 Response: "success: ${response.success}, msg: ${response.msg}"`	// ←
        );	// ←
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

info: POST / 200 Response: "success: true, msg: undefined"
POST /login 200 26.913 ms - 16
info: GET / 200 "홈 화면으로 이동"
GET / 304 2.561 ms - -

 

app>src>public>js>home>login.js--------------------

'use strict'; //ecma script 준수하겠다
// 테스트하기위해서
// console.log("hello");
// console.log("bye");
// login 기능 구현 - 프론트 단 기능 구현
// 아이디와 비밀번호 입력 받고
// 로그인 버튼이 눌릴 때 server로 전달이 된다
// 아이디와 패스워드를 javascript로 처리해야 된다
const id = document.querySelector("#id"),
    psword = document.querySelector("#psword"),
    loginBtn = document.querySelector("#button");
// console.log(id);
// console.log("hello");
loginBtn.addEventListener("click",login); // 두 번째 인수는 함수이다
function login(){
    // console.log("bye");
    // console.log(id.value);
    if (!id.value) return alert("아이디를 입력해주십시오.");	// ←
    if (!psword.value) return alert("비밀번호를 입력해주십시오.");	// ←
    const req = {
        id: id.value,
        psword: psword.value,
    };
    // console.log(req); // 일반 req 리퀘스트 데이터와
    // console.log(JSON.stringify(req)); // JSON 형태로 감싼 req 리퀘스트 데이터 비교해 보자
    fetch("/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json", // 내가 전달하는 데이터의 타입
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())        // ← 이 부분 수정하고
      .then((res) => {				// ← 여기 부분
        if(res.success){                                   // 개발하기쉽게 임시로 주석처리 20
          location.href = "/";		// 이동할 링크           // 개발하기쉽게 임시로 주석처리 20
        } else {
          alert(res.msg);				// 서버에서 전달한 메시지// 개발하기쉽게 임시로 주석처리 20
        }                                                // 개발하기쉽게 임시로 주석처리 20
      })
      .catch((err) => {
        console.error("로그인 중 에러 발생");
        // console.error(new Error("로그인 중 에러 발생"));
      });
};

====================

app>src>models>User.js--------------------

"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        try {
            const user = await UserStorage.getUserInfo(client.id);
            if(user){
                if ( user.id === client.id && user.psword === client.psword){
                    return { success: true};
                }
                return { success: false, msg: "비밀번호가 틀렸습니다."};
            }
            return { success: false, msg: "존재하지 않는 아이디 입니다."};
        } catch (err) {
            return { success: false, msg: err };
        }
    }
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);
            return response;
        } catch (err) {
            return { success: false, msg: err };	// ←
        }
    }
}
module.exports = User;

====================

에러를 만들어보자

app>src>models>UserStrorage.js--------------------

"use strict";
const db = require("../config/db");
class UserStorage {
    static getUserInfo(id){
        return new Promise((resolve, reject) => {
            // const query = "SELECT * FROM users WHERE id = ?;";
            const query = "SELECT * FROM abc WHERE id = ?;";	// ←
            db.query(query, [id], (err, data) => {
                if (err) reject(`${err}`);
                else resolve(data[0]);
            });
        });
    }
    static async save(userInfo){
        return new Promise((resolve, reject) => {
            const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";
            db.query(query, [userInfo.id, userInfo.name, userInfo.psword], (err) => {
                if (err) reject(`${err}`);
                else resolve({ success: true });
            });
        });
    }
}
module.exports = UserStorage;

====================

info: POST / 200 Response: "success: false, msg: Error: ER_NO_SUCH_TABLE: Table 'login_lecture.abc' doesn't exist"
POST /login 200 24.640 ms - 90

 

app>src>models>User.js--------------------

"use strict";
const { response } = require("express");
const UserStorage = require("./UserStorage");
class User{
    constructor(body) {         // 생성자
        this.body = body;
    }
    async login(){
        const client = this.body;
        try {
            const user = await UserStorage.getUserInfo(client.id);
            if(user){
                if ( user.id === client.id && user.psword === client.psword){
                    return { success: true};
                }
                return { success: false, msg: "비밀번호가 틀렸습니다."};
            }
            return { success: false, msg: "존재하지 않는 아이디 입니다."};
        } catch (err) {
            return { success: false, err };	// ←
        }
    }
    async register() {
        const client = this.body;
        try {
            const response = await UserStorage.save(client);
            return response;
        } catch (err) {
            return { success: false, err };	// ←
        }
    }
}
module.exports = User;

====================

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger");
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {    // get 메서드에 해당
    ctrlindex: (req,res)=>{
        logger.info(`GET / 200 "홈 화면으로 이동"`);
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 200 "로그인 화면으로 이동"`);
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        logger.info(`GET /register 200 "회원가입 화면으로 이동"`);
        res.render("home/register"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = await user.login();
        if (response.err) logger.error(`POST / 200 Response: "success: ${response.success}, ${response.err}"`)	// ←
        // console.log(response);
        logger.info(
            `POST / 200 Response: "success: ${response.success}, msg: ${response.msg}"`
        );
        return res.json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register(); // ←
        // console.log(response);
        logger.info(
            `POST /register 200 Response: "success: ${response.success}, msg: ${response.msg}"`
        );
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

info: 3000 포트에서 서버가 가동되었습니다.
info: GET /login 200 "로그인 화면으로 이동"
GET /login 200 6.847 ms - 911
error: POST / 200 Response: "success: false, Error: ER_NO_SUCH_TABLE: Table 'login_lecture.abc' doesn't exist"
POST /login 200 8.777 ms - 90

app>src>public>js>home>login.js--------------------

'use strict'; //ecma script 준수하겠다
const id = document.querySelector("#id"),
    psword = document.querySelector("#psword"),
    loginBtn = document.querySelector("#button");
loginBtn.addEventListener("click",login); // 두 번째 인수는 함수이다
function login(){
    if (!id.value) return alert("아이디를 입력해주십시오.");
    if (!psword.value)
      return alert("비밀번호를 입력해주십시오.");
    const req = {
        id: id.value,
        psword: psword.value,
    };
    fetch("/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())
      .then((res) => {
        if(res.success){
          location.href = "/";
        } else {
          if (res.err) return alert(res.err);	// ←
          alert(res.msg);
        }
      })
      .catch((err) => {
        console.error("로그인 중 에러 발생");
        // console.error(new Error("로그인 중 에러 발생"));
      });
};

====================

 

app>src>public>js>home>login.js--------------------

'use strict'; //ecma script 준수하겠다
const id = document.querySelector("#id"),
    name = document.querySelector("#name"),
    psword = document.querySelector("#psword"),
    confirmPsword = document.querySelector("#confirm-psword"),
    registerBtn = document.querySelector("#button");
registerBtn.addEventListener("click", register); // 두 번째 인수는 함수이다
function register(){
    if (!id.value) return alert("아이디를 입력해주십시오.");
    if (psword.value !== confirmPsword.value)
      return alert("비밀번호가 일치하지 않습니다.");
    const req = {
        id: id.value,
        name: name.value,
        psword: psword.value,
    };
    fetch("/register", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(req),
      })
      .then((res) => res.json())
      .then((res) => {
        if(res.success){
          location.href = "/login";
        } else {
          if (res.err) return alert(res.err);	// ←
          alert(res.msg);
        }
      })
      .catch((err) => {
        console.error("회원가입 중 에러 발생");
      });
};

====================

6:04

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger");
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {    // get 메서드에 해당
    ctrlindex: (req,res)=>{
        logger.info(`GET / 200 "홈 화면으로 이동"`);
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 200 "로그인 화면으로 이동"`);
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        logger.info(`GET /register 200 "회원가입 화면으로 이동"`);
        res.render("home/register"); // views\home
    },
};
// const users = {
//     id: ["newstep", "miero", "김팀장"],
//     psword: ["1234","1234","123456"],
// };
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = await user.login();
        if (response.err) 
            logger.error(
                `POST / 200 Response: "success: ${response.success}, ${response.err}"`
            );
        else
        // console.log(response);
            logger.info(
                `POST / 200 Response: "success: ${response.success}, msg: ${response.msg}"`
            );
        return res.json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register(); // ←
        // console.log(response);
        if (response.err)	// ←
            logger.error(	// ←
                `POST / 200 Response: "success: ${response.success}, ${response.err}"`	// ←
            );	// ←
        else	// ←
            logger.info(
                `POST /register 200 Response: "success: ${response.success}, msg: ${response.msg}"`
            );
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};

====================

테스트

app>src>models>UserStorage.js--------------------

"use strict";
const db = require("../config/db");
class UserStorage {
    static getUserInfo(id){
        return new Promise((resolve, reject) => {
            // const query = "SELECT * FROM users WHERE id = ?;";
            const query = "SELECT * FROM abc WHERE id = ?;";
            db.query(query, [id], (err, data) => {
                if (err) reject(`${err}`);
                else resolve(data[0]);
            });
        });
    }
    static async save(userInfo){
        return new Promise((resolve, reject) => {
            // const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";
            const query = "INSERT INTO abc (id, name, psword) VALUES (?,?,?);";	// ←
            db.query(query, [userInfo.id, userInfo.name, userInfo.psword], (err) => {
                if (err) reject(`${err}`);
                else resolve({ success: true });
            });
        });
    }
}
module.exports = UserStorage;

====================

없는 테이블로

cd app

npm start

192.168.1.65:3000/register

 

info: 3000 포트에서 서버가 가동되었습니다.
info: GET /register 200 "회원가입 화면으로 이동"
GET /register 304 9.570 ms - -
GET /favicon.ico 404 1.907 ms - 150
error: POST / 200 Response: "success: false, Error: ER_NO_SUCH_TABLE: Table 'login_lecture.abc' doesn't exist"
POST /register 200 41.926 ms - 90

 

app>src>config>logger.js--------------------

// const winston = require("winston");
const { createLogger, transports, format } = require("winston");
const { combine, timestamp, simple, colorize, printf, label } = format;
const printFormat = printf(({ timestamp, label, level, message }) => {
    return `${timestamp}  [${label}]  ${level} : ${message}`;
});
const printLogFormat = {
    file: combine(
    label({
        label: "백엔드 맛보기"
    }),
    // colorize(),
    // winston.format.simple()),
    timestamp({
        format: "YYYY-MM-DD HH:mm:dd"
    }),
    printFormat
    ),
    console: combine(
        colorize(),
        simple()
    ),
};
const opts = {
    file: new transports.File({
        filename: "./logs/access.log",
        dirname: "./logs",
        // level: "error",
        level: "info",
        format: printLogFormat.file,
    }),
    console: new transports.Console({
        level: "info",
        format: printLogFormat.console,
    })
}
const logger = createLogger({
    transports: [opts.file],
});
if (process.env.NODE_ENV !== "production") {
    logger.add(opts.console);
}
logger.stream = {	// ←
    write: (message) => logger.info(message),	// ←
};	// ←
module.exports = logger;

====================

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");	// ←
const logger = require("./src/config/logger");	// ←
const dotenv = require("dotenv");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const logger = require("./src/config/logger");
// logger.log("info","Hello 구독자님들.");
// logger.info("Hello 구독자님들.");
// logger.error("Hello 구독자님들.");
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("dev"));
app.use(morgan("common",{ stream: accessLogStream }));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

npm i morgan -S

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const logger = require("./src/config/logger");
const dotenv = require("dotenv");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js
// 앱 세팅
app.set("views", "./src/views");
app.set("view engine", "ejs");
app.use(express.static(`${__dirname}/src/public`));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan("common", { stream: logger.stream }));	// ←
// app.use(morgan("dev"),{ stream: 스트림 });
app.use(morgan("dev"));
app.use(morgan("common",{ stream: accessLogStream }));
app.use("/",home);
module.exports = app;

====================

8:26

info: GET /register 200 "회원가입 화면으로 이동"
info: ::ffff:192.168.1.65 - - [22/Mar/2022:06:42:56 +0000] "GET /register HTTP/1.1" 200 1130

GET /register 200 7.194 ms - 1130
info: ::ffff:192.168.1.65 - - [22/Mar/2022:06:42:57 +0000] "GET /favicon.ico HTTP/1.1" 404 150

GET /favicon.ico 404 1.130 ms - 150

 

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const logger = require("./src/config/logger");
const dotenv = require("dotenv");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const logger = require("./src/config/logger");
// logger.log("info","Hello 구독자님들.");
// logger.info("Hello 구독자님들.");
// logger.error("Hello 구독자님들.");
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views");
app.set("view engine", "ejs");
app.use(express.static(`${__dirname}/src/public`));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan("tiny", { stream: logger.stream }));	// ←
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

info: 3000 포트에서 서버가 가동되었습니다.
info: GET /register 200 "회원가입 화면으로 이동" // 우리가 직접 작성한 메시지
info: GET /register 304 - - 6.859 ms  // 이건 morgan

 

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const logger = require("./src/config/logger");
const dotenv = require("dotenv");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home");
// const logger = require("./src/config/logger");
// logger.log("info","Hello 구독자님들.");
// logger.info("Hello 구독자님들.");
// logger.error("Hello 구독자님들.");
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views");
app.set("view engine", "ejs");
app.use(express.static(`${__dirname}/src/public`));
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("tiny", { stream: logger.stream }));	// ← morgan 같이 사용하지 않겠구요
app.use("/",home);
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

app>app.js--------------------

'use strict'; //ecma script 준수하겠다
// 모듈
const express = require("express");
const bodyParser = require("body-parser");
// const morgan = require("morgan");
// const logger = require("./src/config/logger");
const dotenv = require("dotenv");
const app = express();
dotenv.config();
const accessLogStream = require("./src/config/log");
// port를 위로 빼자
const PORT = 3000;
// 라우팅
const home = require("./src/routes/home"); // index.js // routes폴더가 src폴더 안에 있다
// const logger = require("./src/config/logger");	// ← 지움
// logger.log("info","Hello 구독자님들.");	// ← 지움
// logger.info("Hello 구독자님들.");
// logger.error("Hello 구독자님들.");
// const accessLogStream = fs.createWriteStream(`${루트경로}/log/access.log`, { flags: 'a' })
// const accessLogStream = fs.createWriteStream(`${__dirname}/log/access.log`, { flags: 'a' })
// 앱 세팅
app.set("views", "./src/views"); // views폴더 위치 // views폴더가 src폴더 안에 있다
app.set("view engine", "ejs"); // view 엔진을 ejs 사용 - HTML과 비슷
app.use(express.static(`${__dirname}/src/public`)); // 현재 디렉토리 네임을 가져와서 /src/public폴더로 만들어주자
app.use(bodyParser.json());
// URL을 통해 전달되는 데이터에 한글, 공백 등과 같은 문자가 포함될 경우 제대로 인식되지 않는 문제 해결
app.use(bodyParser.urlencoded({extended: true}));
// app.use(morgan("common", { stream: logger.stream }));
// app.use(morgan("tiny", { stream: logger.stream }));	// ← 지움
// app.use(morgan("dev"),{ stream: 스트림 });
// app.use(morgan("dev"));
// app.use(morgan("common",{ stream: accessLogStream }));
app.use("/",home);  // use → 미들 웨어를 등록해주는 메서드.
// 서버 가동 부분 bin\www.js 별도 파일 만듬
module.exports = app; // 외부파일에서 사용할 수 있도록 보내기

====================

npm uninstall morgan

 

catch 로도 못잡은 error가 있을 수 있다

이것은 개인적으로 공부하자

git add .

git commit -m "winston 프로젝트에 적용"

git tag "v0.4.0-logManagement"

git push origin master

git push origin "v0.4.0-logManagement"

40[Node.js] 백엔드 맛보기 | 최적화 & HTTP 상태코드 (1/2)

git log

q

 

cd app

npm start

info: 3000 포트에서 서버가 가동되었습니다.

 

192.168.1.65:3000/login

info: GET /login 200 "로그인 화면으로 이동"

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger");
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {    // get 메서드에 해당
    ctrlindex: (req,res)=>{
        logger.info(`GET / 200 "홈 화면으로 이동"`);
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 200 "로그인 화면으로 이동"`);
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        logger.info(`GET /register 200 "회원가입 화면으로 이동"`);
        res.render("home/register"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = await user.login();
        const url = {
            method: "POST",
            path: "/login",
            status: "",
        };
        log(response, url);
        return res.json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register(); // ←
        // console.log(response);
        const url = {
            method: "POST",
            path: "/register",
            status: "",
        };
        log(response, url);
        return res.json(response);
        log(response);
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};
const log = (response, url) => {
    if (response.err) {
        logger.error(
            // `POST / 200 Response: ${response.success}, ${response.err}"`
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.err}`
        );
    } else {
    // console.log(response);
        logger.info(
            // `POST /login 200 Response: "success: ${response.success}, msg: ${response.msg}"`
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.msg}`
        );
    }
}

====================

app>src>models>UserStorage.js--------------------

"use strict";
const db = require("../config/db");
class UserStorage {
    static getUserInfo(id){
        return new Promise((resolve, reject) => {
            // const query = "SELECT * FROM users WHERE id = ?;";
            const query = "SELECT * FROM users WHERE id = ?;";	// ←
            db.query(query, [id], (err, data) => {
                if (err) reject(`${err}`);
                else resolve(data[0]);
            });
        });
    }
    static async save(userInfo){
        return new Promise((resolve, reject) => {
            // const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";
            const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";	// ←
            db.query(query, [userInfo.id, userInfo.name, userInfo.psword], (err) => {
                if (err) reject(`${err}`);
                else resolve({ success: true });
            });
        });
    }
}
module.exports = UserStorage;

====================

cd app

npm start

info: 3000 포트에서 서버가 가동되었습니다.

192.168.1.65:3000/login

miero

1234


info: GET /login 200 "로그인 화면으로 이동"
info: POST /login  Response: true undefined -------LOGIN 버튼을 눌렀을때 메시지, 데이터베이스에 있으니까 true
info: GET / 200 "홈 화면으로 이동"

 

undefined 수정해보자

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger");
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {    // get 메서드에 해당
    ctrlindex: (req,res)=>{
        logger.info(`GET / 200 "홈 화면으로 이동"`);
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 200 "로그인 화면으로 이동"`);
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        logger.info(`GET /register 200 "회원가입 화면으로 이동"`);
        res.render("home/register"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = await user.login();
        const url = {
            method: "POST",
            path: "/login",
            status: "",
        };
        log(response, url);
        return res.json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register(); // ←
        // console.log(response);
        const url = {
            method: "POST",
            path: "/register",
            status: "",
        };
        log(response, url);
        return res.json(response);
        log(response);
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};
const log = (response, url) => {
    if (response.err) {
        logger.error(
            // `POST / 200 Response: ${response.success}, ${response.err}"`
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.err}`
        );
    } else {
        logger.info(
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.msg || ""}`	// ←
        );
    }
};

====================

info: POST /login  Response: true 
info: GET / 200 "홈 화면으로 이동"

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger");
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {    // get 메서드에 해당
    ctrlindex: (req,res)=>{
        logger.info(`GET / 200 "홈 화면으로 이동"`);
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 200 "로그인 화면으로 이동"`);
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        logger.info(`GET /register 200 "회원가입 화면으로 이동"`);
        res.render("home/register"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = await user.login();
        const url = {
            method: "POST",
            path: "/login",
            status: response.err ? 400 : 200, // ←
        };
        log(response, url);
        return res.json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register();
        // console.log(response);
        const url = {
            method: "POST",
            path: "/register",
            status: response.err ? 400 : 200, // ←
        };
        log(response, url);
        return res.json(response);
        log(response);
        return res.json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};
const log = (response, url) => {
    if (response.err) {
        logger.error(
            // `POST / 200 Response: ${response.success}, ${response.err}"`
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.err}`
        );
    } else {
        logger.info(
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.msg || ""}`
        );
    }
};

====================

192.168.1.65:3000/login

miero

1234

 

info: GET /login 200 "로그인 화면으로 이동"
info: POST /login 200 Response: true 
info: GET / 200 "홈 화면으로 이동"

 

ctrl + shift + i

네트워크 창 상태에서

192.168.1.65:3000/login

miero

1234

 

Status

304 나온다

 

192.168.1.65:3000/login

miero

123

틀리면

ctrl + shift + i

네트워크 창 상태에서

Name Status

login  200 나온다

 

200 의미는 서버가 정상적으로 반환해 주었다는 의미

 

app>src>models>UserStorage.js--------------------

"use strict";
const db = require("../config/db");
class UserStorage {
    static getUserInfo(id){
        return new Promise((resolve, reject) => {
            // const query = "SELECT * FROM users WHERE id = ?;";
            const query = "SELECT * FROM abc WHERE id = ?;";	// ← 일부러 틀리게 하자
            db.query(query, [id], (err, data) => {
                if (err) reject(`${err}`);
                else resolve(data[0]);
            });
        });
    }
    static async save(userInfo){
        return new Promise((resolve, reject) => {
            // const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";
            const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";
            db.query(query, [userInfo.id, userInfo.name, userInfo.psword], (err) => {
                if (err) reject(`${err}`);
                else resolve({ success: true });
            });
        });
    }
}
module.exports = UserStorage;

====================

192.168.1.65:3000/login

miero

1234

 

info: 3000 포트에서 서버가 가동되었습니다.
info: GET /login 200 "로그인 화면으로 이동"
error: POST /login 400 Response: false Error: ER_NO_SUCH_TABLE: Table 'login_lecture.abc' doesn't exist

 

그런데

ctrl + shift + i

네트워크 창 상태에서

Name Status

login  200 나온다

 

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger");
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {    // get 메서드에 해당
    ctrlindex: (req,res)=>{
        logger.info(`GET / 200 "홈 화면으로 이동"`);
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 200 "로그인 화면으로 이동"`);
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        logger.info(`GET /register 200 "회원가입 화면으로 이동"`);
        res.render("home/register"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.login();
        const url = {
            method: "POST",
            path: "/login",
            status: response.err ? 400 : 200,
        };
        log(response, url);
        return res.status(url.status).json(response); // ←
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register();
        // console.log(response);
        const url = {
            method: "POST",
            path: "/register",
            status: response.err ? 400 : 200,
        };
        log(response, url);
        return res.status(url.status).json(response); // ←
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};
const log = (response, url) => {
    if (response.err) {
        logger.error(
            // `POST / 200 Response: ${response.success}, ${response.err}"`
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.err}`
        );
    } else {
        logger.info(
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.msg || ""}`
        );
    }
};

====================

192.168.1.65:3000/login

miero

1234

 

ctrl + shift + i

네트워크 창 상태에서

Name Status

login  400 나온다(에러 잘 나온다)

 

다음 시간에 HTTP상태코드 보자

41[Node.js] 백엔드 맛보기 | 최적화 & HTTP 상태코드 (2/2)

rendering될 때 상태코드

http 상태코드 - HTTP | MDN

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger");
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");
const ctrloutput = {
    ctrlindex: (req,res)=>{
        logger.info(`GET / 304 "홈 화면으로 이동"`);	// ←
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 304 "로그인 화면으로 이동"`);	// ←
        res.render("home/login");
    },
    register: (req,res)=>{
        logger.info(`GET /register 304 "회원가입 화면으로 이동"`);	// ←
        res.render("home/register"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.login();
        const url = {
            method: "POST",
            path: "/login",
            status: response.err ? 400 : 200,
        };
        log(response, url);
        return res.status(url.status).json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register();
        // console.log(response);
        const url = {
            method: "POST",
            path: "/register",
            status: response.err ? 400 : 200,
        };
        log(response, url);
        return res.status(url.status).json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};
const log = (response, url) => {
    if (response.err) {
        logger.error(
            // `POST / 200 Response: ${response.success}, ${response.err}"`
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.err}`
        );
    } else {
        logger.info(
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.msg || ""}`
        );
    }
};

====================

app>src>models>UserStorage.js--------------------

"use strict";
const db = require("../config/db");
class UserStorage {
    static getUserInfo(id){
        return new Promise((resolve, reject) => {
            // const query = "SELECT * FROM users WHERE id = ?;";
            const query = "SELECT * FROM users WHERE id = ?;";	// ←
            db.query(query, [id], (err, data) => {
                if (err) reject(`${err}`);
                else resolve(data[0]);
            });
        });
    }
    static async save(userInfo){
        return new Promise((resolve, reject) => {
            // const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";
            const query = "INSERT INTO users (id, name, psword) VALUES (?,?,?);";
            db.query(query, [userInfo.id, userInfo.name, userInfo.psword], (err) => {
                if (err) reject(`${err}`);
                else resolve({ success: true });
            });
        });
    }
}
module.exports = UserStorage;

====================

cd app

npm start

192.168.1.65:3000/login

abc 없는 아이디

123

존재하지 않는 아이디 입니다

4:10

app>src>routes>home>home.ctrl.js--------------------

"use strict";
const logger = require("../../config/logger");
const User = require("../../models/User");
// const UserStorage = require("../../models/UserStorage");    // 컨트롤러는 유저스토리지에 접근하지 않는다 지워주자
const ctrloutput = {    // get 메서드에 해당
    ctrlindex: (req,res)=>{
        logger.info(`GET / 304 "홈 화면으로 이동"`);
        res.render("home/index"); // views\home
    },
    ctrllogin: (req,res)=>{
        logger.info(`GET /login 304 "로그인 화면으로 이동"`);
        res.render("home/login"); // views\home
    },
    register: (req,res)=>{
        logger.info(`GET /register 304 "회원가입 화면으로 이동"`);
        res.render("home/register"); // views\home
    },
};
const ctrlprocess = {
    ctrllogin: async (req,res)=>{
        const user = new User(req.body); // app>src>models>User.js의 constructor(body)로 들어온다 // 인스턴스를 만들면
        const response = await user.login();
        const url = {
            method: "POST",
            path: "/login",
            status: response.err ? 400 : 200,
        };
        log(response, url);
        return res.status(url.status).json(response);
    },
    register: async (req,res)=>{
        const user = new User(req.body);
        const response = await user.register();
        // console.log(response);
        const url = {
            method: "POST",
            path: "/register",
            status: response.err ? 409 : 201,	// ←
        };
        log(response, url);
        return res.status(url.status).json(response);
    },
};
// 오브젝트 {key:value} 외부로 넘겨 주기
module.exports = {
    ctrloutput,
    ctrlprocess,
};
const log = (response, url) => {
    if (response.err) {
        logger.error(
            // `POST / 200 Response: ${response.success}, ${response.err}"`
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.err}`
        );
    } else {
        logger.info(
            `${url.method} ${url.path} ${url.status} Response: ${response.success} ${response.msg || ""}`
        );
    }
};

====================

git add .

git commit -m "백엔드 맛보기 최종 최적화"

git push origin master

git tag "v0.5.0-refactor"

git push origin v0.5.0-refactor