<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>실습 - submit 이슈</title>
<script>
// 이벤트가 전이되는 것을 차단하기 - e.preventDefault()
// 테스트 시나리오 - preventDefault를 했을 때와 안 했을 때(없을 때)
// preventDefault가 없으면 새로고침 됨 - submit 전송 - 새로고침(부작용)
// get방식 -> query string 사용자가 입력한 값이 올라탄다 ?mem_id=kiwi
// 콘솔에 찍고 싶은데 잠깐 보여줬다가 사라짐. 왜? 새로고침이 일어나니까(날라가는 것)
// preventDefault를 했을 때는 새로고침이 안 일어나니까 콘솔창에서 볼 수 있다
function login(event){
console.log(event.target);
console.log('로그인 호출 성공');
document.getElementById('f_login').submit();
}
</script>
</head>
<body>
<form id="f_login" method="get" action="">
<input type="text" name="mem_id" id="mem_id">
<input type="button" value="로그인" onclick="login(event)">
<button id="btnLogin">로그인2</button>
</form>
<script>
const flogin = document.querySelector("#f_login");
const login2 = (event) => {
// event.preventDefault();
event.preventDefault();
console.log(event);
}
flogin.addEventListener('submit',login2); // 콜백함수
</script>
</body>
</html>
// 구조분해 할당
// 1. 배열
const colors = ['red','green','blue'];
// ES5
const color1 = colors[0];
const color2 = colors[1];
const color3 = colors[2];
// ES6 - 구조분해할당 문법 지원
const[c1, c2, c3] = colors;
console.log(c1+c2+c3); // 'redgreenblue'
// 2. 객체
const dept = {
deptno: 10,
dname: '개발부',
loc: '서울'
}
const {deptno, dname, loc} = dept
// ES5
console.log(dept.deptno);
console.log(dept['dname']);
console.log(deptno);
console.log(dname);
console.log(loc);
// 배열 -> filter -> 얕은복사 or 깊은복사
const words = ['spray', 'elite', 'exuberant', 'destruction', 'present'];
// -> filter는 다른 여러 객체에서도 재사용할 수 있는 prototype
// -> filter함수는 리턴타입이 배열이다. 그런데 깊은 복사이다 - 새로운 배열이다
// 결론: 두 배열이 주소번지가 다른 것이다
const result = words.filter((word) => word.length > 6);
console.log(typeof result);
console.log(result.length);
words.push('abcdefg');
console.log(words);
console.log(result); // filter타입 -> 깊은 복사라는 걸 알아야 한다
console.log(result);
// Expected output: Array ["exuberant", "destruction", "present"]
// 배열에 대한 초기화를 한 줄로 끝냄 - 구조분해 할당 -> react -> props
const [r1,r2,r3] = result;
console.log(r1);
console.log(r2);
console.log(r3);
import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.22.1/firebase-app.js';
const firebaseConfig = {
firebase에서 apikey 정보 담기
};
// Initialize Firebase
export const app = initializeApp(firebaseConfig);
import {
getAuth,
GithubAuthProvider,
GoogleAuthProvider,
} from 'https://www.gstatic.com/firebasejs/9.22.1/firebase-auth.js';
class AuthLogic {
constructor() {
this.auth = getAuth();
this.gitProvider = new GithubAuthProvider();
this.googleProvider = new GoogleAuthProvider();
}
getUserAuth = () => {
return this.auth;
};
getGoogleAuthProvider = () => {
return this.googleProvider;
};
} // end of AuthLogic
// import { AuthLogic } from "./service/authLogic.js"
// export 뒤에 default가 있을 때는 좌중괄호 우중괄호 안 됨
export default AuthLogic;
// import { loginGoogle, loginKakao, logout } from "./service/authLogic.js"
// (authLogic.loginGoogle 이렇게 쓰고 싶지 않음)
// 클래스의 주소번지 없이도 html,js에서(css는 X) 호출하고 싶다면
// 함수 선언 앞에 export 붙인다
// 로그아웃 할 때(html에서 버튼누를 때) 호출되는 함수이다
// 파라미터에는 auth가 필요하다
// 이 auth는 어떤 과정을 거쳤나: firebase.js 통과 - app을 얻게 됨 - 이 app을 통해 getAuth(인증정보가 있을 것이다)
// 파라미터로 auth를 넣어줘야 signOut() 호출이 가능하다
// 이 때 에러가 발생하면(인증토큰 없다 - 우리 가족이 아니다 - 너 url로 접근하려는 거야?)
// 인정한 통로가 아닌 곳으로 오는 너는 침입자 - catch -> 403
// catch에 잡힌 너는 reject에서 처리할게 - 인터셉트
export const logout = (auth) => {
return new Promise((resolve, reject) => {
auth. signOut().catch(e=>reject(alert(e+":로그아웃 에러 발생")))
// 원서비스에서는 세션에서 관장해야 한다 - 구글 서버측에서 담당 -> signOut()
localStorage.removeItem('uid'); // uid를 쥐고 있다는 건 구글 서버로부터 정상적으로 토큰을 받았고 그 결과 uid 갖게 됨
resolve()
})
}
export const loginGoogle = (params) => {
return new Promise((resolve, reject) => {
signInWithEmailAndPassword(auth, googleProvider)
.then((result) => {})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
});
});
}; //end of loginGoogle
export const loginKakao = (params) => {
return new Promise((resolve, reject) => {
try {
const response = axios({
method: 'get',
url: '카카오토큰을 받아올 URL주소 -카카오개발자 센터 긁어옴',
params: params,
});
console.log(response);
resolve(response);
} catch (error) {
reject(error);
}
});
};
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>도서관리시스템 - html활용코드</title>
</head>
<body>
<button id="btnLogin">로그인</button>
<button id="btnLogout">로그아웃</button>
<script type="module">
import { firebaseApp } from "../service/firebase.js"
import { getAuth } from "https://www.gstatic.com/firebasejs/9.22.1/firebase-auth.js";
import AuthLogic from "../service/authLogic.js"
const auth = getAuth(firebaseApp);
console.log(auth);
// authLogic.js에서 구현한 클래스를 인스턴스화 하기
const authLogic = new AuthLogic();
// 객체생성이 되었으니까 전변을 호출할 수 있다
// console.log(authLogic.googleProvider);
// console.log(authLogic['googleProvider']);
</script>
</body>
</html>
firebase 문서 - 빌드 - 인증 - 웹
https://firebase.google.com/docs/auth/web/google-signin?hl=ko
도서관리시스템
도서목록(조건검색조회포함)
페이징처리
도서상세보기 - 모달
카카오페이, 카카오지도, 네이버로그인, 토스증권 결제
import { firebaseApp } from "../service/firebase.js"; // 초기화 작업함 - 준비과정 - app객체를 돌려받음
/* 돌려받은 app 객체로 무엇을 했나?
-> getAuth함수를 호출할 때 파라미터 자리에 앱 객체를 넣었다
const auth = getAuth(app);
auth는 어떤 정보를 쥐고 있나?
localhost:5500/xxxx/index.html -> 로그인버튼 -> 전처리(로그인 위한 사전단계) 필요함 -> auth 쥐고 있어야 한다
auth 객체는 어떻게, 언제, 왜 쥐어야 하나?
-> auth 객체가 있어야 로그인하는 함수호출이 가능하니까 콜백함수로 로그인을 누르기 전까지 쥐어야 함
*/
import { getAuth } from "https://www.gstatic.com/firebasejs/9.22.1/firebase-auth.js";
import AuthLogic from "../service/authLogic.js"
import { loginGoogle } from "../service/authLogic.js"
const auth = getAuth(firebaseApp);
/
팝업은 누가 띄웠나? 구글. 구글에서 만들어놓은 모달이 출력됨
signInWithPopup(auth, 서비스제공업체-google: 전역변수로 googleProvider)
이 함수가 호출되었을 때 팝업이 열림
-> 처리단계 진행(구글서버가 진행) -> 구글에서 처리해주는 시간이 있으니 지연 발생 -> waiting이 벌어짐 -> 그런데 자바스크립트는 절차지향적이어서 순서가 그 다음으로 진행하는데, 그러면 안 되니까 우리는 응답을 받을 때까지 기다리라고 해야 한다 -> 비동기처리를 해야 함 -> 이 비동기 처리를 위해 async 예약어를 함수 앞에 붙이고 await을 콜 -> await loginGoogle(auth, googleProvider) -> 기다림 -> 응답 -> 알림이 옴 -> 메세지로 push -> 듣게 됨 -> 들은 내용을 가지고 처리 -> 처리가 되면 콜백함수를 쓰는 것 then((result)=>{})(콘솔로그에 result를 찍어본다) -> 이걸 문자열로 바꿔야 하니 stringify
고차함수 return new Promise((resolve[성공],reject[실패])=>{})
성공해서 돌려받은 데이터를 resolve의 파라미터로 넘겨준다. 왜? 리턴받아야 index.html에서 출력할 수 있으니까
돌려받은 건 authLogic.js에서 돌려받았는데 이걸 사용하는 것은 index.html에서 사용해야 하니까 반환값을 사용함
/
파이어베이스 콘솔
Authentification: 등록 -> 프로젝트 생성 -> API key 받음
npm 방식(로컬처리방식 - npm i firebase) or cdn 방식(url을 통해서 import)이 있음 - 5500 포트를 사용하고 있음(Live Server가 제공하는 포트)
npm 방식으로 한다면 추가 설정 필요(build와 관련된 작업이 필요) - build 파셀, 웹팩, babel...
구글개발자 콘솔
clientID 발급 받음 -> 도메인 추가함 -> 승인된 도메인이 클라이언트 도메인이 추가돼있어야 함
단, 구글개발자 콘솔에서 프로젝트를 생성하고 받은 키는 필요없었음
Youtube 라이브러리
도메인을 추가할 때 127.0.0.1은 등록이 안 되므로 사용 X
<!DOCTYPE html>
<html>
<head>
<title>한빛출판사</title>
<link rel="stylesheet" href="/stylesheets/style.css" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
crossorigin="anonymous"
/>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
crossorigin="anonymous"
></script>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.min.js"></script>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.min.css"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick-theme.min.css"
/>
</head>
<body>
<div class="container">
<%-include("header.ejs")%>
<div id="loading" class="row my-5">
<div class="col my-5">
<img src="/images/loading.gif" alt="로딩이미지" />
</div>
</div>
<%-include(pageName)%> <%-include("footer.ejs")%>
</div>
</body>
<script>
// DOM이 다 그려진 거야?
$(document).on('ready', () => {
setTimeout(() => {
$('#loading').hide();
}, 1000);
});
</script>
</html>
<div class="row my-5 justify-content-center">
<div class="col-8 col-md-6 col-lg-4">
<h3 class="text-center mb-5">로그인</h3>
<form name="frm" method="post">
<div class="input-group my-2">
<div class="input-group-text">이 메 일</div>
<input class="form-control" name="email" value="tomato@hot.com" />
</div>
<div class="input-group">
<div class="input-group-text">비밀번호</div>
<input
class="form-control"
name="password"
type="password"
value="12345678"
/>
</div>
<div class="my-3">
<!--
<input type=button> or <button> 기본적으로 submit속성이 내장됨
-->
<button class="btn btn-success w-100">로그인</button>
</div>
<!-- 회원가입 링크경로는 반드시 router/ 생각할 것 -->
<div class="text-end mt-3"><a href="/users/join">회원가입</a></div>
</form>
</div>
</div>
<script type="module">
import { app } from '/javascripts/firebase.js';
import {
getAuth,
signInWithEmailAndPassword,
} from 'https://www.gstatic.com/firebasejs/9.22.1/firebase-auth.js';
const auth = getAuth(app);
console.log(auth);
//로그인 버튼을 눌렀을 때
//submit이슈 - submit이벤트를 처리할때 캡쳐링으로 인한 이벤트 전이가 발생함 - 방어해야함
$(frm).on('submit', function (e) {
console.log('로그인버튼 클릭');
e.preventDefault();
//사용자가 화면에 입력한 이멜 주소 담기
let email = $(frm.email).val();
//사용자가 화면에 입력한 비번 담기
let password = $(frm.password).val();
console.log(`${email} ${password}`);
//https://firebase.google.com/docs/auth/web/start?hl=ko&authuser=0
//기존 사용자가 자신의 이메일 주소와 비밀번호를 사용해 로그인할 수 있는 양식을 만듭니다.
//사용자가 양식을 작성하면 signInWithEmailAndPassword 메서드를 호출합니다.
signInWithEmailAndPassword(auth, email, password)
.then((response) => {
// Signed in
const user = response.user;
//JSON.stringify(user) -> string으로 변환이 되어서 글자를 알아볼 수 있다 - Object를 출력하지 않고
console.log(`user ===> ${JSON.stringify(user)}`); //[object, Object] - JSON.parse():JSON-Array
console.log(`uid ====> ${user.uid}`);
console.log(`email ====> ${user.email}`);
localStorage.setItem('uid', `${user.uid}`); //로컬 브라우저 저장소에 담음
localStorage.setItem('email', `${user.email}`); //로컬 브라우저 저장소에 담음
location.href = '/';
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
});
});
</script>
var express = require('express');//외부 프레밍워크 가져올때
var router = express.Router();//페이지 전환
/* GET home page.
express가 Restful API를 지원해서 웹 서비스를 제공할 수 있게 해준다.(서블릿, JSP)
router는 페이지 전환 해주는 API로 - 화면 전환 처리 이벤트
get함수의 첫번째 파라미터가 요청에 대한 URL 주소이다.
URL주소마다 자바단에서는 메소드를 설계(구현)해야 한다.
*/
router.get('/', function(req, res, next) {
res.render('index', { title: '도서관리시스템' , pageName:"home.ejs"});
});
router.get('/login', function(req, res, next) {//app.js -> path 라이브러리 __dirname, views
res.render('index', { title: '로그인', pageName: "auth/login.ejs" });
});
module.exports = router;
<div class="row my-5 justify-content-center">
<div class="col-8 col-md-6 col-lg-4">
<h3 class="text-center mb-5">회원가입</h3>
<form name="frm" method="post">
<div class="input-group my-2">
<div class="input-group-text">이 메 일</div>
<input class="form-control" name="email" value="tomato@hot.com" />
</div>
<div class="input-group">
<div class="input-group-text">비밀번호</div>
<input
class="form-control"
name="password"
type="password"
value="12345678"
/>
</div>
<div class="my-3">
<button class="btn btn-success w-100">회원가입</button>
</div>
<div class="text-end mt-3"><a href="/login">로그인</a></div>
</form>
</div>
</div>
<script type="module">
import { app } from '/javascripts/firebase.js';
import {
getAuth,
createUserWithEmailAndPassword,
} from 'https://www.gstatic.com/firebasejs/9.22.1/firebase-auth.js';
const auth = getAuth(app);
console.log(auth);
$(frm).on('submit', function (e) {
console.log('회원가입 버튼 클릭');
e.preventDefault();
let email = $(frm.email).val();
// 사용자가 화면에 입력한 비번 담기
let password = $(frm.password).val();
console.log(`${email} ${password}`);
createUserWithEmailAndPassword(auth, email, password)
.then((response) => {
// 회원가입에 성공하면
console.log(response);
location.href = '/login';
})
.catch((error) => alert(error.message));
}); // end of createUserWithEmailAndPassword
</script>
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function (req, res, next) {
res.send('respond with a resource');
});
router.get('/join', function (req, res, next) {
res.render('index', { title: '회원가입', pageName: 'users/join.ejs' });
});
router.get('/cart', function (req, res, next) {
// res.send();파라미터 문자열이 출력되고 나는 장바구니 화면을 출력할거니까 render함수 호출함
res.render('index', { title: '장바구니', pageName: 'users/cart.ejs' });
});
router.get('/mypage', function (req, res, next) {
res.render('index', { title: '마이페이지', pageName: 'users/mypage.ejs' });
});
module.exports = router;
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>실습 - Handlebars[템플릿엔진]</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
crossorigin="anonymous"
/>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
crossorigin="anonymous"
></script>
<!-- cdn: 가장 가까운 서버에서 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.1/handlebars.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
</head>
<body>
<!--
x-handlebars-template sub mime type은 표준이 아니다?
표준이 아니라는 건 재해석이 필요하다 - 모르는 애
핸들바스로 되어있는 템플릿 컴파일 합니다
-->
<script id="tb-dept" type="text/x-handlebars-template">
<table class='table'>
<!-- header 영역 시작 -->
<thead>
<tr>
<th scope='col'>부서번호</th>
<th scope='col'>부서명</th>
<th scope='col'>지역</th>
</tr>
</thead>
<!-- header 영역 끝 -->
<!-- 데이터셋 추가하는 화면 제공되는 영역 시작 -->
<tbody>
{{#depts}}
<tr>
<td>{{deptno}}</td>
<td>{{dname}}</td>
<td>{{loc}}</td>
</tr>
{{/depts}}
</tbody>
<!-- 데이터셋 추가하는 화면 제공되는 영역 끝 -->
</table>
</script>
</body>
<script>
// 핸들바스 템플릿을 가져옵니다
const tb_dept = $('#tb-dept').html();
const template = Handlebars.compile(tb_dept);
// 핸들바스 템플릿에 바인딩 될 데이터셋입니다 - 내부는 Array
const data = {
depts: [
{ deptno: 10, dname: '개발1팀', loc: '서울' },
{ deptno: 20, dname: '운영팀', loc: '제주' },
{ deptno: 30, dname: '품질관리팀', loc: '세종' },
],
};
// 핸들바 템플릿에 데이터를 바인딩해서 html을 새로 생성함
const deptList = template(data);
// 위에서 생성된 템플릿을 body태그에 붙인다(추가)
$('body').append(deptList);
</script>
</html>
<!--
select된 결과가 3건이라면 for문을 돌려서 한 개 로우씩 3번 반복되어야 한다
문제제기:자바코드와 태그코드가 섞이는게 불편하다
: 1. 가독성 - DOM Tree -> 태그로만 작성해 본다(이쪽이 더 유리)
: 2. 디자인과 로직은 분리되어야 한다
: 좌중괄호 우중괄호 짝이 안 맞으면 500번 에러가 발생
-> 대안으로 템플릿 엔진을 지원하게 되었다
-->
URL 파라미터 가져오기
https://gurtn.tistory.com/126