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에 접근하지 않는다
"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;
다르면
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를 제공하고 있다
찍고 요 promise 라는 것을 불러 오면 되요
const fs=require("fs").promises
Promise는 약속이라는 의미로 Promise가 수행하는 동작이 끝남과 동시에
상태를 알려주기 때문에 비동기 처리에 아주 효과적입니다
"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;
Promise { <pending> }
undefined
"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;
"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;
"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;
"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;
"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;
"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;
{ id: 'miero', psword: '1234', name: '미에로' }
{ id: 'miero', psword: '1234', name: '미에로' }
"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: '미에로' }
"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,
};
서버 가동
{ id: 'miero', psword: '1234', name: '미에로' }
"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>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;
"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;
"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;
====================
28[Node.js] 백엔드 맛보기 | 파일 DB로 회원가입 구현 | promise와 async await 으로 비동기 최적화
"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;
"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,
};
"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;
"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;
"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;
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("회원가입 중 에러 발생");
});
};
====================
a
{
"id":["newstep","miero","nextlevel"],
"psword":["1234","1234","123456"],
"name":["뉴스텝","미에로","넥스트레벨"]
}
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); // ←
}
"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;
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;
{"id":["newstep","miero","nextlevel","aaa"],"psword":["1234","1234","123456","1234"],"name":["뉴스텝","미에로","넥스트레벨","에에에"]}
이거 를 인스톨 해 줘 보세요 그런 다음에 바로 되는게 아니에요
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;
"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;
"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,
};
에러 처리는 어떻게 하냐면 요
"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;
"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;
Error: 이미 존재하는 아이디입니다.
"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;
"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: 이미 존재하는 아이디입니다.
"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: 이미 존재하는 아이디입니다.
"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;
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;
"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;
{"id":["newstep","miero","nextlevel","aaa","구독"],"psword":["1234","1234","123456","1234","1234"],"name":["뉴스텝","미에로","넥스트레벨","에에에","좋아요"]}
git add .
git commit -m "fs모듈을 통한 회원가입 기능 구현"
git push origin master
29서버 API 테스트 도구 | Postman | curl
curl http://localhost:3000/login
curl http://localhost:3000/register -X -d '{"id":"miero123","psword":"1234"}' -H "Content-Type: application/json"
{"success":true}% 가 되었구요
4:32
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--------------------
[0mGET /login [36m304[0m 6.579 ms - -[0m
[0mGET /register [36m304[0m 1.203 ms - -[0m
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
'컴퓨터 > nodejs' 카테고리의 다른 글
Node.js & MySQL 생활코딩 (0) | 2023.03.23 |
---|---|
Node.js server 코딩애플 (0) | 2023.02.28 |
callback 함수의 이해, 한글인코딩, 변수, API서버만들기, promise, async, await (0) | 2022.12.15 |
Node.js 다음메일 여러 개 보내기 (0) | 2022.01.10 |
nodejs pm2 메모 (0) | 2021.10.13 |