코드스쿼드 코코아과정 3주차 TIL - Part1
<link>
태그의 rel
속성은 현재 문서와 외부 리소스 사이의 연관 관계를 나타내는 필수 속성이다.
css파일과 html을 연결해줄 때도 아래와 같이 사용된다.
html 요소에 내장된 고유 CSS스타일 속성을 초기화 시켜서 크로스브라우징(=어떤 브라우저에서도 동일한 모양을 가짐)을 구현할 수 있게 한다.
각 브라우저에 기본적으로 설정되어있는 스타일을 해제 해주는 CSS 툴은 여러가지가 있는데, 대표적으로 <Eric Meyer's Reset CSS 2.0> 가 있다.
이런 툴을 꼭 사용하지 않더라도 Asterisk (*
; wildcard)로 모든 요소를 선택해 default 속성을 해제해줄 수 있다.
* {
margin: 0;
padding: 0;
}
em과 rem 단위를 사용하면 px보다 비율조절이 쉬워진다.
em 과 rem은 모두 길이가 유연한 가변 단위로, 디자인에 설정된 폰트 크기에 따라 브라우저에 의해 픽셀값으로 변환된다.
각 단위의 차이점은 이것을 브라우저가 px 값으로 변환할 때 고려하는 결정 요인에 있다.
em : 변환되는 픽셀값은 스타일을 지정한 요소의 폰트 크기를 곱한 값이 된다. 실제 사용된 요소의 폰트 크기가 기준이 된다.
ex. div의 폰트 크기가 18px이라면, 10em은 10 x 18 = 180 이므로 180px이 된다.
em 단위를 쓰는 주된 목적은 디자인 요소가 지닌 특별한 상황에 따라 그곳에 어울리는 변동성이 요구될 때 사용하면 좋다.
최상위 요소 말고 기타 다른 특정 요소의 font-size를 기준으로 그 크기가 바뀌어야 하는 곳에 사용. 어느 한 요소의 크기를 정할 때 해당 요소가 기본 폰트 크기로 지정되어 있지 않을 때.
rem : 변환된 픽셀 크기는 페이지 최상위(root) 요소, html 요소의 폰트 크기가 기준이 된다. 이 최상위 요소의 폰트 크기에다 rem 단위로 지정한 숫자를 곱한 값이 바로 마지막 변환된 값.
ex. 최상위 요소의 폰트 크기가 16px이면, 10rem은 10 x 16 = 160 으로 160px이 된다.
rem 단위를 사용하는 주된 목적은 사용자가 브라우저의 기본 폰트 크기를 어떤 값으로 설정했든 간에, 이에 따른 가변 텍스트 크기에 맞춰서 사이트 레이아웃이 적절히 조정될 수 있도록 하려는 것. rem 단위를 쓰면, 사용자가 폰트 크기를 늘리더라도, 레이아웃은 그대로 온전하게 보전할 수 있다.
웬만하면 폰트 크기는 rem를 사용할 것.
textContent : textContent의 값은 식별자 노드의 내부 콘텐츠를 text/plain 으로 파싱(Parsing)한 결과로 다른 프로퍼티들에 비해 파싱이 빠르다.
innerHTML : innerHTML 프로퍼티의 값은 text/html으로 파싱한 결과로 상대적으로 파싱이 느린편이다. 또한, XSS(Cross-Site Scripting) 공격에 취약해 다른 공격 루트들은 방어하지 못한다. 그래서 프로젝트가 보안 점검을 거치게 되는 프로젝트인 경우, innerHTML을 사용하면 코드가 거부 될 가능성이 높다.
성능과 보안 측면을 고려할 때, 가능한 textContent 보다는 innerHTML을 사용하는 것을 권한다.
var aValue = storage.getItem(keyName);
-MDN
괄호 안에 key이름을 넣어 실행하면 storage 객체에서 해당 key를 key로 가지고 있는 value를 리턴해준다.
//이런 식으로 쓸 수 있음. 로컬 스토리지에서 'toDos'를 key로 갖는 value 불러오기
const TODOS_LOCALSTORAGE = 'toDos';
const toDos = localStorage.getItem(TODOS_LOCALSTORAGE);
storage.setItem(keyName, keyValue);
-MDN
key 이름과 value를 전달하면 해당 key를 지정된 storage 객체에 추가하거나 이미 존재하는 경우 해당 key의 값을 업데이트한다.
const toDos = [];
function saveToDos() {
localStorage.setItem(TODOS_LOCALSTORAGE, toDos);
}
❗️❗️❗️주의❗️❗️❗️
➡️ local storage는 내부에 있는 값을 모두 "string"으로 저장하기 때문에 객체는 위 화면처럼 [object Object]
로 나온다.
객체를 저장하길 원한다면 JSON.stringify()
로 문자열화 시킨 후에 저장할 것!
JSON.stringify()
로 문자열화 시킨 후 정상적으로 출력된 모습 ⬆️
!
+ tab
으로 기본 html 틀을 자동완성할 수 있다.
Emmet은 보다 간편하게 html을 작성할 수 있게 해준다.
ex. ul>li*10
(=<ul>
태그 하위에 <li>
태그 10개 추가)을 입력하게 되면 아래와 같이 해당 태그들이 자동완성 된다.
클로징 태그 없이 혼자서 별도의 의미를 가진 태그들(<br>
, <input>
등등)은 /
를 넣어서 꼭 닫아주는 것이 좋다.
event.preventDefault();
는 브라우저가 가진 기본 이벤트를 막는다. 예를 들어 스크롤을 내리면 화면이 밑으로 생기는 걸 막을 수 있음.
MDN에서 더 알아보기
오픈 소스를 활용하는 방법:
다른 사람들이 만든 코드를 많이 보고 힌트를 얻어서 직접 짜보는 것도 좋은 방법이다!
개발환경을 세팅할 때 '절대경로'를 기준으로 소스코드를 빨리 찾게 해주는 라이브러리의 대표적인 예는 @jquery.js이다.
require
안에 ./
를 적어주지 않으면 Node.JS 자체 라이브러리에서 모듈을 찾게 된다.
만약 제이쿼리를 쓰겠다고 하면,
const query. = require(“./node_modules/dist/jquery.js”)
이렇게 적는 대신 const query. = require(“jquery.js”);
이렇게만 기재해도 노드가 경로를 알아서 찾아준다. node_module
의 경로를 알아서 찾아주는 것이다.
(나중에 더 상세히 알아볼 것)
DOM은 HTML구조. HTML구조는 동적으로 바꿀 수 있는데, 그러기 위해서는 화면에 접근을 가능하게 하는 DOM API가 필요하다. DOM API란 DOM에 쉽게 접근하게 해주는 querySelector
, querySelectorAll
, getElementById
등을 의미한다.
HTML에서 document란 최상위 객체이다. document는 DOM트리에서 루트를 찾아준다.
document는 객체인데 이것으로 노드를 찾았다면 그 노드 또한 객체이다.
CSS 클래스도 넣고 빼는 것을 동적으로 할 수 있다. 기본적으로 DOM트리에 있는 모든 것을 다~~ 바꿀 수 있다. 이런 작업들을 할 수 있도록 제공되는 함수 묶음이 DOM API인 것.
DOM조작은 기본 중의 기본이지만, 노드를 변경하고 추가하는 작업이 워낙 번거롭다보니 React, Vue.js, Angular와 같은 프레임워크들이 그 작업을 대신해주어서 렌더링을 보다 쉽게 할 수 있도록 한다.
<Event 객체>
Document.addEventListener(“click”, () => {}
브라우저는 이벤트를 모니터링하다가(지켜보다가) click이벤가 일어나면 그 때 eventHandler를 실행한다.
이 때 Target은 이벤트가 발생한 정보에 마지막 node의 정보를 반환해줌.
이벤트 정보에 많은 것들이 있으니 탐색을 해볼 것.
<Class를 만들 때 고려할 점>
I. 개발을 할 때는 역할을 정하는 것이 중요!
프론트엔드는 결국 UI(눈)를 만드는 것.
“동적인 기능”이 있는 것들은 “클래스”로 만들면 된다.
예를 들면,
1) inputView.js (입력에 관한 것들. 입력값을 받아서 전달하는 것)
2) listView.js (UI 리스트에 관한 것들)
이런식으로 두 개의 모듈로 나누어 볼 수 있다.
II. 클래스 간의 의존성을 낮추는 것이 중요!!
함수 밖에서 인자로 넣어주는 것도 방법.
함수 내부에서 짜지 말고 파라미터로 넣어주기!
DOM이나 다른 클래스에 의존하고 있다면 좋지 않음.
클래스를 어떻게 나눌까, 의존성을 어떻게 낮출까를 고민하면서 디자인 패턴을 구축해야한다.
자바스크립트는 ‘일급객체’이기 떄문에 함수를 반환값으로 쓰거나 인자로 넘겨줄 수 있는 점을 활용하기!
의존관계를 낮추는 방법 중 또 하나는 제 3의 어떤 것을 기준으로 주거니 받거니 할 수도 있다.
중간에서 전달해주는 제 3자를 만드는 것.
Procedure:
인풋이 바뀌면 모델에 알려준다.
➡️ 모델은 데이터를 추가/삭제/변경(데이터 관련 책임을 짐)
➡️ 바뀐 정보를 V에 알려줌
➡️ V는 바뀐 정보를 적용해서 렌더링 함.
MVC, MVP, MVVM 등등 다양한 디자인 형태를 만드는 패턴이 있다.
일단 모델을 나누는 것부터 해보고, 그게 어렵다면 v1, v2만 만들어서 서로 호출을 하게끔 할 수도 있다.
현대의 프레임워크는 더 많은 뷰를 나눈다. (브랜치 모양)
1. 시나리오 정의하기 (목표정하기)
- 입력창에 값을 입력하면 그 결과가 바로 화면에 노출된다.
- todo를 입력한 후, 확인버튼을 누르면 입력된 todo값이 화면에 추가된다.
- html 화면 구조(뼈대코드; skeleton) 만들기 -> css 일부분 작업 -> 동적인 기능 구현
//skeleton 코드 예시 Class Todo { constructor () { } onEvent() { document.querySelector(“button”).addEventListener(“click”, (e) => { }); } validateInputValue(inputValue) { let result = false; } renderNewTodo(newTodo) { } }
2. 동적인 기능 구현 (feature / task) -> 피처를 잘게 나누기. 이 부분이 중요!!! 여기서 공을 들여야 한다.
- 확인버튼 이벤트 핸들러 만들기
- 이벤트 핸들러 안에서 입력값을 가져와서 유효성검증
- todo값을 리스트영역에 노출
*이런 task들을 소스 코드의 상단에 주석으로 두고 해도 됨.
- 코드 스타일 관련 tip:
<template>
태그는 브라우저에 렌더링이 안됨. 숨기는 기능. <template>
& template literal & innerHTML
사용해서 HTML에 요소 추가해보기 http://tcpschool.com/html-tag-attrs/link-rel
https://homzzang.com/b/css-257
https://webdesign.tutsplus.com/ko/tutorials/comprehensive-guide-when-to-use-em-vs-rem--cms-23984
https://velog.io/@raram2/%EB%8B%B9%EC%8B%A0%EC%9D%B4-innerHTML%EC%9D%84-%EC%93%B0%EB%A9%B4-%EC%95%88%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0
https://developer.mozilla.org/en-US/docs/Web/API/Storage/getItem
https://developer.mozilla.org/en-US/docs/Web/API/Storage/setItem