Fix. babel-eslint package.json에 추가 후 install
text-overflow 의 조건
text-overflow 속성을 사용하려면 몇 가지 조건이 만족되어야 동작한다. 그렇지 않으면 생략 기호로 나타나지 읺을 수 있다.
i. width 또는 height가 고정적일 것
+ 추가) 부모 요소의 display 속성이 block이여야 한다. 왜냐하면 text-overflow 속성은 블럭형태인 경우에만 적용되기 때문이다.
SPA 라우팅
index.html에는 라우팅 변경을 할 수 있는 link
라우팅에 따라서 템플릿이 삽입된 history-app과 hash-app이 있다.
라우팅 변경에 따라 해당 Content영역에 템플릿이 삽입될 것이다.
이제 각 라우팅을 위한 about과 home 페이지를 만들자.
파일들은 html이 아닌 Handlebars로 생성할 것이기 때문에 확장자는 .hbs 또는 .handlebars로 생성해야 한다.
.handlebars 확장자로 생성 시 webpack.config.js에서 handlebars-loader 영역의 정규식을 /\.handlebars$/로 수정해야 한다.
라우팅 생성 router.js
핵심 부분만 보자.
history 일 경우엔 historyRouterPush를 통해서 history PushState API를 사용하고 template를 렌더링
onpopstate를 통하여 브라우저 뒤로 가기 또는 앞으로 가기에 따라 히스토리를 관리할 수 있다.
hash인 경우 hashchange 이벤트를 통하여 hash가 변경되는 것을 감지하고 hash에 따라 페이지를 렌더링하고 있다.
index.js(app.js)
각 html 태그에 이벤트를 생성하고 이벤트에 따라 라우팅을 변경하는 코드가 존재한다. 또한, 최초에 initialRoutes를 통해 기본 페이지를 렌더링
// template
const homeTemplate = require("./pages/home.hbs");
const aboutTemplate = require("./pages/about.hbs");
const Home = homeTemplate();
const About = aboutTemplate();
const routes = {
"/": Home,
"/home": Home,
"/about": About,
};
// render
function renderHTML(el, route) {
el.innerHTML = route;
}
// & : get hash history route
function getHashRoute() {
let route = "/";
Object.keys(routes).forEach(hashRoute => {
if (window.location.hash.replace("#", "") === hashRoute.replace("/", "")) {
route = routes[hashRoute];
}
});
return route;
}
// & : entry point - mode에 따른 동작
function initialRoutes(mode, el) {
renderHTML(el, routes["/"]);
if (mode === "history") {
window.onpopstate = () => renderHTML(el, routes[window.location.pathname]);
} else {
window.addEventListener("hashchange", () => renderHTML(el, getHashRoute()));
}
}
// set browser history
function historyRouterPush(pathName, el) {
window.history.pushState({}, pathName, window.location.origin + pathName);
renderHTML(el, routes[pathName]);
}
// set hash history
function hashRouterPush(pathName, el) {
renderHTML(el, getHashRoute());
}
module.exports = {
initialRoutes,
historyRouterPush,
hashRouterPush,
};
JavaScript
복사
json()
에서 .then()을 활용했다. fetch()를 이용해 URL에서 데이터를 가져오게 되면 promise를 건네 받는다. 데이터를 fetching하는 데에는 시간이 소요되고, 따라서 이를 비동기적으로 우선 promise를 건넨 후 fetching이 완료된 후 데이터를 사용하는 것이다.
여기서 주의할 점은 fetch의 결과로 가져온 res는 JSON이 아니라는 것이다. 여기서 JSON을 읽어오려면 .json()으로 가져와야 한다. 그리고 .json()은 또 다른 promise를 던져준다. 다시 한번 .then()을 사용해야 하는 이유다.
console?
쿠키는 기본적으로 만료일(expiration day)을 함께 설정합니다. 만료일은 사용자가 삭제하지 않아도 일정 시간이 지나면 저장된 데이터를 사용할 수 없게 되는 것으로 특히 보안이나 내부 데이터 관련된 내용들이 쿠키사용에 더 적합할 수 있을 것입니다. 이에 반하여, 로컬저장소는 사용자가 임의로 삭제하지 않는 경우 삭제되지 않기 때문에 중요한 성격의 자료보다 단순한 보관 용도의 데이터 타입이 더 적합하게 사용할 수 있습니다.
대부분의 브라우저에서 현재 localStorage와 같은 HTML5 API를 지원하고 있으나 아직 100% 완벽하지는 않으므로 호환성을 고려한다면 쿠키(cookie)의 사용이 더 나은 방법
쿠키에는 단점도 존재한다. 장기간 유지되고 브라우저 종료 후에도 유지되는 Persistent Cookie의 경우 사용자의 하드디스크에 저장된다. 그렇기 때문에 공공 PC의 경우는 쿠키를 탈취하여 개인정보를 빼돌릴 수도 있다. 이러한 보안상 취약점이 있고, 네트워크를 통해 암호화되지 않는 쿠키를 전송할 때 쿠키 정보를 탈취하는 스니핑(Sniffing) 공격에 당할 수도 있다.
user라는 데이터는 로그아웃하면 지워주는데 안하면 남아있음. 쿠키는 로그아웃하면 지워주고 안하면 만료일에 따라 지워짐.>>로그인유지하려면 만료일 무한 >> 단점?
세션 쿠키(Session Cookie)는
임시 쿠키 파일로 브라우저를 닫을 때 지워지는 쿠키이다 / 장바구니
영구 쿠키(Persistent Cookie)는
브라우저를 닫아도 지워지지 않는 쿠키
/ 로긴유지, 언어 선택, 책갈피 또는 즐겨 찾기
세션의 경우 메모리에 저장하기 때문에 브라우저가 종료되면 사라진다. 쿠키의 트래픽 문제와 보안상 취약점을 해결하기 위해 사용되었다
세션은 서버의 리소스를 사용하기 때문에 세션을 많이 쓸 경우 서버에 부하가 생기게 될 수 있다. 특별히 세션은 사용자 인증, 로그인에 많이 쓰시는데 서비스가 확장되어 유저의 수가 너무 늘어날 경우에는 서버 램이나 DB 성능에 무리를 줄 수 있기에 유의