Fact
- 오늘은 학습 정리를 했다.
Feelings
- 고오오오옹부 빨리하자
Findings
- 빌드 하는 이유
- transpiling 표준 되어 있지 않은 기능들을 현제 설정 사항에 맞게 알아 들을 수 있게 변환 작업
- 오류점검
- 성능
- 테스팅
js 최적화 (min & uglify)
js 코드 품질 검증 (js lint, flow)
js 테스트 수행
css 최적화(min)
css image sprite 자동화 (이미지 하나로 만들어서 좌표값으로 불러오기)
frontend
frontend에서 브라우저 하위 호환성을 보장하는게 힘들다.
js에서 최신 기능을 사용하고 싶지만 브라우저가 호환을 안하면 못쓴다.
https://caniuse.com/?search=array
https://kangax.github.io/compat-table/es6/
transpiler
transpiling 을 통해서
-
하위브라우저에서도 동작하게 문법을 바꾼다.
- 최신기능의 문법도 사용가능하다.
- 제안된 기능(언어에 표준 기능? 으로 등록 되어 있지 않은것들) TC39 Process(https://tc39.es/process-document/) 에 들어가면 1~3단계가 제안된 기능이라고 보면 된다. 이러한 기능들을 쓰다가 그 기능들이 없어질 수도 있다.
polyfill을 통해서 지원하지 않는 native API를 다른 코드로 동작하게 한다.
- feature detection를 기반으로 동작
- 걷어내기 쉽다. (브라우저 100% 달성 했을시에 빼고 싶을때 그냥 지우면 코드에 영향 없이 바로 지울 수 있다.)
webpack
-
bundler 이라고 생각하면 편하다.
- js, css, html 등 종류별 다수 파일들을 종류별 하나의 파일로 묶어 준다.
- 묶어주는 행동을 bundling이라고 한다. bundling을 할때 babel로 transpiling 과정을 거칠 수 있고 또한 polyfill을 쓴다 하면 설정 되로 지원하지 않는 native API를 지원 할 수 있게 된다.
- 웹팩 설정에서 Tree Shaking 이라는 옵션을 줄 수 있다.
-
이것은 안쓰는 모듈들을 지운다.(build 에서 제외)
- import export로 통해서 감지
- webpack 4 부턴 compiler 한태 package.json속성을 통하여 파일들이 “pure” 한것들을 전달해서 안전하게 제거가 가능한지 알려준다.
- 웹팩 설정에서 sourcemap 이라는 옵션을 줄 수 있다
- 소스맵은 generated/transpiled/minified JavaScript 파일과 하나 이상의 원본 파일 간의 매핑이다. 소스맵의 주요 목적은 디버깅을 지원하는 것이다. 기본적으로 생성된 코드 파일에 오류가 있을 경우 맵에서 원본 파일 위치를 알려줄 수 있다.
-
사용방법
-
devtool: "source-map"
webpackconfig에 이것만 넣어 주면 된다. https://trackjs.com/blog/debugging-with-sourcemaps/
-
- 웹팩 설정에서 SplitChunksPlugin 을 줄 수 있다.
-
이것은 보통 코드 스플리팅 을 해야 할때 쓰는 것이다.
- 코드 스플리팅은 간단하게 말해서 많은 코드들을 분리 하는것이다. 예를들어서 한 페이지에 수많은 코드가 있어서 로딩 속도가 느려지면 그때 그때 필요한것을 로딩 할 수 있게 끔 나눠서(빨리 렌더링 될수 있게끔) 만드는게 코드 스플리팅이다.
- https://www.zerocho.com/category/Webpack/post/58ad4c9d1136440018ba44e7
ES Module
- 모듈라 프로그래밍은 복잡한 애플리케이션을 모듈단위로 만들어 관계를 짓는 (의존성을 관리하는) 프로그래밍 방법이며,
웹프론트엔드에서도 SPA(single page application)의 등장으로 더욱 필요성이 커졌다.
</div>
<script type="text/javascript" src="//c.011st.com/js/lib/handlebars/handlebars-v4.0.5.min.js"></script>
<script type="text/javascript" src="//c.011st.com/html/inc_header_data.js"></script>
<script type="text/javascript" src="//c.011st.com/js/common/headerCommonJs.js"></script>
<script type="text/javascript" src="//c.011st.com/html/browsing/main/mainAdDsData.js"> </script>
...
이러한 파일들을
</div>
<script type="module" src="./app.js"></script>
...
//handlebars-v4.0.5.min.js
const handlebars = {
code ...
}
export default handlebars
//inc_header_data.js
const incHeaderData = {
code ...
}
export default incHeaderData
//app.js
import incHeaderData from '..../inc_header_data.js'
import handlebars from '..../handlebars-v4.0.5.min.js'
code ...
하나의 루트 파일에서 export import를 하면서 tree 구조로 관리를 할 수 있게 된다.
중요 한 점은
<script type="module" src="./app.js"></script>
에서 type=“module” 로 해줘야한다. 그리고 이 app.js 가 entry point 이다.
이벤트 위임
이벤트 효율적으로 등록 하여 브라우저가 너무 많은 이벤트핸들러를 기억하지 않게 하고, 또한 DOM이 추가/삭제 될때 Event등록을 매번 해줘야 하는 수고를 없앨 수 있다.
예제
<ul>
<li>
<img src="https://images-na.,,,,,/513hgbYgL._AC_SY400_.jpg" class="product-image" > </li>
<li>
<img src="https://images-n,,,,,/41HoczB2L._AC_SY400_.jpg" class="product-image" > </li>
<li>
<img src="https://images-na.,,,,51AEisFiL._AC_SY400_.jpg" class="product-image" > </li>
<li>
<img src="https://images-na,,,,/51JVpV3ZL._AC_SY400_.jpg" class="product-image" >
</li>
</ul>
사진이 있다고 치자. 각 사진에 이벤트를 달기 위해서 보통
const logNode = document.querySelector(".log");
const lists = document.querySelectorAll("ul > li");
for(let i=0,len=lists.length; i < len; i++) {
lists[i].addEventListener("click", function(evt) {
logNode.innerHTML = "clicked" + evt.currentTarget.firstElementChild.src;
});
}
로 4개의 이벤트를 달 수 있다.
그러나 4개 단다는게 너무 비효율 적이다. 그래서 하는게 event bubbling이다.
const ul = document.querySelector("ul");
ul.addEventListener("click",function(evt) {
if(evt.target.tagName === "IMG") {
log.innerHTML = "clicked" + evt.target.src;
} else if (evt.target.tagName === "LI") {
log.innerHTML = "clicked" + evt.target.firstElementChild.src;
}
});
target = 현제 누르는것
currentTarget = 이벤트단 최상단 element
이벤트 버블링이란 중첩된 노드에서 아래에 걸 클릭 할때 그것을 감싸고 있는 엘레먼트 중 이벤트 가 등록되어 있다면 실행 시켜주는 과정이다
event delegation 이벤트 위임 => img tag의 이벤트를 위쪽 ul인 부모에게 위임한다 해서 나온 말이다.
불가피 하게 다수 이벤트를 등록 해야 하지만 부모의 이벤트를 실행 시키지 않고 싶다면 stopPropagation을 쓰면 된다.
<div>
<p> hello
<span>
hi
</span>
</p>
</div>
document.querySelector("div").click(function(){
alert("The div element was clicked.");
});
document.querySelector("span").click(function(event){
event.stopPropagation();
alert("The span element was clicked.");
});
document.querySelector("p").click(function(){
alert("The p element was clicked.");
});
hello를 누르면 alert 가 두번 나온다. 처음 “The p element was clicked.” 와 그다음 “The div element was clicked.” 이 나온다.
hi 를 누르게 되면 stopPropagation을 event bubbling을 방지하게 됨으로써 “The span element was clicked.” 만 출력이 된다.
FE-Promise패턴과 fetch API활용
예전엔 page.html을 요청만 가능했었는데, 비동기적으로 데이터를 받아 올 수 있게 됨으로써 json형태의 데이터를 받아올 수 있게 되었다. spa에선 이러한 형식이 중요하다.
데이터통신을 위해서는 XML이나 JSON같은 포맷을 통해서 클라이언트와 서버가 맞춰야 한다.
XML보단 JSON을 표준처럼 쓴다. 클라이언트에서 데이터를 보낼때나 받을때 모두 JSON형태를 사용할 수 있다. https://json.org/example.html
fetch api
비동기 데이터 통신은 XMLHTTPRequest 객체를 사용했다. 그러나 이러한 통신을 사용할때 코드가 길어지면 형태가 콜백헬처럼 된다. 이 이유 뿐만은 아니지만 전체적으로 조금 더 원활하게 사용하기 위해서 나온게 fetchAPI이다.
xhr 코드
let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://domain/service');
// request state change event
xhr.onreadystatechange = function() {
// request completed?
if (xhr.readyState !== 4) return;
if (xhr.status === 200) {
// request successful - show response
console.log(xhr.responseText);
}
else {
// request error
console.log('HTTP error', xhr.status, xhr.statusText);
}
};
// start request
xhr.send();
fetchapi 코드
fetch(
'http://domain/service',
{ method: 'GET' }
)
.then( response => response.json() )
.then( json => console.log(json) )
.catch( error => console.error('error:', error) );
promise 패턴
비동기처리를 동기적인것처럼 보여주는 패턴이다.
콜백함수(비동기 수행이 끝난 다음에 실행되는)을 비동기 로직에서 분리 되었다. 콜백함수는 then 의 인자로 등록되었다.
let myFirstPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Success!");
}, 1000);
});
myFirstPromise.then((successMessage) => {
console.log("Yay! " + successMessage);
});
실행순서 promsie 실행 -> then 실행(콜백함수 promise에 등록) -> 비동기완료시 resolve메서드실행 -> 콜백함수 실행
특징
- Promise는 비동기로직에서 콜백함수를 분리 할수 있다.
- thenable syntax 코드 구조를 사용하여 synchronous한것 처럼 보이는 코드를 만들 수 있다.
- then메서드에 의해 실행되는 콜백함수는 resolve 혹은 reject메서드가 실행된 후에 실행 된다.
- 위의 기능들로 가독성이 높아진다
활용 방법
-
병렬 처리
-
const promise1 = Promise.resolve(3); const promise2 = 42; const promise3 = new Promise((resolve, reject) => { setTimeout( () => resolve("foo"), 1000); }); Promise.all([promise1, promise2, promise3]).then(function(values) { console.log(values); });
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
-
fetchAPI promise all 예제
function getDatas() { const todos = fetch('https://jsonplaceholder.typicode.com/todos') .then(response => response.json()); const comments = fetch('https://jsonplaceholder.typicode.com/comments') .then(response => response.json()); Promise.all([todos, comments]) .then( values => { const [todoList, commentList] = values; fn(todoList, commentList); }) }
-
Future Action
- 막 하는것 보다 효율적인것을 생각하면서 하자 뭐든.