: html 태그들을 훨씬 유연하게 디자인할 수 있게 해주는 css property이다. 참고로, flexbox이전에 float라는 속성이 있었다. float는 아래처럼 사용하는데 태그들이 이름그대로 어느방향으로 흘러갈지 지정할 수 있다.
.box {
float:left
}
: important 👉 inline 👉 id 👉 class 👉 html selector. 순으로 css 스타일이 정해진다. 단! inline, important는 쓰지 않도록한다! 디버깅, 유지보수가 매우 힘들어진다.
그리고 우선순위가 같은 것이 동시에 적용이 된다면 나중에 쓰여진 css가 적용된다.
<div class="product featured"> ... </div>
.product {
background-color: grey;
}
.featured {
background-color: green;
}
이땐 featured가 적용됨
css 애니메이션: js 쓰레드가 아닌 컴포지터 쓰레드를 이용하기 떄문에 stack에 작업이 쌓여 성능이 저하되는 것을 막을 수 있다. css자체가 선언형이라 직관적 표현이 가능
js 애니메이션: stop, pause, reverse같은 animation api를 이용하여 더 정교하게 애니메이션을 구현할 수 있다. 그러나 계속해서 요소의 위치를 재계산 하므로 reflow(layout)가 일어나 성능이 저하될 수 있다.
: 모든 html element는 일종의 box이다. box는 content + padding + border + margin으로 이루어져 있다. 이러한 구성요소로 box가 만들어지는 것을 box model이라고 한다.
이때 아래와 같이 width를 설정한다고 하자.
div {
width: 320px;
padding: 10px;
border: 5px solid gray;
margin: 0;
}
그럼 box의 width이 320px이 될까? 아니다. content가 320px이 된다. 그럼 box의 진짜 넓이는? 320 + (10 X 2(좌,우)) + (5 X 2) + (0) = 350px
이렇게 된다.
그럼 box 넓이를 지정할때 이런것을 일일이 계산해야한다. 그래서 box-sizing: border-box;
를 모든 element에 지정해주는 것이다.
border-box는 width안에 padding, border가 포함되도록 하는 value이다.
defer : dom이 다 rendering되고나서 execute된다. broswer가 이 스크립트를 만나면 background에서 다운로드된다. 만약 defer script가 여러개면 동시에 loading한다(성능을위해서) 그러나 어느 한쪽이 다 다운로드 되지 않으면 실행되지 않는다.
async : defer처럼 dom 랜더링을 막지 않는다. defer와 다른점은 async script는 다른 script, 심지어 DOM도 기다리지 않는다. 그리고 다른 script, 그리고 DOM도 async script를 기다리지 않는다. 완전히 독립적이다. background에서 다운로드되고 다 다운되면 바로 실행된다.
summary: defer는 dom에 의존하는 script일때 또는 order가 중요한 script일때 쓴다. async는 dom과 다른 script에 의존하지 않을때 쓴다. 즉, 라이브러리 같은경우 보통 async를 쓰고 비즈니스 로직은 defer를 쓴다.
음... 이런거였군.. 흥미롭다😮
: element의 특정 상태를 나타내고 싶을때 사용하는 클래스이다. 아래와 같은 class가 존재
a:link {
color: red;
}
/* visited link */
a:visited {
color: green;
}
/* mouse over link */
a:hover {
color: hotpink;
}
/* selected link */
a:active {
color: blue;
}
참고로 hover은 link,visted 뒤에 와야하며, active는 hover뒤에 와야 스타일이 적용된다.
: 위와 아래의 margin이 겹치면 더 큰 margin으로 겹치는 margin의 크기가 정해진다. 단, 좌,우의 margin이 겹칠때는 병합이 일어나지 않는다.
: 결론부터 말하면 reflow 또는 repaint를 막기 위함이다.
예를 들어 아래와 같이 css를 정의한다고 하자
<html>
<head>
</head>
<body>
<script src="script.js" type="text/javascript"></script>
<div class="blue yellow big bold">
Hello, world!
</div>
<style type="text/css">
.foo { color: red; }
</style>
<link rel="stylesheet" type="text/css" href="styles/all_styles.css">
</body>
</html>
그럼 hello world가 나타난후에 style이 적용되면서 hello world가 다시 paint되어 나타날것이다.
그럼 아래와 같이 head로 옮겨주자
<html>
<head>
<style type="text/css">
.foo { color: red; }
</style>
<link rel="stylesheet" type="text/css" href="styles/all_styles.css">
</head>
<body>
<script src="script.js" type="text/javascript"></script>
<div class="blue yellow big bold">
Hello, world!
</div>
</body>
</html>
깜빡임이 없어진다. 그러나 보여지는 결과물은 같을것이다.
또한 네트워크 다운로드에 걸리는 시간까지 줄어든다.
출처
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
</form>
이렇게 되어있으면 p태그를 눌렀을때 p에 할당된 이벤트 뿐만아니라 그 위 조사에 할당된 이벤트까지 모두 차례로 실행이 되는 것을 의미한다.
더불어, 이때 event.target 과 this는 다르게 나타난다. 만약 아래와 같이 이벤트가 설정되어있다고 보자.
<form onclick="alert('form')">FORM
<div>DIV
<p>P</p>
</div>
</form>
이때 event.target은 클릭된 요소이고 this(=event.currentTarget)는 이벤트가 할당된 요소이다.
: 변수에 접근할 수 있는 범위를 뜻하며, 지역 스코프와 전역 스코프로 크게 나뉜다.
: 외부변수를 기억하고 이 외부변수에 접근할 수 있는 함수를 뜻한다. 아래와 같은 함수가 있다고 하자.
A closure is the combination of a function
bundled together (enclosed) with references to its surrounding state (the lexical environment).
function makeCounter() {
let count = 0
return function innerCounter() {
return count++
}
}
let counter = makeCount()
이때 innerCounter의 [[environment]]
라고 불리는 숨김 프로퍼티 안에는 외부 렉시컬 환경의 내용을 기억하고 있다 innerCounter의.[[environment]] = { ... count:0 }
이런식으로말이다. 그리고 [[environment]]
는 함수 생성 이후에 한 번 만들어지며 이후에 변하지 않는다.
그럼 counter가 실행될때 내부 렉시컬 환경에 count가 없으므로 외부 렉시컬 환경을 참조한다. 그럼 count가 있다!! 그래서 count를 업데이트 한다.
이렇게 counter를 사용하고 난 다음에 필요없으면 counter함수가 도달가능하지 못한 상태로 만들어줌으로써 가비지 컬렉터가 메모리에서 counter를 제거 시키도록 해야한다.
counter = null
JavaScript engine is single threaded so the language itself is synchronous and hence blocking in nature.
It means any task will run completely before another can run.
However, a feature called “event loop” is provided by the environment where javascript is running which provides capability for asynchronous execution providing non-blocking functionality. Environment here refers to Web browsers , NodeJS etc.
Event Loops are not a part of JavaScript language specifications but is an add on feature that is provided by the implementing environment just like DOM API in browser or any other web API
원래는 동기적언어로 blocking한 성격을 가지고 있지만 JS가 실행되는 환경안에서 event loop이라는 broswer api가 제공되므로 비동기적(non-blocking)인 프로그래밍이 가능.
: 특정 애니메이션을 반복하여 화면에 나타날때 사용되는 winodw api이다. 만약 JS로 애니메이션을 구현한다고 하면 콜스택이 꽉차서 maximum stack over flow 에러가 나타날 수 있다. 또한 js에서 화면을 다시 그리면 reflow, replaint가 다시 일어나 화면이 끊길 수 있다.
requestAnimationFrame는 js call stack에 쌓이지 않고 백그라운드에서 동작하며 1초에 60번 동작을 제한으로 한다.
: 함수가 쓰여진 환경을 뜻한다.
변수와 함수의 이름이 어떤 변수와 함수를 의미하는지에 대한 기록이 담겨있는 곳.그리고 이 변수와 함수가 어떤 실제 힙과 스택에 저장된 객체와 원시타입 데이터의 주소르 가리키는지에 대한 정보가 담겨있는 곳.
즉, 어디서 호출을 하든 그 환경은 변하지 않는다. references
to its surrounding state. 때에 따라서 그 outer environment를 참조 할 수 있다. 그리고 이 모든 record는 [[environment]]
라는 내부 property에 저장되어있다.
it's the internal js engine construct that holds identifier-variable mapping. (here identifier refers to the name of variables/functions, and variable is the reference to actual object [including function type object] or primitive value). A lexical environment also holds a reference to a parent lexical environment.
: 변수 scope, 함수 scope는 그 변수나 함수가 보여지는, 그리고 접근 가능한 공간/장소
를 의미한다. local scope(block scope, function scope) 와 global scope로 나뉜다.
: 런타임에서 실행 스택의 상태를 의미한다.
Execution contexts contain the current evaluation state of code, a reference to the code (function) itself, and possibly references to the current lexical environments.
Execution contexts are managed in a stack.
and the global execution context stays at the bottom of this stack.
함수안에 있는 코드를 읽어나가면서 무엇이 먼저 실행되고 나중에 실행되어야하는지에 대한 정보가 담겨있다. 그리고 함수가 실행되면 stack에서 execution context가 pop된다.
그리고 전역객체(window)와 this가 stack가장 밑에 깔려있다. 그리고 window === this // true
이다
The best way to think of an execution context is as a stack frame, while lexical environments are indeed the scopes.
라고 한다 ㅎㅎ
: 이 글 참고
:이 글 참고
: 오류 검사를 더더욱 엄격하게 한다. 최상단에 "use strict"
를 적음으로써 모드가 적용된다.
출처 : https://www.tcpschool.com/javascript/js_exception_strict
: 사실 둘다 거의 비슷하다. 그러나 다른점이 분명히 있다. 공통점과 차이점을 기준으로 설명하겠다.
&
,extends
키워드로 확장이 가능하다. interface Kitten {
purrs: boolean;
}
interface Kitten {
colour: string;
}
// In the other case a type cannot be changed outside of
// its declaration.
type Puppy = {
color: string;
};
type Puppy = {
toys: number;
};
이때 interface는 오류가 안나고 type은 오류가 난다.
접근 가능성 | public | protected | private |
---|---|---|---|
클래스 내부 | O | O | O |
상속 클래스 내부 | O | O | X |
클래스 인스턴스 | O | X | X |
: 클래스 construct object를 통해서만 접근 가능하며 다른 class 멤버변수와 엮이지 않는다. 그리고 class레벨이기에 instance를 만들때마다 생겨나지 않아서 메모리 절약도 된다.
그리고 public, private, protected 와 같은 visibility modifiers를 붙일 수 있다.
원리: virtual DOM(이하 vDOM)을 사용한다. state가 변화되었을때 이전 vDom과 새로운 vDOM을 비교하여 바뀐 부분만 계산해서 다시 rendering된다. SPA에서 흔히 일어나는 작업이다. 메모리에서만 상징적으로 존재하는 vDOM을 쓰더라도 매번 비교해서 그려줘야하기에 비효율적일 수 있다.
특징: 선언적이고 컴포넌트 기반으로 코드를 짠다.
그리고 전반적으로 보면 리액트는 MVC패턴에서 메인으로 V(view)를 담당한다. 그러나 컴포넌트안에 model, view, controller를 모두 구현 할 수 있다.
역할 | 담당 |
---|---|
Model | state 또는 store |
View | JSX |
Controller | 컴포넌트안에 있는 로직 |
MVC패턴에 대해 더 알고 싶다면 요기 들어가보기
REACT 가 DOM을 다루는 원리에 대해서 이해하고 싶다면 요기
: 프로그래밍 컨셉이다. DOM fragment를 이용해서 노드를 하나하나 만들고 비교해서 새로 바뀐것만 DOM에 던져주어도 된다. 그러나 virtual DOM은 이 모든것을 자동으로 수행한다고 보면 된다.
출처
: mount 👉 update 👉 unMount
render: DOM 트리를 계산하기위해 각 element의 속성을 계산
paint: 실제 스크린에 layout을 표시하고 그리는 과정
useEffect(추천)
useLayoutEffect
:setState를 통해서 변경해야만 rendering이 다시 일어나기 때문이다. 그리고 리액트가 클로져를 통해 state를 안전하게 고립해서 관리하고 있기 때문이다.
: 컴포넌트가 렌더될 때, useCallback 은 이전 렌더에서 정의한 함수 자체를 메모이제이션하고, useMemo 는 이전 렌더에서 계산한 함수의 실행 결과를 메모이제이션합니다. 따라서 useCallback 은 debounce 등의 처리를 하거나, React.memo 로 감싸진 컴포넌트에 props 를 전달하는 등 함수 인스턴스가 바뀌는 상황에서 사용되고, useMemo 는 컴포넌트가 렌더되는 중에 복잡한 연산을 해야 할 경우 이를 최적화하는 데에 유용하게 쓰이곤 합니다.
XXS(Cross-Site Scripting): 공격자가 어떤 버튼이나 게시물같은곳에 스크립트를 삽입하고 사용자가 그걸 클릭하면 사용자의 중요한 정보를 빼거나 하는 등 의도지 않은 행위를 수행하게 한다.
해결책
CSRF(Cross-Site Request Forgery): 공격자의 스크립팅이 삽입된 페이지를 사용자가 클릭하면 그 스크립팅이 서버에 악의적인 영향을 끼치는 것을 말한다. 그리고 사용자는 이미 권한을 인증받은 사용자이다. 이 점을 이용해서 사용자로 하여금 악의적인 요청 스크립트가 삽입된 어떤 것을 클릭하게 만든다.
그럼, 주문을 한다거나, 글을 쓴다거나, 계좌정보를 조작한다거나 하는 등 서버를 조작하게 된다.
웹사이트가 브라우저를 신뢰하는 것을 이용한 공격이다. 웹사이트 서버가 타겟이 된다. 사용자는 자기도 모르게 서버를 공격하게 되는 것을 의미한다.
해결책
쿠키에 관한 글에서 언급했으니 참고하면 될듯
✨보너스: CORS(Cross Origin Resouce Sharing)정책이 CSRF를 막아주는 걸까 아님 오히려 CSRF공격에 취약하게 만드는 걸까? CORS는 SOP(Same Origin Policy)의 단점을 보완하기 위해 만들어진 정책이다. 요새는 같은 도메인(origin)이 아닌 다른 도메인에서 자원을 요청하는 경우가 대부분이니.
그럼 당연히 보안 문제가 대두될 수 밖에 없다. 그래서 CORS는 Access-Control-Allow-Origin
을 통해 자원이 공유가능한 도메인을 설정해놓고 preflight
라는 예비요청을 보내는 것이다. 예비요청은 서버에 클라이언트가 집에 방문하기전(본요청) 미리 전화로 확인하는 작업과 같다. '어디사는 누구인데 케익 들고가도되?' 그때 서버는 전화건 사람이 초대받을 수 있는 명단에 있는지 확인하고 다시 전화를 준다. '너는 명단에 없으니 올수 없어'. 이 상황은 CORS를 위반한 상황이다.
근데 CSRF는 공격자가 이미 인가
받은 사용자를 속여서 forgery request를 서버로 보내게 만드는 것이니, CORS는 CSRF공격과 큰 연관이 없다고 봐야 하나 모르겠다. 애초에 다른 도메인을 허용하게 하니 오히려 공격에 취약하게 만드는 것일지도...
: 인증이 이루어지고 난 뒤에 인가가 이루어짐.
인증(authentication)
인가(authorization)
그리고 브라우저에 따라서 합성단계가 나타난다. 합성은 layer들을 한장의 비트맵으로 만들어서 reflow,repaint를 최소화 한다.
html(dom tree),css(cssom tree) 파싱 👉 랜더트리 구축 👉 레이아웃 👉 페인트 👉 합성
주로 위와 같이 Critical Rendering Path가 구성되며 reflow는 layout부터 repaint는 페인트부터 다시 CRP가 일어난다. 즉 리플로우가 가장 최악의 경우이므로 리플로우는 되도록 피해야한다.
그럼 언제 리플로우와 리페인트가 일어날까?
쿠키: 서버는 기본적으로 상태를 가지고 있지 않으며 연결이 지속되지 않는다. 그래서 클라이언트에서 서버에 요청을 보낼 때마다
클라이언트의 상태(로그인, 접속시간, 선택한 언어 etc)를 쿠키에 담아서 보내게 된다. 용량은 대략 20kb이며 저장가능한 쿠키는 최대 20개이다.
쿠키에는 만료기간을 설정할 수 있다.
그리고 httpOnly
옵션을 true로 하면 document.cookie
를 통해 접근 불가능 하므로 XXS공격도 막을 수 있으니 true로 설정해두는게 좋다.
그리고 중요한 정보는 절대 쿠키에 저장하지 말자. 언제 탈취될지 모르니깐.
참고로 쿠키는 브라우저에서만 사용가능하다 안드로이드나 IOS에서는 쿠키를 사용할 수 없기때문에 토큰(그냥 string이다.)을 사용한다.
세션: 사용자 정보를 쿠키가 아닌 서버 DB에 저장하는 경우이다. 그러므로 쿠키보다 보안이 더 잘 보장된다. 그리고 쿠키에 포함된 sessionID를 식별자로 클라이언트를 확인한다. 클라이언트가 요청을 보낼때 쿠키에 sessionID가 없으면 서버에서 Set-Cookie를 통해 sessionID를 클라이언트에 보내게 된다.
그럼 이후에는 클라이언트가 그 ID를 쿠키에 포함시켜서 서버로 보내게 된다. 서버는 쿠키에 담긴 sessionID를 확인하여 적절한 자원을 보낸다.
세션은 메모리에 저장하므로 브라우저가 종료되면 사라진다.
또한, 클라이언트가 많아지면 그만큼 보관하고 있어야할 자원도 많아지므로 서버DB에 부하가 많이 걸린다. 아래는 세션의 주요 특징이다.
아래의 그림을 보면 sessionID를 발급하고 쿠키에 넣어 전송하고 정보를 주고받는 순서를 한눈에 알 수 있다.
위에서 잠깐, 클라이언트가 많아지면 세션에 부담
이라고 언급했다. 이때는 JWT를 사용할 수 있다. JWT는 클라이언트의 정보(아이디 , 비번 같은거)를 살짝 변형해서 클라이언트로 넘겨준다. 이때 클라이언트는 JWT를 잘 보관했다가 서버 요청보낼때 포함시켜 보낸다. 그럼 서버는 JWT가 변형되었는지 아닌지만 확인한후에 자원을 보내면 된다. 즉, sessionID를 보관할 DB를 만들고 DB안에 있는 ID를 찾는 일을 하지 않아도 된다.
그래서 이러한 JWT의 특성상, stateless를 유지해야할 때 유용하게 쓰인다. 블랙프라이데이처럼 특정일에 불특정 다수가 한꺼번에 몰린다고 할때 sessionID쓰면 서버가 다운될 수 있다 이때 JWT를 이용해서 클라이언트가 모든 정보를 가지고 있게 하면 DB에 부담이 훨씬 줄어들것이다.
단, JWT는 강력하게 암호화된 정보가 아닐 뿐더러 누구든지 열람할 수 있으니 중요한 정보는 JWT로 만들면 안된다.
sessionID는 id만 달랑있고 그 id에 해당되는 유저 정보는 서버 DB에 저장되어있지만 JWT안에는 id뿐만아니라 DB에 있어야 하는 유저정보가 다 들어있다. (복잡한 스트링으로 약하게 인코딩되어있어 매우 쉽게 디코딩 가능하다)
그럼 JWT의 약점을 보완하려면 어떻게 해야할까?
✨보너스
sessiondID를 사용하면 클라이언트들의 정보를 관리할 힘을 갖게 된다. 즉 어떤 유저가 로그인 되었는지 알 수 있고 이를 통해 로그인 된 친구들을 보여준다던가 , 강제 로그아웃 같은 기능을 사용할 수 있다. 단 언급되었듯이 클라이언트가 많아지면 DB도 커져야한다(redis를 주로 이상황에서 사용한다).
JWT를 사용하면 session을 위한 DB가 필요없어도 되지만 유저를 전반적으로 관리할 수 없으니 강제 로그아웃같은 기능을 구현할 수 없게 될것이다.
그래서 유저수가 적거나 유저에 대한 정보를 관리하지 않아도 되면 JWT를 쓰고 그렇지 않으면 session을 쓰자.
<출처>
: 위에 다 나와있으니 알아서 답하면 됨
: 위에 다 나와있으니 알아서 답하면 됨
: 위에 다 나와있으니 알아서 답하면 됨
: html form 태그는 기본적으로 GET,POST 두가지 메소드만 사용가능. 그렇기에 더 다양한 경우를 표현하기에는 한계가 있다. 근데 REST 라는 설계도, 규약으로 데이터를 조작하고 주고받게 되면 훨씬 다양한 경우를 커버할 수 있게 된다.
:서버와 클라이언트가 정보를 주고받기 위해 따라야하는 규약. address, method, data type, expiration 같은 정보를 폼에 맞게 보낸다.
(우체국에서 편지보낼때를 생각해보거라)
HTTPS는 간단하게 말해, HTTP규약을 통해 전송되는 plain text를 암호화 시키는 규약을 의미한다. HTTP는 80포트를 쓰는데 비해 HTTPS는 443포트를 사용한다.
즉, HTTP 같은 경우엔, 정보를 누구나 탈취해서 열람할 수 있기에 이를 SSL(Secure Socket Layer)/TLS(Transport Layer Security)로 한 번 감싸서 서버/클라이언트에 메시지를 보내게 된다.
또한 HTTP와는 달리 서로의 신원을 확인함으로써 인증된 서버/사용자인지 검증하는 기능도 있다.
신원을 확인하면 데이터를 암호화 하여 통신하는데 암호화 할때 비대칭 키를 사용한다. 비대칭 키란 암호화 할때의 키와 복호화 할때의 키가 다르다는 것을 의미한다. 데이터에 암호키를 적용하여 보낸다. 암호키는 공통키로써 해커가 탈취해도 복호화키가 없으므로 해독하지 못한다.
그리고, HTTPS로 통신할때는 어떤 일련의 과정을 거치는데 이를 handshake라고 한다. 더 자세하게 알아보자
아래와 같은 과정을 서로 번갈아 주고받음으로써 서로의 신원을 확인하고 비대칭 키를 생성해낸다
그럼 이제 클라이언트에서 결제할때 사용자가 입력하는 개인정보를 암호화 해서 서버로 전송하게 되는 것이다.
출처