"type": "module",
packge.json에 등록한다
생략하면 CommonJS이므로 반드시 module 등록한 후 사용 가능(주의할 것!)
<step 1>
export default 10; // 1개밖에 사용 못함, default사용하면 {} 사용불가!
export const insa = "hello";
export const names = ["apple", "kiwi", "tomato"];
export const hap = (i, j) => {
return i + j;
};
export class Sonata {
constructor() {
this.wheelNum = 4;
this.speed = 10;
}
speedUp = () => {
this.speed = this.speed + 1;
};
}
/*
호이스팅 이슈
1) var i
2) head태그 안에 선언한 함수
3) import문 - 모듈사용(ES6, 브라우저지원)
함수선언
1) 선언형 함수
2) 익명함수 - 콜백함수(나중에 실행) -> JS는 동기적
전제조건: JS에서는 함수도 객체다
3) 대입함수 - 일급함수 -> 고차함수[리덕스(리액트 상태관리 구현한것) 만드는데 결정적 역할] -> 리액트
const func = () => {}
4) 즉시실행함수 (){} - ES6 이전에는 호이스팅 이슈를 해결하는 방법으로 사용됨
*/
import number from "./module1.js";
import { insa, names, hap, Sonata } from "./module1.js";
console.log(number); // 10
console.log(insa); // hello
console.log(names); // [ 'apple', 'kiwi', 'tomato' ]
console.log(hap); // [Function: hap]
const myCar = new Sonata();
console.log(`내 자동차의 바퀴수는 ${myCar.wheelNum}`); // 내 자동차의 바퀴수는 4
myCar.speedUp();
console.log(`현재 소나타의 속도는 ${myCar.speed}`); // 현재 소나타의 속도는 11
import * as all from "./module1.js";
console.log(all);
/* [Module: null prototype] {
Sonata: [class Sonata],
default: 10,
hap: [Function: hap],
insa: 'hello',
names: [ 'apple', 'kiwi', 'tomato' ]
} */
console.log(all.insa); // hello
console.log(all.names); // [ 'apple', 'kiwi', 'tomato' ]
console.log(all.hap); // [Function: hap]
/*
매개변수로 함수를 받을 수 있다는 것은 함수가 객체라는 의미
리턴타입을 함수로 사용 가능한 것은 고차함수
변수가 함수를 참조할 수 있는 것은 일급함수
이런 것들이 가능한 객체를 일급 객체라고함
*/
const myCar = new all.Sonata();
console.log(`내 자동차의 바퀴수는 ${myCar.wheelNum}`); // 내 자동차의 바퀴수는 4
myCar.speedUp();
console.log(`현재 소나타의 속도는 ${myCar.speed}`); // 현재 소나타의 속도는 11
console.log(1);
setTimeout(() => {
console.log(2);
}, 2000); // mili sec 1000이 1초임
console.log(hap(1, 3)); /// import문이 뒤에 있음에도 4가 출력됨 -> 호이스팅 발생
/* import문도 호이스팅이 일어남 */
import { hap } from "./module1.js";
console.log(3);
/*
1
4
3
2
*/
<step 2>
export const one = () => {
return 1;
};
export const two = () => {
return 2;
};
export { one } from "./one.js";
export { two } from "./two.js";
// 모듈을 가져오자마자 내보내기도 가능
import { one, two } from "./common.js";
console.log(one()); // 1
console.log(two()); // 2
kakaomap api
1. npm init -y
package.json 생성됨
2. index.js 파일 추가한 뒤 console.log('123')
3. package.json에 아래 내용 수정함
"scripts": {
"dev": "parcel ./index.html",
"build": "parcel build ./index.html" },
4. 실행 시에는 npm run dev
5. 콘솔창에 http://localhost:1234 ctrl+클릭
6. 해당 파일이 열림
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Kakao 지도 시작하기</title>
</head>
<body>
<div id="map" style="width: 700px; height: 500px"></div>
<script
type="text/javascript"
src="//dapi.kakao.com/v2/maps/sdk.js?appkey="
></script>
<script>
const container = document.getElementById("map");
const options = {
center: new kakao.maps.LatLng(37.4989931, 127.0329085),
level: 2,
};
const map = new kakao.maps.Map(container, options);
const marker = new kakao.maps.Marker({
position: new kakao.maps.LatLng(37.4989931, 127.0329085),
});
marker.setMap(map);
</script>
</body>
</html>
동기(synchronous)
코드를 순차적으로 실행
비동기(asynchronous)
코드를 비순차적으로 실행
<동기와 비동기 step 1>
setTimeout(() => {
console.log("상품조회");
}, 3000);
console.log("장바구니담기");
console.log("결제");
console.log("배송준비");
/*
비동기, 순서x
장바구니담기
결제
배송준비
상품조회
*/
<동기와 비동기 step 2>
<!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>
<button id="btnCart">장바구니담기</button>
<script src="./main2.js"></script>
</body>
</html>
const btnCart = document.querySelector("#btnCart");
// 자바스크립트는 기본적으로 동적 처리이다
// 그러나 실생활에서는 비동기적 상황들이 훨씬 많이 일어난다
btnCart.addEventListener("click", () => {
console.log("카트담기");
});
console.log("여기");
<callback패턴 1>
// 콜백(callbak) 패턴
const goodSearch = () => console.log("상품조회");
const cart = () => console.log("카트담기");
goodSearch();
cart();
/*
상품조회
카트담기
*/
<callback패턴 2 - 지연발생>
// 콜백(callbak) 패턴
const goodSearch = () => {
setTimeout(() => {
console.log("상품조회");
}, 2000);
};
const cart = () => console.log("카트담기");
goodSearch();
cart();
/*
카트담기
상품조회
*/
<callback패턴 3 - 콜백함수>
// 콜백(callbak) 패턴
const goodSearch = (callback) => {
setTimeout(() => {
console.log("상품조회");
callback();
}, 2000);
};
const cart = () => console.log("카트담기");
// 함수도 객체 -> 파라미터(일급함수), 리턴타입(고차함수)으로 넘길 수 있다
goodSearch(() => {
cart();
});
/*
상품조회
카트담기
*/
<callback패턴 4 - 결제하기 추가>
// 콜백(callbak) 패턴
const goodSearch = (callback) => {
setTimeout(() => {
console.log("상품조회");
callback();
}, 3000);
};
const cart = (callback) => {
setTimeout(() => {
console.log("카트담기");
callback();
}, 2000);
};
const account = () => console.log("결제하기");
goodSearch(() => {
cart(() => {
account();
});
});
/*
상품조회
카트담기
결제하기
*/
<callback패턴 5 - 배송하기 추가>
// 콜백(callbak) 패턴
const goodSearch = (callback) => {
setTimeout(() => {
console.log("상품조회");
callback();
}, 3000);
};
const cart = (callback) => {
setTimeout(() => {
console.log("카트담기");
callback();
}, 2000);
};
const account = (callback) => {
setTimeout(() => {
console.log("결제하기");
callback();
}, 4000);
};
const delivery = () => console.log("배송하기");
goodSearch(() => {
cart(() => {
account(() => {
delivery();
});
});
});
/*
상품조회
카트담기
결제하기
배송하기
*/
/*
이처럼 순서대로 일처리를 위해 콜백을 계속 반복해서 작성해야하고
바깥쪽에서 안쪽으로 계속적인 들여쓰기가 되면서 해석하기도 불편하고
유지보수도 어려워진다.
이것을 콜백지옥이라고함
*/
<Promise prototype 활용 1>
// Promise prototype 활용
const goodSearch = () => {
// 고차함수(함수 반환함)
// 설공시 resolve 콜백, 실패시 reject 콜백
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("상품조회");
resolve();
}, 2000);
});
};
const cart = () => console.log("카트담기");
// goodSearch함수가 호출될 때 콜백에서 cart함수를 호출하면
// 순서가 보장된다
goodSearch().then(() => {
cart();
});
/*
상품조회
카트담기
*/
<Promise prototype 활용 2 - 결제하기 추가>
// Promise prototype 활용
const goodSearch = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("상품조회");
resolve();
}, 3000);
});
};
const cart = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("카트담기");
resolve();
}, 2000);
});
};
const account = () => console.log("결제하기");
goodSearch()
.then(() => {
return cart();
})
.then(() => {
return account();
});
/*
상품조회
카트담기
결제하기
*/
<Promise prototype 활용 3 - 배송하기 추가>
// Promise prototype 활용
const goodSearch = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("상품조회");
resolve();
}, 3000);
});
};
const cart = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("카트담기");
resolve();
}, 2000);
});
};
const account = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("결제하기");
resolve();
}, 2000);
});
};
const delivery = () => console.log("배송하기");
goodSearch()
.then(() => {
return cart();
})
.then(() => {
return account();
})
.then(() => {
return delivery();
});
/*
상품조회
카트담기
결제하기
배송하기
*/
<Promise prototype 활용 4 - fetch형식으로 바꾸기 1>
// Promise prototype 활용
const goodSearch = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("상품조회");
resolve();
}, 3000);
});
};
const cart = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("카트담기");
resolve();
}, 2000);
});
};
const account = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("결제하기");
resolve();
}, 2000);
});
};
const delivery = () => console.log("배송하기");
// Fetch형식으로 바꾸기
goodSearch()
.then(() => cart())
.then(() => account())
.then(() => delivery());
/*
상품조회
카트담기
결제하기
배송하기
*/
<Promise prototype 활용 4 - fetch형식으로 바꾸기 2>
// Promise prototype 활용
const goodSearch = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("상품조회");
resolve();
}, 3000);
});
};
const cart = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("카트담기");
resolve();
}, 2000);
});
};
const account = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("결제하기");
resolve();
}, 2000);
});
};
const delivery = () => console.log("배송하기");
// Fetch형식으로 바꾸기
goodSearch()
.then(cart) // 파라미터로 cart를 넘기면 resolve가 cart함수 전체를 받아서 처리해줌
.then(account) // account를 넘기면 resolve가 account함수 전체를 받아서 처리해줌
.then(delivery) // delivery를 넘기면 resolve가 delivery함수 전체를 받아서 처리해줌
.then(() => console.log("배송완료"));
/*
상품조회
카트담기
결제하기
배송하기
배송완료
*/
<기존의 authLogic>
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(); // 구글 github 지원 객체
}
// 로그인 함수
login(providerName) {
const authProvider = this.getProvider(providerName); // 구글인지 깃헙인지 문자열 정보 가져옴
return signInWithPopup(this.firebaseAuth, authProvider);
}
// 로그아웃 버튼이 눌리면 호출
// 굳이 export로 선언하는 이유
// -> 리액트에서는 한 페이지를 모듈화시켜서 재사용성을 높이는 방식이므로
// 어떤 컴포넌트에서든지 호출이 가능하도록 (함수를) 설계하는것이 좋다
logout() {
this.firebaseAuth.signOut();
}
// 호출되면 파라미터값에 따라서 변경사항이 있을때마다 자동 호출됨
onAuthChange(onUserChanged) {
// 구글에서 제공되는 함수 - onAuthStateChanged
this.firebaseAuth.onAuthStateChanged((user) => {
onUserChanged(user);
});
}
// 파라미터에 Google 혹은 Github(소문자로쓰면 값이달라 에러!)
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; // 이렇게해야 외부에서 사용가능함, 객체가 하나니까 default붙임
/*
package.json에는 의존관계 라이브러리 등록
개발자 의존 -D(실제 운영서버에는 미배포)
배포용
외부 스크립트 사용 방법
1. commonjs - 디폴트(생략되어있음 - package.json -> npm init -y해야 생성됨)
const http = requires('http')
2. module
import { ... } from './XXX.js'
리액트 수업 공통 사항
authLogic.js - 리액트 수업 활용
export - 여러개 가능 {}
export default - 하나만 가능
호이스팅 대상(가장 먼저 실행된다, 전역변수화된다)
1. var i
2. 함수 선언
3. import문
이걸 미루는 예약어 defer -> 다운로드가 끝나고, 브라우저(인터프리터)가 DOM Tree를 그린다 이때까지 기다릴것
-> DOM Tree가 완성되면 DOM API 사용가능 -> document.querySelector() document.querySelectorAll() => 반환타입 배열[]
-> 브라우저는 같은 이름이 두 개 이상이면 자동으로 배열 전환이 된다.
checkbox neme = hobby
배열 - 데이터셋과 직결 - json
const temp = JSON.stringify(response.json()) -> 객체를 문자열로 바꿔줌
const jsonDoc = JSON.parse(temp) -> 문자열을 배열로 바꿔줌
jsonDoc[].XXX
이런 json 누가 제공하나? -> 서버가 제공한다
유투브 API, OpenWeather, HackerNews 등등
내려받으려면 시간이 걸림 - 비동기처리 발생 - 지연발생
따로따로 처리하다가 먼저 처리가 되면 -> then(()=>{})
fetch("https://api.openweathermap.org/data/2.5/weather?appid=&q=seoul&units=metric", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
mime type
text/javascript -> import, require쓰면 error!
text/module -> import기억하기
text/common -> require기억하기
위의 것들은 서로 호환되지 않는다
*/
<Promise 활용한 authLogic>
import {
getAuth,
signInWithPopup,
GithubAuthProvider,
GoogleAuthProvider,
} from "https://www.gstatic.com/firebasejs/9.17.1/firebase-auth.js";
class AuthLogic {
constructor() {
this.auth = getAuth();
this.googleProvider = new GoogleAuthProvider();
}
getUserAuth = () => {
return this.auth;
};
getGoogleAuthProvider = () => {
return this.googleProvider;
};
} // end of AuthLogic
export default AuthLogic;
// 크롬에서 서비스 사용시 로그인 정보가 수정될 때 콜백되는 코드
// 상태가 바뀔때마다 자볻으로 호출됨
// 절대 개발자가 호출하는 함수가 아님
export const onAuthChange = (auth) => {
return new Promise((resolve) => {
auth.onAuthStateChanged((user) => {
resolve(user);
});
});
};
export const loginGoogle = (auth, googleProvider) => {
return new Promise((resolve, reject) => {
//result에는 구글 서버에서 전달해준 사용자 이름이 들어있음
signInWithPopup(auth.googleProvider)
.then((result) => {
const user = result.user;
console.log(user); // json형식
resolve(user);
})
.catch((e) => reject(e));
});
}; // end of loginGoogle
export const logout = (auth) => {
return new Promise((resolve, reject) => {
auth.signOut().catch((e) => reject(alert(e + ": 로그아웃 에러입니다")));
resolve();
});
};
<OpenWeatherAPI 1 - 날씨조회>
import { weatherKey } from "../../apiKEY.js";
const getWeather = (local, callback) => {
fetch(
`https://api.openweathermap.org/data/2.5/weather?appid=${weatherKey}&q=${local}&units=metric`
)
.then((response) => response.json())
.then((response) => {
console.log(response);
callback();
});
};
// 함수호출, 비동기(순서x)
getWeather("seoul", () => {
console.log("서울 날씨 가져오기");
});
getWeather("busan", () => {
console.log("부산 날씨 가져오기");
});
getWeather("incheon", () => {
console.log("인천 날씨 가져오기");
});
<OpenWeatherAPI 2 - callback활용>
import { weatherKey } from "../../apiKEY.js";
const getWeather = (local, callback) => {
fetch(
`https://api.openweathermap.org/data/2.5/weather?appid=${weatherKey}&q=${local}&units=metric`
)
.then((response) => response.json())
.then((response) => {
console.log(response);
callback();
});
};
// 함수호출, 비동기(순서x)
getWeather("seoul", () => {
console.log("서울 날씨 가져오기");
getWeather("busan", () => {
console.log("부산 날씨 가져오기");
getWeather("incheon", () => {
console.log("인천 날씨 가져오기");
});
});
});
<OpenWeatherAPI 3 - promise 활용>
import { weatherKey } from "../../apiKEY.js";
const getWeather = (local) => {
return new Promise((resolve, reject) => {
fetch(
`https://api.openweathermap.org/data/2.5/weather?appid=${weatherKey}&q=${local}&units=metric`
)
.then((response) => response.json())
.then((response) => {
console.log(response);
resolve();
});
});
};
getWeather("seoul")
.then(() => {
console.log("서울 날씨 가져오기");
})
.then(() => {
console.log("부산 날씨 가져오기");
return getWeather("busan");
})
.then(() => {
console.log("인천 날씨 가져오기");
return getWeather("incheon");
});
<jquery이용해 브라우저에 출력>
<!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>날씨조회</title>
</head>
<body>
<h3 id="cTime">현재시간→</h3>
<h3 id="cTemp">현재온도→</h3>
<h3 id="maxTemp">최고온도→</h3>
<h3 id="minTemp">최저온도→</h3>
<h2 class="icon"></h2>
<script
src="https://code.jquery.com/jquery-3.6.3.js"
integrity="sha256-nQLuAZGRRcILA+6dMBOvcRh5Pe310sBpanc6+QBmyVM="
crossorigin="anonymous"
></script>
<script>
$.getJSON(
`https://api.openweathermap.org/data/2.5/weather?appid=&q=seoul&units=metric`,
(result) => {
console.log(result);
console.log(result.dt);
console.log(result.main);
console.log(result.weather);
console.log(result.weather[0].icon);
// 현재 시간 출력하기
// 시간(밀리세크) 단위 변환
const timeFormat = (t) => {
const cdate = new Date(t * 1000);
const hour = cdate.getHours();
const min = cdate.getMinutes();
const sec = cdate.getSeconds();
return `${hour}:${min}:${sec}`;
};
const dt = result.dt; // 현재시간(밀리세크단위)
const test = timeFormat(dt);
$("#cTime").append(test);
// 현재 온도 출력하기
$("#cTemp").append(result.main.temp);
// 최고온도 출력하기
$("#maxTemp").append(result.main.temp_max);
// 최저온도 출력하기
$("#minTemp").append(result.main.temp_min);
// 날씨 아이콘 출력하기
const iconURL = `<img src="http://openweathermap.org/img/wn/${result.weather[0].icon}.png" alt="${result.weather[0].description}" />`;
$(".icon").html(iconURL);
}
);
</script>
</body>
</html>
<async와 await 1>
// async와 await
const goodSearch = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("상품조회");
resolve();
}, 2000);
});
};
const cart = () => console.log("카트담기");
// async와 await 사용
const runTest = async () => {
await goodSearch();
cart();
};
runTest();
/*
상품조회
카트담기
*/
<async와 await 2 - 날씨 가져오기>
import { weatherKey } from "../../apiKEY.js";
const getWeather = (local) => {
return new Promise((resolve, reject) => {
fetch(
`https://api.openweathermap.org/data/2.5/weather?appid=${weatherKey}&q=${local}&units=metric`
)
.then((response) => response.json())
.then((response) => {
console.log(response);
resolve();
});
});
};
// promise가 반환하는 함수에서만 await를 붙여야한다
// console.log에는 await를 붙이지 않는다
// async와 await는 함께 사용한다
const runTest = async () => {
await getWeather("seoul");
console.log("서울 날씨 가져오기");
await getWeather("busan");
console.log("부산 날씨 가져오기");
await getWeather("incheon");
console.log("인천 날씨 가져오기");
};
runTest();
/*
날씨를 제공하는 서버에 다녀오는(request와 response) 시간이 걸리므로
어느 지역이 먼저 처리될지 알 수 없다
실행할때마다 순서가 다를 수 있다
호출하는 순서가 처리 순서를 의미하지 않는다
만약 순서를 보장하고 싶다면?
콜백메소드 반복 작성
들여쓰기와 arrow function이 반복해서 나옴
이러면 depth가 깊어짐 -> 소스분석이 어렵다
자바스크립트는 기본적으로 순서대로 처리된다, 동기(서로 맞춘다) <=> 비동기(순서가 맞지 않는것)
*/
<동기 비동기코드 1>
const double = (x) => {
return x * 2;
};
// 6번 x가 확정되어야 9번 y가 실행될 수 있다(종속적) -> 동기코드(순차적 실행됨)
const x = double(100);
console.log("x: " + x); // x: 200
const y = x;
console.log("y: " + y); // y: 200
<동기 비동기코드 2>
const hap = (x, y) => {
setTimeout(() => {
return x + y;
}, 2000);
};
const x = hap(2, 3);
console.log("x: " + x); // x: undefined
const y = x;
console.log("y: " + y); // y: undefined
/*
2초 대기 후 리턴하기에 undefined, 2초 후에는 리턴 값을 받을 곳이 없음
*/
<동기 비동기코드 3>
const hap = (x, y, callback) => {
setTimeout(() => {
callback(x + y);
}, 2000);
};
const x = hap(2, 3, (result) => {
console.log("result: " + result);
});
const y = x;
console.log("y: " + y);
/*
y는 undefined이지만, x는 콜백을 썼기에 5
y: undefined
result: 5
*/
'국비학원 > 수업기록' 카테고리의 다른 글
국비 지원 개발자 과정_Day55 (1) | 2023.02.15 |
---|---|
국비 지원 개발자 과정_Day54 (1) | 2023.02.14 |
국비 지원 개발자 과정_Day52 (1) | 2023.02.10 |
국비 지원 개발자 과정_Day51 (0) | 2023.02.09 |
국비 지원 개발자 과정_Day50 (0) | 2023.02.08 |
댓글