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

국비 지원 개발자 과정_Day49

by 루팽 2023. 2. 7.

<구글 로그인>

<html>
  <body>
    <script src="https://accounts.google.com/gsi/client" async defer></script>
    <div
      id="g_id_onload"
      data-client_id=""
      data-callback="handleCredentialResponse"
    ></div>
    <div class="g_id_signin" data-type="icon" data-shape="circle"></div>
    <script>
      function handleCredentialResponse(response) {
        // decodeJwtResponse() is a custom function defined by you
        // to decode the credential response.
        const responsePayload = parseJwt(response.credential);
        console.log("ID: " + responsePayload.sub);
        console.log("Full Name: " + responsePayload.name);
        console.log("Given Name: " + responsePayload.given_name);
        console.log("Family Name: " + responsePayload.family_name);
        console.log("Image URL: " + responsePayload.picture);
        console.log("Email: " + responsePayload.email);
      }
      function parseJwt(token) {
        var base64Url = token.split(".")[1];
        var base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
        var jsonPayload = decodeURIComponent(
          atob(base64)
            .split("")
            .map(function (c) {
              return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
            })
            .join("")
        );
        return JSON.parse(jsonPayload);
      }
    </script>
  </body>
</html>
<!--
    http://localhost:5500/google/googleLogin.html 로 테스트하면 됨
    주의 localhost대신 127.0.0.1은 절대 안됨
-->

 

<!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>구글로그인 - [모듈화 사용: type = "module"]</title>
  </head>
  <body>
    <!--
      type = text/javascript를 사용하는 경우와 module을 사용하는 경우 호환이 안 되는 부분 발생
      ECMAScript6기준으로 작업하는가? WWW CommonJS기준으로 작업하는가? -> 차이있음
    -->
    <script type="module">
      import { firebaseApp } from "../service/firebase.js";
      import AuthLogic from "../service/authLogic.js";

      console.log(firebaseApp);
      const authLogic = new AuthLogic();
      console.log(authLogic);

      const btnGoogle = document.querySelector("#btnGoogle");
      btnGoogle.addEventListener("click", (e) => {
        /* 
        button태그 사용시에 디폴트 타입이 submit이어서 폼 전송이 일어나게되며
        이럴 경우 해당 페이지에 리프레쉬 발생함에 따라 이상동작이 발생하므로
        반드시 button태그로 click이벤트 처리시에는 주의할 것!
        */
        e.preventDefault(); // submit 방지 용으로 추가 할 것!!(이벤트 버블링 방지)
        // console.log(e.target + e.currentTarget);
        authLogic.login("Google").then((snapshot) => {
          console.log(snapshot);
        });
      });
    </script>
    <button id="btnGoogle">구글로그인</button>
  </body>
</html>

 

// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.17.1/firebase-app.js";

// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: "",
  authDomain: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
};

// Initialize Firebase
export const firebaseApp = initializeApp(firebaseConfig);

 

import {
  getAuth,
  signInWithPopup,
  GithubAuthProvider,
  GoogleAuthProvider,
} from "https://www.gstatic.com/firebasejs/9.17.1/firebase-auth.js";
class AuthLogic {
  constructor() {
    this.firebaseAuth = getAuth();
    this.googleProvider = new GoogleAuthProvider();
    this.githubProvider = new GithubAuthProvider();
  }
  login(providerName) {
    // console.log("providerName : " + providerName);
    const authProvider = this.getProvider(providerName);
    // console.log("authProvider : " + authProvider);
    // console.log("this.firebaseAuth : " + this.firebaseAuth);
    //return signInWithPopup(this.firebaseAuth, authProvider);
    return signInWithPopup(this.firebaseAuth, authProvider);
  }

  logout() {
    this.firebaseAuth.signOut();
  }

  onAuthChange(onUserChanged) {
    this.firebaseAuth.onAuthStateChanged((user) => {
      onUserChanged(user);
    });
  }

  getProvider(providerName) {
    switch (providerName) {
      case "Google":
        return this.googleProvider;
      case "Github":
        return this.githubProvider;
      default:
        throw new Error(`not supported provider: ${providerName}`);
    }
  }
}

export default AuthLogic;

 

선언함수

이름이 있는 함수

따로 변수에 넣어주지 않고 선언할 때 붙여준 이름으로 호출함

function funcName () {
	// 실행코드 작성
}

funcName();

 

익명함수

이름이 없는 함수

익명함수를 선언하고 사용하기 위해선 변수에 넣어서 사용해야 함

const funcName = function () {
	alert('Hello');
};

funcName();

 

대입함수

js에서 함수는 객체이다

사이드 컨벤션

1. 일급함수

함수를 다른 변수와 동일하게 다룸(변수에 할당, 파라미터로 제공, 함수 반환)

 

2. 고차함수

함수를 반환하는 함수

// 1. 변수에 함수 할당
const foo = function() {
   console.log("foobar");
}

// 변수를 사용해 호출
foo();


// 2. 함수를 인자로 전달
// 다른 함수에 인자로 전달된 함수를 콜백 함수라고 함
function sayHello() {
   return "Hello, ";
}

function greeting(helloMessage, name) {
  console.log(helloMessage() + name);
}

// `sayHello`를 `greeting` 함수에 인자로 전달
// sayHello는 콜백함수!
greeting(sayHello, "JavaScript!");


// 3. 함수 반환
// 함수를 반환하는 함수를 고차 함수라고 함
function sayHello() {
   return function() {
      console.log("Hello!");
   }
}

 

즉시실행함수

정의되자마자 즉시 실행되는 함수

const result = (function () {
    const name = "Barry";
    return name;
})();

// 즉시 결과를 생성한다.
result; // "Barry"

 

<보드 판매량>

<!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>
    <!-- 
      외부 자바스크립트 파일 참조하기
      이럴 경우 시점의 문제 발생하니 주의
      해결 방법: 순서지향적인 처리, DOM 구성이 완료된 후에 html문서의 태그정보를 접근하려면 defer를 붙이기!
      이유는 코딩 순서대로 진행되기 때문에
    -->
    <script defer src="./board.js"></script>
    <link rel="stylesheet" href="./board.css" />
    <script type="text/javascript">
      // 전역변수 선언자리
      // 마진 버튼을 클릭했을 때 호출함수
      function getBoardSold() {
        console.log("getBoardSold");
        // createRequest(); 비동기 통신 객체를 생성하기
        xhrObject = createRequest(); // 비동기 통신 객체를 리턴값으로 받기
        console.log(xhrObject);
        const url = "./boardSellAction.html"; // 집계된 보드 판매량 수치
        xhrObject.open("GET", url, true); // true-async / false-sync(동기일거면 ajax 필요없음)
        xhrObject.onreadystatechange = soldProcess;
        xhrObject.send();
      }

      // 요청에 대한 응답이 다운로드 되었을 때
      // 서버로부터 전달된 상태값이 200번일 때
      // 호출되는 함수 - 콜백함수(어떤 조건이 만족되면 시스템이 호출해주는 함수)
      function soldProcess() {
        console.log("soldProcess 호출 => " + xhrObject.readyState);
        // 4 -> 다운로드가 완료됐을때(0~4상태값이 바뀔때마다 콜백함수 호출됨)
        if (xhrObject.readyState == 4) {
          // 200 -> 응답을 성공적으로 받음(응답이 정상처리됨)
          if (xhrObject.status == 200) {
            // 보드 판매량
            const newTotal = xhrObject.responseText; // 새로 받아온 값
            console.log(newTotal);
            const boardSoldEl = document.querySelector("#boardSold");
            replaceText(boardSoldEl, newTotal);

            // 구매가
            const costEl = document.querySelector("#cost");
            let cost = getText(costEl);

            // 소비자가
            const priceEl = document.querySelector("#price");
            let price = getText(priceEl);

            // 보드 1개당 마진 금액
            let cashPerBoard = price - cost;
            let cash = cashPerBoard * newTotal;
            console.log("마진금액은 " + cash);

            // 마진 금액 붙일 곳
            const cashEl = document.querySelector("#cash");
            replaceText(cashEl, cash);
          }
        }
      }
    </script>
  </head>
  <body>
    <!-- type을 생략하면 text/javascript -->
    <script>
      window.addEventListener("load", function (event) {
        const btnMargin = document.querySelector("#btnMargin");
        btnMargin.addEventListener("click", (event) => {
          event.preventDefault(); // submit으로인한 전송처리로 페이지가 새로고침 방지
          getBoardSold();
        });
      });
    </script>
    <h2>보드 판매량</h2>
    <table width="300px" height="80px">
      <tr>
        <th width="120px">보드 판매량</th>
        <td width="180px"><span id="boardSold">10</span></td>
      </tr>
      <!-- 
      소비자가-구매가=보드 한개당 마진 금액
      한개당 마진 금액*판매량=마진금액계산
      -->
      <tr>
        <th>구매가</th>
        <td><span id="cost">100</span>원</td>
      </tr>
      <tr>
        <th>소비자가</th>
        <td><span id="price">120</span>원</td>
      </tr>
    </table>
    <h2>마진금액 : <span id="cash">0</span>원</h2>
    <button type="submit" id="btnMargin">마진은?</button>
  </body>
</html>

 

30

 

body {
  font-family: sans-serif;
  text-align: center;
}

table {
  margin-left: auto;
  margin-right: auto;
  border: 1px solid black;
}

td,
th {
  border: 1px dotted gray;
  text-align: center;
}

th {
  background-color: #ffaaaa;
}

 

// 비동기 통신 객체 생성해서 담을 변수 선언
let xhrObject = null; // 선언

// 비동기 통신 객체 생성하는 함수 구현 - 리턴 예약어가 있어야 반환받을 수 있음
function createRequest() {
  // 자바스크립트에서도 예외처리가 가능하다
  try {
    xhrObject = new XMLHttpRequest(); // constructor, 생성자
  } catch (trymicrosoft) {
    try {
      // MS의 IE사용자 위한 객체 생성
      xhrObject = new XMLHttpRequest("Msxml2.XMLHTTP");
    } catch (error) {
      xhrObject = null;
    }
  }
  if (xhrObject == null) {
    alert("비동기 통신 객체 생성 에러");
  }
  return xhrObject;
} // end of createRequest

// span태그가 가지고 있는 텍스트 노드값을 읽어오기
// <td>100</td> -> 태그 이름이 없다, 속성을 정의 못한다, 아이디나 클래스를 정의하지 못함, 접근불가
// 해결방법 - 그래서 텍스트노드를 span으로 감싸고 id를 준다
// document.querySelector("#id")
// document.querySelector(".class")
// document.querySelector("태그이름")
// const costEl = document.querySelector("#cost"); 구매가
// const priceEl = document.querySelector("#price"); 소비자가
function getText(el) {
  let text = ""; // ES6 -> ECMAScript2015 - 적용안되는 브라우저이면 babel이 필요(js컴파일러) 또는 번들러(parcel)
  if (el != null) {
    // el이 null, undefuned, "", NaN이 아닌 경우 true여서 아래 if문 들어감
    if (el.childNodes) {
      // costEl, priceEl
      console.log(el + "," + el.childNodes.length); // 길이 1
      for (let i = 0; i < el.childNodes.length; i++) {
        let childNode = el.childNodes[i];
        //너 텍스트 노드니?
        if (childNode.nodeValue != null) {
          text = text + childNode.nodeValue;
        }
      }
    }
  }
  return text;
}

// 기존 TextNode의 값을 다른 문자열로 바꾸기
/***********************************************
	param1 :document.getElementById("boardSold")
	param1 :document.querySelector("#boardSold")
	param2 :xhrObject.
	************************************************/
// el -> boardSoldEl(보드판매량), cashEl(마진계산) -> span태그
function replaceText(el, value) {
  // 여기 들어오는 el은 span
  if (el != null) {
    clearText(el); // 기존에 있던 10을 지우기
    // 새로운 텍스트 노드 value(파라미터로 받은 수)를 생성하기
    var newNode = document.createTextNode(value);
    // 위에서 생성한 텍스트 노드 값을 el에 붙이는 함수 호출하기
    el.appendChild(newNode); // <span>10</span> -> <span></span> -> <span>20</span>
  }
}

// 기존 태그안에 문자열 지우는 함수 구현
function clearText(el) {
  if (el != null) {
    // 자바스크립트에서는 0이 아닌 건 모두 참이다
    if (el.childNodes) {
      for (let i = 0; i < el.childNodes.length; i++) {
        let childNode = el.childNodes[i];
        el.removeChild(childNode); // 해당 el 삭제하기 - DOM API -> 직관적이지 않다, 유지보수 어렵다
      }
    }
  }
}

댓글