Repository: baeharam/Must-Know-About-Frontend
Branch: main
Commit: 8dee553abd9f
Files: 57
Total size: 120.0 KB
Directory structure:
gitextract_qcdtrx2_/
├── .github/
│ └── PULL_REQUEST_TEMPLATE.md
├── Notes/
│ ├── css/
│ │ ├── bfc.md
│ │ ├── block-inline-inline-block.md
│ │ ├── box-model.md
│ │ ├── center.md
│ │ ├── float-clear.md
│ │ ├── grid.md
│ │ ├── img-space.md
│ │ ├── margin-collapsing.md
│ │ ├── reset-normalize.md
│ │ └── z-index.md
│ ├── frontend/
│ │ ├── bom-dom.md
│ │ ├── browser-rendering.md
│ │ ├── bundler-transpiler.md
│ │ ├── ci-cd.md
│ │ ├── csr-ssr.md
│ │ ├── css-js-animation.md
│ │ └── engine.md
│ ├── html/
│ │ ├── data.md
│ │ ├── doctype.md
│ │ ├── script-tag-type.md
│ │ ├── semantic.md
│ │ ├── standard-quirks.md
│ │ └── web-storage-api.md
│ ├── javascript/
│ │ ├── ajax.md
│ │ ├── closure.md
│ │ ├── es11.md
│ │ ├── es6.md
│ │ ├── es7-es8.md
│ │ ├── es9-es10.md
│ │ ├── event-delegation.md
│ │ ├── event-loop.md
│ │ ├── execution-context.md
│ │ ├── hoisting.md
│ │ ├── identity-equal.md
│ │ ├── iife.md
│ │ ├── module.md
│ │ ├── native-host.md
│ │ ├── new.md
│ │ ├── prototype.md
│ │ ├── scope.md
│ │ ├── stack-heap.md
│ │ ├── strict-mode.md
│ │ ├── this.md
│ │ └── var-let-const.md
│ ├── network/
│ │ ├── cdn.md
│ │ ├── cookie-session.md
│ │ ├── http.md
│ │ ├── http1.1-2.md
│ │ ├── https.md
│ │ ├── rest-api.md
│ │ ├── tcp-udp.md
│ │ ├── type-url-process.md
│ │ └── uri.md
│ └── security/
│ ├── sop.md
│ └── xss-csrf.md
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## 무엇이 잘못되었나요?
## 어떻게 해결하셨나요?
## 리뷰어들이 주의깊게 봤으면 하는 부분이 있으신가요?
================================================
FILE: Notes/css/bfc.md
================================================
# Block Formatting Context
MDN의 정의를 보면,
> *BFC는 웹페이지의 블록 레벨 요소를 렌더링하는데 사용되는 CSS의 비주얼 서식 모델 중 하나이다.*
즉, 블록 레벨 요소가 포함되는 **서식모델** 이다.
<br>
## 생성 조건
BFC가 생성되기 위해선 다음과 같은 조건 중 하나를 만족해야 한다.
* 루트 혹은 이를 포함하는 요소
* float가 none이 아니면서 clear 되지 않은 경우
* position이 absolute / fixed
* display가 inline-block / tabel-cell / tabel-caption
* overflow가 visible이 아님
* display가 flex / inline-flex
위 조건에 따른 예제를 보면, 아래 요소들은 모두 BFC를 생성한다.
```html
<div class="float"></div>
<div class="position"></div>
<div class="display"></div>
<div class="overflow"></div>
<div class="flex"></div>
```
```css
.float { float: left; }
.position { position: absolute; }
.display { display: inline-block; }
.overflow { overflow: hidden; }
.flex { display: flex; }
```
<br>
## 활용
1. **마진겹침 제거하기**
```html
<div class="bfc">
<p>element</p>
<p>element</p>
<div class="new-bfc">
<p>element</p>
</div>
</div>
```
```css
div {
background-color: blue;
}
p {
margin: 10px 0;
background-color: green;
}
.bfc {
overflow: hidden;
}
.new-bfc {
overflow: hidden;
}
```
[Codepen](https://codepen.io/BaeHaram/pen/YzXGZBd)
`p` 태그 사이에 10px의 마진이 마진겹침으로 인해 20px이 아닌 10px이 되었다. 이 때 새로운 BFC를 생성해서 `p` 를 집어넣으면 마진겹침을 해결할 수 있다.
2. **float된 요소들 포함하기**
```html
<div class="container">
<div class="float"></div>
</div>
```
```css
.container {
border: 3px solid red;
overflow: hidden;
}
.float {
float: left;
width: 500px;
height: 300px;
background-color: yellow;
}
```
[Codepen](https://codepen.io/BaeHaram/pen/oNXZBXJ)
보통 float된 요소를 포함하기 위해선 `.clearfix` 핵을 사용하지만 새로운 BFC를 생성함으로도 해결할 수 있다.
3. **float된 요소를 감싸는 텍스트를 분리하기**
```html
<div class="container">
<div class="box"></div>
<p>많은 양의 텍스트....</p>
</div>
```
```css
.container {
border: 3px solid red;
overflow: hidden;
}
.box {
float: left;
width: 100px;
height: 100px;
background-color: green;
}
p {
overflow: hidden;
}
```
[Codepen](https://codepen.io/BaeHaram/pen/VwLpPvN)
`p` 태그로 새로운 BFC를 생성하여 텍스트가 float 된 요소를 감싸지 않도록 하였다.
<br>
## 참고
* [Understanding Block Formatting Contexts in CSS](https://www.sitepoint.com/understanding-block-formatting-contexts-in-css/)
* [MDN, Block formatting context](https://developer.mozilla.org/ko/docs/Web/Guide/CSS/Block_formatting_context)
================================================
FILE: Notes/css/block-inline-inline-block.md
================================================
# block vs inline vs inline-block
| 특징 | block | inline | inline-block |
| ---------------------------- | ------------------ | ------------------ | ------------------ |
| 상하 마진/패딩 | :white_check_mark: | :x: | :white_check_mark: |
| 좌우 마진/패딩 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| 요소 사이 줄바꿈 | :white_check_mark: | :x: | :x: |
| 기본너비가 부모너비 | :white_check_mark: | :x: | :x: |
| 요소 사이 공백 | :x: | :white_check_mark: | :white_check_mark: |
| 너비와 높이 명시했을 때 적용 | :white_check_mark: | :x: | :white_check_mark: |
[Codepen](https://codepen.io/BaeHaram/pen/poJaRyK) 을 통해서 확인해보면 위의 특징들을 좀 더 명확하게 알 수 있으니 해보도록 하자.
<br>
## 참고
* [Gist, css-display.md](https://gist.github.com/Asheq/1ef5ec77b8e89c2c9da89d2b7a1cf8cb)
* [Stackoverflow, CSS display: inline vs inline-block](https://stackoverflow.com/questions/9189810/css-display-inline-vs-inline-block)
================================================
FILE: Notes/css/box-model.md
================================================
# Box Model
<p align="center">
<img src="../../images/css/box model.png">
</p>
문서상의 요소들을 시각적인 목적을 위해서, 모든 요소를 하나의 "직사각형 박스"로 여기는 모델이다. 모든 박스는 아래 영역들을 갖는다.
* **컨텐츠 영역(Content Area)** : 글이나 이미지, 비디오 등 요소의 실제 내용을 포함한다.
* **안쪽여백 영역(Padding Area)** : 안쪽여백 경계(Padding Edge)가 감싼 영역으로 컨텐츠 영역을 요소의 안쪽 여백까지 포함하는 크기로 확장한다.
* **테두리 영역(Border Area)** : 테두리 경계(Border Edge)가 감싼 영역으로, 안쪽여백 영역을 요소의 테두리까지 포함하는 크기로 확장한다.
* **바깥여백 영역(Margin Area)** : 바깥여백 경계(Margin Edge)가 감싼 영역으로, 테두리 영역을 확장해 요소와 인근 요소사이의 빈 공간까지 포함하도록 한다.
<br>
## box-sizing
box-sizing 속성을 사용하면, `width` 와 `height` 이 컨텐츠 영역 기준인지, 테두리 영역 기준인지 정할 수 있다.
* `box-sizing: content-box` : 기본값이며 컨텐츠 영역 기준이다. 즉, 안쪽여백 영역부터 포함하지 않는다.
* `box-sizing: border-box` : 테두리 영역 기준이며 바깥여백 영역부터 포함하지 않는다.
<br>
## 참고
* [MDN, CSS 기본 박스 모델 입문](https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model)
* [W3, CSS Box Model Module Level 3](https://www.w3.org/TR/css-box-3/)
* [BrainJar, CSS Positioning](http://www.brainjar.com/css/positioning/)
================================================
FILE: Notes/css/center.md
================================================
# 가로/세로 가운데 정렬하기
## div의 가운데 정렬
```html
<div class="position-margin"></div>
<div class="position-transform"></div>
<div class="flex">
<div></div>
</div>
```
위와 같이 마크업이 되어있다고 했을때 다음 방법들을 사용할 수 있다.
### position과 margin
```css
.position-margin {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
```
원래 `div` 는 부모의 너비만큼 너비를 갖기 때문에 자신의 너비가 있다 하더라도 보이지 않는 공간이 있다. 이런 특성 때문에 `margin: 0 auto` 와 같이 가로 가운데 정렬을 할 수 있는데, `position: absolute` 를 쓰면 이 공간이 사라지게 된다. 따라서, 해당 공간을 전체로 확장하기 위해서 `left` , `right` , `top` , `bottom` 을 각각 0으로 설정해주었다. 이렇게 되면 보이지 않는 공간이 가로/세로를 전부 차지하게 되고 여기서 `margin: auto` 를 주면 알아서 바깥여백이 만들어지기 때문에 전체적으로 가운데 정렬된다.
### position과 transform
```css
.position-transform {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
```
`div` 의 너비와 높이를 모를 때 유용한 기법으로 부모 기준으로 50% 위/왼쪽에서 떨어진다음 자신의 너비/높이의 50%를 다시 역방향으로 오게 하는 방법이다.
### flex
```css
.flex {
display: flex;
justify-content: center;
align-items: center;
}
```
부모에게 `display: flex` 를 줘야 해결할 수 있는 제약이 있고 지원하지 않는 브라우저가 있긴 하지만 그래도 상당히 유용하게 쓰인다.
**[Codepen](https://codepen.io/BaeHaram/pen/LYVdRmL) 을 통해서 연습해보자.**
<br>
## 텍스트 요소의 가운데 정렬
### 텍스트 - padding
```html
<div>
<span>텍스트</span>
</div>
```
```css
div {
text-align: center;
padding: 3em 0;
}
```
부모에 `text-align: center` 를 줘서 자식 요소들의 텍스트를 가로 가운데 정렬 했고 높이를 주지 않고 패딩을 상/하로 줘서 세로 가운데 정렬을 했다. 이 때 패딩의 단위로 `em` 을 사용했는데 이는 현재 엘리먼트의 폰트 크기의 3배를 의미한다. 즉, 폰트 크기가 바뀔 때마다 패딩도 변하기 때문에 유동적으로 세로 가운데 정렬이 이루어지는 방법이다.
### 텍스트 - line-height
```css
div { height: 100px; }
span { line-height: 100px; }
```
만약 높이를 명시적으로 준다면, 텍스트 요소에게 동일한 크기의 `line-height` 를 주어서 해결할 수 있다.
### 이미지
```html
<div>
<img src="이미지주소">
<span>텍스트</span>
</div>
```
```css
img {
vertical-align: middle;
}
```
이미지의 정렬도 위와 같이 할 수 있는데 한가지 다른 점은, 폰트의 baseline 기준으로 배치가 되기 때문에 이를 middle로 맞춰야 제대로된 정렬이 이루어진다.
**[Codepen](https://codepen.io/BaeHaram/pen/oNXqzJo) 을 통해서 연습해보자.**
<br>
## 참고
* [빔캠프, div 가로세로 모두 가운데 정렬 css position (유튜브)](https://www.youtube.com/watch?v=vdvLfkn9wp4)
* [빔캠프, 너비높이를 알 수 없는 div 가로세로 모두 가운데 정렬 (유튜브)](https://www.youtube.com/watch?v=78-X1JGvCZU)
* [빔캠프, CSS 텍스트 요소 가로, 세로 가운데 정렬 (유튜브)](https://www.youtube.com/watch?v=PEYt17TlTQk)
* [Stackoverflow, Best way to center a on a page vertically and horizontally?](https://stackoverflow.com/questions/356809/best-way-to-center-a-div-on-a-page-vertically-and-horizontally)
================================================
FILE: Notes/css/float-clear.md
================================================
# float를 해제하는 방법들
float 속성을 자식 엘리먼트에 사용하게 되면 부모 엘리먼트가 자식의 높이를 감지할 수 없기 때문에 이를 반영하기 위한 방법이 필요하다. 다음 코드를 가정으로 한다.
```html
<div class="parent">
부모
<div class="child">
자식
</div>
</div>
```
```css
.child {
float: left;
}
```
<br>
## 부모 엘리먼트에 `float` 적용
* 자식을 포함할 만큼만 너비로 줄어듦
* 부모가 겹겹이 있을 경우 계속해서 float 시켜야 함
```css
.parent {
float: left;
}
```
<br>
## 부모에 `overflow` 속성 적용
* `overflow: auto` 의 경우, 자식의 너비가 더 크면 스크롤바 생김
* `overflow: hidden` 의 경우, 자식의 너비가 더 크면 잘림
```css
.parent {
overflow: hidden;
}
```
<br>
## 부모가 끝나기 전 빈 엘리먼트로 `clear` 적용
* 의미없는 엘리먼트를 넣기 때문에 권장되지 않음
```html
<div class="parent">
...
<div class="clearfix">
</div>
</div>
```
```css
.clearfix {
clear: both;
height: 0;
overflow: hidden;
}
```
<br>
## 부모에 `display: inline-block` 적용
* 약간의 여백이 생김
* 자식의 너비를 포함할 만큼으로 줄어듦
```css
.parent {
display: inline-block;
}
```
<br>
## 가상요소로 `clear` 적용
* 제일 권장되는 방법
```css
.parent::after {
content: '';
display: block;
clear: both;
}
```
<br>
## 참조
* [float를 clear하는 4가지 방법](https://naradesign.github.io/article/float-clearing.html)
================================================
FILE: Notes/css/grid.md
================================================
# 그리드 시스템
그리드 레이아웃을 구현하기 위해 설계한 시스템으로 너비 960px 혹은 1200px 기준으로 정해놓은 시스템들이 있다. 열(Column)의 개수에 따라 12단/16단/24단 그리드라고 부르기도 한다. 그리드 레이아웃을 구현하는 방법은 여러가지가 있으며 여기선 12단 그리드로 진행한다.
> float, flexbox, grid의 기본개념과 문법들에 대해 알고있어야 한다.
<br>
## Float grid system
flexbox나 grid가 나오기 이전에 사용하던 방식으로 float 속성을 사용하여 구현한다. float된 높이를 잡기 위해 clearfix 핵을 사용해야 하며 각 너비를 열/행의 간격에 맞게 계산해주어야 한다.
**[Codepen](https://codepen.io/BaeHaram/pen/XWbYpwx) 에서 꼭 직접 해보자!**
<img src="../../images/css/float-grid.png">
```html
<h1>Float grid system</h1>
<div class="container">
<div class="row">
<div class="col col-3-12"></div>
<div class="col col-3-12"></div>
<div class="col col-3-12"></div>
<div class="col col-3-12"></div>
</div>
<div class="row">
<div class="col col-6-12"></div>
<div class="col col-6-12"></div>
</div>
<div class="row">
<div class="col col-4-12"></div>
<div class="col col-4-12"></div>
<div class="col col-4-12"></div>
</div>
</div>
```
```css
:root {
--gutter: 10px;
}
.container {
width: 500px;
border: 3px solid red;
padding: 1rem;
}
.row::after {
content: '';
display: block;
clear: both;
}
.row + .row {
margin-top: var(--gutter);
}
.col {
height: 100px;
background-color: orange;
float: left;
margin-right: var(--gutter);
}
.col:last-child { margin-right: 0; }
.col-1-12 { width: calc(100%/(12/1) - var(--gutter)*11/12); }
.col-2-12 { width: calc(100%/(12/2) - var(--gutter)*10/12); }
.col-3-12 { width: calc(100%/(12/3) - var(--gutter)*9/12); }
.col-4-12 { width: calc(100%/(12/4) - var(--gutter)*8/12); }
.col-5-12 { width: calc(100%/(12/5) - var(--gutter)*7/12); }
.col-6-12 { width: calc(100%/(12/6) - var(--gutter)*6/12); }
.col-7-12 { width: calc(100%/(12/7) - var(--gutter)*5/12); }
.col-8-12 { width: calc(100%/(12/8) - var(--gutter)*4/12); }
.col-9-12 { width: calc(100%/(12/9) - var(--gutter)*3/12); }
.col-10-12 { width: calc(100%/(12/10) - var(--gutter)*2/12); }
.col-11-12 { width: calc(100%/(12/11) - var(--gutter)*1/12); }
.col-12-12 { width: calc(100%/(12/12) - var(--gutter)*0/12); }
.col:nth-child(even) {
background-color: blue;
}
```
`row::after` 로 clearfix 핵을 적용하였고 행의 `margin` 으로 수직 간격을, 열의 `margin` 으로 수평 간격을 지정하였다. 또한 12단 그리드이기 때문에 `.col-x-12` 가 뜻하는 것은 12단 중에 x개를 차지하는 너비를 말한다. 간격에 유동적으로 적용하기 위해 간격변수인 `--gutter` 기준으로 계산하였다.
<br>
## Flexbox grid system
**[Codepen](https://codepen.io/BaeHaram/pen/oNXyZvv) 에서 꼭 직접 해보자!**
<img src="../../images/css/flexbox-grid.png">
대부분 float를 사용한 방식과 동일하되, clearfix 핵을 없애고 flex를 적용한 것이다.
```css
/*.row::after {
content: '';
display: block;
clear: both;
}*/
.row {
display: flex;
}
```
<br>
## Grid layout grid system
grid를 사용한 경우로, float/flexbox와는 완전히 다르다. 너비를 계산하지도 않고 `row` 나 `column` 을 따로 지정하지 않는다. 단순하게 grid 관련된 속성을 사용해서 열/행의 너비 및 높이와 각 항목의 비율을 지정한다.
**[Codepen](https://codepen.io/BaeHaram/pen/JjdZWoQ) 에서 꼭 직접 해보자!**
<img src="../../images/css/grid-grid.png">
```html
<h1>Grid layout grid system</h1>
<div class="container">
<div class="grid">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
<div class="item item-7">7</div>
<div class="item item-8">8</div>
</div>
</div>
```
```css
.container {
width: 500px;
border: 3px solid red;
padding: 1rem;
}
.grid {
display: grid;
height: 500px;
grid-template-rows: repeat(4,1fr);
grid-template-columns: repeat(3,1fr);
grid-row-gap: 10px;
grid-column-gap: 10px;
}
.item {
background-color: crimson;
text-align: center;
font-size: 2rem;
font-weight: bold;
}
.item:nth-child(even) {
background-color: yellow;
}
.item-3 {
grid-row: 1/3;
grid-column-start: 3;
}
.item-6 {
grid-column: 1/4;
grid-row: 3/4;
}
```
<br>
## 참고
* [Sass로 12단 그리드 시스템 만드는 법](https://medium.com/fluosoup/sass로-12단-그리드-시스템-만드는-법-d2c7cf54c36)
* [CSS Grid 완벽 가이드](https://heropy.blog/2019/08/17/css-grid/)
================================================
FILE: Notes/css/img-space.md
================================================
# img 아래쪽 공백 제거
## img의 공백
`<img>` 태그를 사용할 때 기본적으로 아래쪽에 공백이 생긴다.
```html
<div class="container">
<img src="https://images.unsplash.com/photo-1584380497382-2722e59ff33f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=687&q=80" alt="">
</div>
```
```css
.container {
width: 300px;
border: 1px solid crimson;
}
img {
max-width: 100%;
}
```
<p align="center">
<img src="../../images/css/img-space.png">
</p>
<br>
## 공백이 생기는 이유
`<img>` 태그는 인라인-레벨 요소이기 때문에 기본적으로 일반 텍스트와 동일하게 baseline 기준으로 정렬이 된다. 이 말은 즉, `vertical-align: baseline` 이 기본값이라는 말이다.
<p align="center">
<img src="../../images/css/img-baseline.gif">
</p>
[이미지 출처](https://stackoverflow.com/a/34952703/11789111)
위 그림에서 텍스트가 baseline 기준으로 정렬된 것을 볼 수 있는데 `<img>` 도 마찬가지이다. baseline 기준으로 정렬된 인라인-레벨 요소는 알파벳의 y, j, p, g, q 등과 같은 하강문자(descender)를 위해 아래쪽에 더 공간이 있어야 하기 때문에 `<img>` 의 아래쪽에 공백이 생기는 것이다.
<br>
## 해결방법
* `<img>` 에 `display: block`
* 블록-레벨 요소로 바꿔서 해결하는 방법인데 이러면 한 줄을 다 차지한다는 단점이 있다.
* 컨테이너에 `line-height: 0`
* 컨테이너에 포함된 인라인 요소의 `line-height` 를 없애는 방법인데, 그 안에 포함된 모든 텍스트의 `line-height` 에 영향을 주기 때문에 좋은 방법이 아니다.
* **`<img>` 에 `vertical-align: middle/top/bottom`**
* `vertical-align` 을 바꾸는 방법으로 baseline 의 경우에만 아래쪽 공간이 생기니 기준을 바꿔버리는 것이다. **가장 좋은 방법이다.**
<br>
## 참고
* [Image inside div has extra space below the image](https://stackoverflow.com/questions/5804256/image-inside-div-has-extra-space-below-the-image)
================================================
FILE: Notes/css/margin-collapsing.md
================================================
# 마진겹침 현상
마진겹침(Margin-Collpasing)이란 블록 레벨 엘리먼트(Block-level element)에 한해서 발생하는 현상으로, 좌우 방향으로는 적용되지 않고 **오로지 수직방향** 으로 적용된다. 2개의 마진이 겹칠 때 더 큰 마진으로 덮어 씌우는 방식이며 하나의 마진이 음수일 경우 더하는 방식을 취한다.
<br>
## 3가지 경우
마진겹침은 블록 레벨 엘리먼트라는 가정하에 3가지 경우에 한해서 발생한다.
1. **인접한 엘리먼트**
```html
<div class="element1"></div>
<div class="element2"></div>
```
```css
div {
width: 100px;
height: 100px;
background-color: red;
}
.element1 { margin-bottom: 20px; }
.element2 { margin-top: 40px; }
```
<p align="center">
<img src="../../images/css/margin-collapsing1.png">
</p>
두번째 엘리먼트의 위쪽 마진이 더 크기 때문에 둘 사이의 간격은 40px이 된다.
2. **부모와 처음/마지막 자식 사이에서**
```html
<div class="parent">
<div class="child">
</div>
</div>
```
```css
div {
width: 100px;
height: 100px;
}
.parent {
background-color: red;
margin-top: 20px;
}
.child {
background-color: blue;
margin-top: 20px;
}
```
<p align="center">
<img src="../../images/css/margin-collapsing2.png">
</p>
둘의 마진이 같기 때문에 20px이 된다. 이를 해결하기 위해선 **부모에 inline 컨텐츠, border, padding** 을 줘서 경계를 구분시키면 된다.
```css
.parent {
background-color: red;
border: 1px solid red;
margin-top: 20px;
}
```
<p align="center">
<img src="../../images/css/margin-collapsing3.png">
</p>
3. **빈 엘리먼트**
```html
<div class="empty"></div>
<div class="element"></div>
```
```css
.empty { margin-top: 50px; }
.element {
width: 100px;
height: 100px;
background-color: red;
margin-top: 100px;
}
```
<p align="center">
<img src="../../images/css/margin-collapsing4.png">
</p>
높이가 없는 빈 엘리먼트가 인접해있을 때도 마진겹침이 발생하여 위쪽 마진은 100px이 된다. 이를 해결하기 위해선 **빈 엘리먼트에 height, min-height, padding, border나 inline 컨텐츠** 를 줘서 경계를 구분시키면 된다.
```css
.empty {
border: 1px solid red;
margin-top: 50px;
}
```
<p align="center">
<img src="../../images/css/margin-collapsing5.png">
</p>
<br>
## 예외 대상
`position: absolute` , `float: left` , `display: flex` 등 다양한 상황에 마진겹침이 발생하지 않지만, 그냥 **새로운 BFC(Block Formatting Context)를 생성하는 조건이 마진겹침을 발생시키지 않는다** 고 알아두면 된다.
<br>
## 참고
* [MDN, 마진 상쇄 정복](https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing)
* [Velog, CSS 마진 상쇄(Margin-collapsing) 원리 완벽 이해](https://velog.io/@raram2/CSS-%EB%A7%88%EC%A7%84-%EC%83%81%EC%87%84Margin-collapsing-%EC%9B%90%EB%A6%AC-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4#%EB%A7%88%EC%A7%84-%EC%83%81%EC%87%84-%EA%B7%9C%EC%B9%99-%EC%98%88%EC%99%B8)
* [Youtube, [ㅁ] 마진병합 margin collapsing | 코딩가나다 | 빔캠프](https://www.youtube.com/watch?v=c19Mjg-ivxc)
* [생활코딩, 마진겹침 현상](https://opentutorials.org/course/2418/13464)
================================================
FILE: Notes/css/reset-normalize.md
================================================
# Reset.css vs Normalize.css
크롬, 사파리, IE 등 각 브라우저마다 HTML 요소의 기본 스타일을 가지고 있다. 따라서, CSS로 스타일링을 적용할 때 이러한 특징이 동일한 스타일 적용을 방해하기 때문에 이를 해결하기 위해서 나온 스타일 초기화 기법들이다.
<br>
## Reset.css
**모든 브라우저 내장 스타일을 없애는 기법** 으로, 그 어떤 스타일도 없는 상태에서 스타일링을 시작한다. `h1` ~ `h6` , `p` , `em` 등 각 태그에 적용되는 스타일을 모두 없앤다. 가장 유명한 스타일은 Eric Mayer의 Reset CSS이며 이를 [깃헙](https://github.com/shannonmoeller/reset-css) 에서 유지하고 있다. 보통, 초기화를 한 후 각자의 방식에 맞게 변형해서 사용한다.
<br>
## Normalize.css
**모든 브라우저의 스타일을 동일하게 하는 기법** 으로, 스타일을 없애는 Reset.css와는 다르게 기존 스타일을 유지하되 브라우저들의 다른 스타일을 고치는 방식이다. 가장 유명한 스타일은 necolas의 normalize.css이며 이를 [깃헙](https://github.com/necolas/normalize.css/) 에서 유지하고 있다. 실제 코드의 주석을 보면 각 요소를 스타일링 하는 이유에 대해 설명하고 있다.
<br>
## 차이점과 선택
* Reset.css의 경우, 모든 것을 초기화하기 때문에 스타일을 처음부터 적용해 나가는 것이 힘들 수 있고 브라우저의 버그를 고치는 것이 아니기 때문에 각 브라우저마다 다른 버그를 발생시킬 수 있다. 하지만, 아예 초기화를 하는 것이기 때문에 업데이트가 필요없다.
* Normalize.css의 경우, 브라우저가 업데이트 되어서 새로운 내장 스타일이 적용될 때마다 각 브라우저의 다른 점을 파악하여 스타일을 업데이트해야 하기 때문에 끊임없는 버전 업데이트가 있어야 최신 스타일을 유지할 수 있다. 하지만, 브라우저의 버그를 고치기 때문에 버그가 발생할 걱정을 덜고 기본 스타일을 어느정도 유지하기 때문에 스타일링에 힘을 덜 들일 수 있다.
둘 다 장단점이 있기 때문에 어떤 것이 더 낫다라고는 할 수 없고, 상황에 맞게 적용해서 사용하면 된다고 생각한다.
<br>
## 참고
* [Stackoverflow, CSS reset - What exactly does it do?](https://stackoverflow.com/questions/11578819/css-reset-what-exactly-does-it-do)
* [Stackoverflow, What is the difference between Normalize.css and Reset CSS?](https://stackoverflow.com/questions/6887336/what-is-the-difference-between-normalize-css-and-reset-css)
* [reset.css 와 Normalize.css](https://sapjil.net/resetcss-normalizecss/)
* [About normalize.css](http://nicolasgallagher.com/about-normalize-css/)
================================================
FILE: Notes/css/z-index.md
================================================
# z-index의 동작방식
## z-index와 쌓임 맥락
z-index를 이해하기 위해선 먼저, 쌓임 맥락(Stacking Context)의 개념을 이해해야 한다. **쌓임 맥락이란, HTML 요소들에 사용자를 바라보는 기준으로 가상의 z축을 생성하여 3차원 개념으로 보는 것** 이다. 따라서, 쌓임 맥락을 형성한다는 것은 자신만의 3차원 공간을 형성하는 것이며 그 요소들의 우선순위를 z-index가 정하게 되는 원리이다.
<img src="../../images/css/stacking context.png">
[그림 출처](https://tympanus.net/codrops/css_reference/z-index/)
위 그림을 보면, 각 요소들이 사용자를 바라보는 z축 상에서 z-index에 따라 **"쌓이는"** 것을 볼 수 있다. 바로 이것이 쌓임 맥락의 개념이며 쌓임 맥락을 형성하는 조건은 [꽤 많다.](https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context) 모든 걸 기억하면 좋겠지만 중요한 것들을 기억해두록 하자.
* **position이 relative/absolute이면서 z-index가 auto가 아닌 요소**
* **position이 fixed/sticky인 요소**
* **opacity가 1보다 작은 요소**
* **transform이 none이 아닌 요소**
가장 많이 쓰는 속성들을 기준으로 조금만 나열해보면 위와 같은데 이 정도는 암기하도록 하자.
쌓임 맥락은 다음 특징들을 갖는다.
* 쌓임 맥락은 **다른 쌓임 맥락을 포함할 수 있다.**
* 쌓임 맥락에서 쌓임을 고려하는 것은 **오직 자식 요소들에 대해서** 만이다.
즉, 2개의 쌓임 맥락을 형성하는 요소가 있다고 했을 때, 각각은 독립적인 쌓인 맥락을 갖으며 그 안의 자식 요소들은 부모 안에서의 쌓임만 고려된다는 것이다.
<br>
## 우선순위
쌓임 맥락을 형성하는 요소가 아무것도 없다고 하면 다음 우선순위로 쌓이게 된다.
<img src="../../images/css/default stacking order.png">
[그림 출처](https://tympanus.net/codrops/css_reference/z-index/)
만약, 동일한 성격의 요소라면 마크업 순서로 쌓임이 결정된다. 즉, 아래와 같은 경우,
```html
<div>A</div>
<div>B</div>
<div>C</div>
```
```css
div {
position: absolute;
}
```
여기서 쌓임 맥락을 형성하는 것으로 착각할 수도 있는데 `position: absolute` 라고 해도 `z-index: auto` 이면 쌓임 맥락을 형성하지 않는다. 어쨌든 여기선 동일한 성격의 요소들이기 때문에 마크업 순서인 A,B,C 순으로 쌓임이 형성된다. ([Codepen](https://codepen.io/BaeHaram/pen/ExjmvRY) 에서 확인할 수 있다.)
쌓임 맥락을 형성한다면, `z-index` 값을 설정할 수 있는 `position: static` 이 아닌 요소들의 경우는 동일한 마크업 레벨에서, `z-index` 값으로 우선순위를 결정한다. `z-index` 값을 설정할 수 없는 요소라면 마크업 순서로 결정한다. 여기선 `position: static` 이 아니고 `z-index: auto` 가 아닌 요소를 보자.
```html
<div>1</div>
<div>2</div>
<div>3
<div>4</div>
<div>5</div>
<div>6</div>
</div>
```
마크업이 위와 같이 되어 있을 때, `z-index` 에 따라 다음과 같이 쌓인다.
<img src="../../images/css/z-index stacking order.png">
[그림출처](https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context)
* div1과 div2, div3는 같은 레벨에 있으므로 z-index에 따라 쌓이기 때문에 div2 > div3 > div1 순으로 쌓인다.
* div4와 div5, div6은 div3안에 있으므로 **그 안에서** z-index에 따라 쌓인다.
* 즉, div3 안의 요소들의 z-index가 div1,div2 보다 커도 영향을 주지 않는다.
* 결론적으로, div5 > div6 > div4 순으로 쌓인다.
<br>
## 참고
* [CSSReference, z-index](https://tympanus.net/codrops/css_reference/z-index/)
* [MDN, Stacking Context](https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context)
* [MDN, z-index](https://developer.mozilla.org/ko/docs/Web/CSS/z-index)
================================================
FILE: Notes/frontend/bom-dom.md
================================================
# BOM과 DOM
## BOM (Browser Object Model)
**브라우저의 창이나 프레임을 프로그래밍적으로 제어할 수 있게 해주는 객체모델** 이다. 이를 통해서 브라우저의 새 창을 열거나 다른 문서로 이동하는 등의 기능을 실행시킬 수 있다. 전역객체로 `window` 가 있으며 하위 객체들로 `location` , `navigator` , `document` , `screen` , `history` 가 포함되어 있다.
<img src="../../images/frontend/bom.png">
<br>
## DOM (Document Object Model)
**웹페이지를 프로그래밍적으로 제어할 수 있게 해주는 객체모델** 이다. 최상위 인터페이스로 Node가 있으며 이는 아래와 같은 구조로 나타난다.
<img src="../../images/frontend/dom.png">
[이미지 출처](https://web.stanford.edu/class/cs98si/slides/the-document-object-model.html)
위의 트리구조를 보면 엘리먼트 뿐만 아니라 텍스트와 주석도 있는 것을 알 수 있는데, 이런 것들까지도 DOM 트리에 포함된다. 실제적인 DOM 트리는 아래와 같이 생성된다.
```html
<!DOCTYPE html>
<html>
<head>
<title>제목</title>
</head>
<body>
<div class="클래스"></div>
<!-- 주석 -->
<a href="https://naver.com">네이버</a>
</body>
</html>
```
<p align="center">
<img src="../../images/frontend/dom2.png">
</p>
[Live DOM Viewer](https://software.hixie.ch/utilities/js/live-dom-viewer/) 를 사용해서 DOM 트리를 구성해 본것으로 엘리먼트 뿐만 아니라 텍스트 노드와 주석 노드까지 포함하고 있다. 이제 이런 DOM을 다루기 위해선 `getElementsById` , `querySelector` , `firstElementChild` 등과 같은 브라우저가 제공하는 DOM API를 사용하면 된다.
<br>
## 참고
* [Javascript.info, DOM 트리](https://ko.javascript.info/dom-nodes)
* [생활코딩, 웹브라우저와 자바스크립트](https://opentutorials.org/course/1375)
* [Stackoverflow, What is the DOM and BOM in JavaScript?](https://stackoverflow.com/questions/4416317/what-is-the-dom-and-bom-in-javascript)
================================================
FILE: Notes/frontend/browser-rendering.md
================================================
# 브라우저의 렌더링 원리
브라우저가 화면에 나타나는 요소를 렌더링 할 때, 웹킷(Webkit)이나 게코(Gecko) 등과 같은 **렌더링 엔진** 을 사용한다. 렌더링 엔진이 HTML, CSS, Javascript로 렌더링할 때 **CRP(Critical Rendering Path)** 라는 프로세스를 사용하며 다음 단계들로 이루어진다.
1. **HTML 파싱 후, DOM(Document Object Model) 트리 구축**
2. **CSS 파싱 후, CSSOM(CSS Object Model) 트리 구축**
3. **Javascript 실행**
* 주의! HTML 중간에 스크립트가 있다면 HTML 파싱이 중단된다.
4. **DOM과 CSSOM을 조합하여 렌더트리(Render Tree) 구축**
* 주의! `display: none` 속성과 같이 화면에서 보이지도 않고 공간을 차지하지 않는 것은 렌더트리로 구축되지 않는다.
5. **뷰포트 기반으로 렌더트리의 각 노드가 가지는 정확한 위치와 크기 계산 (Layout/Reflow 단계)**
6. **계산한 위치/크기를 기반으로 화면에 그림 (Paint 단계)**
<br>
실제로 크롬 개발자 도구를 이용해 다음 코드를 어떻게 렌더링 하는지 살펴보았다.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>테스트</title>
</head>
<body>
<div></div>
<script src="script.js"></script>
</body>
</html>
```
```css
body {
background-color: red;
}
div {
width: 100px;
height: 100px;
background-color: blue;
}
```
```javascript
document.querySelector('div').addEventListener('click', () => {
console.log('Click div');
});
```
<img src="../../images/frontend/rendering.png">
위 로그를 보면 알 수 있는 것처럼 위에서 언급한 CRP가 진행된다.
1. Parse HTML을 통해 HTML 파싱 후, DOM 트리 구축
2. Parse Stylesheet를 통해 CSS 파싱 후, CSSOM 트리 구축
3. Evaluate Script를 통해 Javascript 실행
4. 렌더트리 구축
5. Layout을 통해 뷰포트 기준으로 렌더트리 노드들의 각 크기/위치 계산
6. Paint를 통해 Layout에서 계산한 값들로 각 요소를 화면에 그림
<br>
## 참고
* [HTML Critical rendering path의 이해](https://blog.asamaru.net/2017/05/04/understanding-the-critical-rendering-path/)
* [Naver, 브라우저는 어떻게 동작하는가?](https://d2.naver.com/helloworld/59361)
* [MDN, Critical Rendering Path](https://developer.mozilla.org/en-US/docs/Web/Performance/Critical_rendering_path)
* [Google, 렌더링 트리 생성, 레이아웃 및 페인트](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction)
* [Stackoverflow, When does parsing HTML DOM tree happen?](https://stackoverflow.com/questions/34269416/when-does-parsing-html-dom-tree-happen)
================================================
FILE: Notes/frontend/bundler-transpiler.md
================================================
# 모듈 번들러와 트랜스파일러
## 모듈 번들러
> 모듈의 개념을 모른다면 이 문서의 [모듈시스템](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/module.md) 을 읽고오자.
현대의 프론트엔드 개발은 모듈단위로 파일을 엮어서 개발하는 방식이다. 즉, 모듈은 서로 의존성을 띄고 있는데 이런 점에서 다음과 같은 문제들이 생긴다.
* 수많은 모듈들의 순서를 어떻게 처리할 것인가? (의존성 처리)
* 모듈이 많아질수록 HTTP 요청이 많아질텐데 이로 인한 오버헤드는 어떻게 해결할 것인가?
* ES6+ 스펙의 코드를 어떻게 처리할 것인가?
위 문제들을 해결하기 위해 등장한 것이 **모듈 번들러(Module Bundler)로 각각의 모듈 의존성을 해결하여 하나의 자바스크립트 파일로 만드는 도구** 이다. 이미지 압축, 최소화(Minification) 등의 여러가지 기능들도 제공하며 유명한 번들러로는 Webpack, Parcel, Rollup 등이 있다.
<br>
## 트랜스파일러
트랜스파일링(Transpiling)이란 특**정 언어로 작성된 코드를 비슷한 다른 언어로 변환시키는 행위** 를 말하며 이를 해주는 것이 트랜스파일러(Transpiler)이다. 트랜스파일러가 필요한 이유는 모든 브라우저가 ES6+의 기능을 제공하지 않기 때문에 이를 ES5 코드로 변환시키는 과정이 필요하다. 트랜스파일러는 이 작업을 수행해준다. 사실 ES6+의 기능 뿐만 아니라 리액트의 JSX를 자바스크립트 코드로 변환시킨다거나 타입스크립트를 자바스크립트로 변환시키는 등의 역할도 트랜스파일러의 기능 중에 하나이다. ES6+나 JSX를 변환시키는 트랜스파일러로는 바벨(Babel)이 있으며 타입스크립트를 변환시키는 도구로는 타입스크립트 트랜스파일러가 있다. 보통 프론트엔드 프레임워크 및 라이브러리를 사용해서 개발할 때 모듈 번들러에 트랜스파일러를 추가해서 사용하는 방식을 사용한다.
<br>
## 참고
* [What is module bundler and how does it work?](https://dev.to/tanhauhau/what-is-module-bundler-and-how-does-it-work-3gp2)
* [트랜스파일이란?](https://ooz.co.kr/416)
================================================
FILE: Notes/frontend/ci-cd.md
================================================
# CI와 CD
## CI (Continuous Integration, 지속적 통합)
CI는 빌드와 테스트를 자동화해서 공유 저장소에 병합시키는 프로세스를 뜻한다. git과 같은 버전관리 시스템을 사용할 때 여러명의 개발자가 하나의 공유 저장소를 사용하는 경우가 많다. 이렇게 되면 새로운 코드의 변경 사항이 저장소에 통합되지 않을 경우 서로 충돌할 수 있다. 따라서 빌드/테스트 자동화부터 코드의 일관성(Consistency)을 제공하기 때문에 지속적으로 통합한다는 용어를 사용하는 것이다.
<br>
## CD (Continuous Delivery/Deploy, 지속적 전달/배포)
CD는 CI의 빌드/테스트를 통해서 정상적으로 수행됨을 확인하면 이는 배포를 수동으로 하느냐 자동으로 하느냐에 따라 2가지로 나뉜다.
* **지속적 전달** : 프로덕션 배포를 위한 상태가 되고 배포 자체는 수동으로 실행한다.
* 개발팀과 비즈니스팀간의 커뮤니케이션 부족 문제를 해결한다.
* **지속적 배포** : 프로덕션까지 자동으로 배포한다.
* 어플리케이션의 제공 속도를 증가시킨다.
<br>
CI/CD의 대표적인 서비스로 Jenkins, Travis CI, Circle CI 등이 있으며 이를 다이어그램으로 보면 아래와 같다.
<img src="../../images/frontend/ci-cd.png">
[이미지 출처](https://aws.amazon.com/ko/devops/continuous-integration/)
<br>
## 참고
* [AWS, 지속적 통합이란 무엇입니까?](https://aws.amazon.com/ko/devops/continuous-integration/)
* [Red Hat, CI/CD(지속적 통합/지속적 제공): 개념, 방법, 장점, 구현 과정](https://www.redhat.com/ko/topics/devops/what-is-ci-cd)
* [개발자노트님, CI(Continuous Integration), CD(Continuous Delivery/Deployment)에 대해 알아보자.](https://jhleed.tistory.com/130)
================================================
FILE: Notes/frontend/csr-ssr.md
================================================
# CSR(Client Side Rendering)과 SSR(Server Side Rendering)
## SPA와 MPA
* **SPA (Single Page Application)**
하나의 HTML 파일을 기반으로 자바스크립트를 이용해 동적으로 화면의 컨텐츠를 바꾸는 방식의 웹 어플리케이션이다.
* **MPA (Multiple Page Application)**
사용자가 페이지를 요청할 때마다, 웹 서버가 요청한 UI와 필요한 데이터를 HTML로 파싱해서 보여주는 방식의 웹 어플리케이션이다.
전통적인 방식을 이용한다면, SPA가 사용하는 렌더링 방식은 CSR이고, MPA가 사용하는 렌더링 방식은 SSR이다. 각 방식의 동작방식과 장단점을 알아보고, 전통적인 방식을 벗어나, SPA에서도 적절히 SSR을 구현했을 때의 장점과 그 이유를 알아보자.
<br>
## CSR
<img src="../../images/frontend/CSR.png">
[이미지 출처](https://medium.com/@adamzerner/client-side-rendering-vs-server-side-rendering-a32d2cf3bfcc)
CSR에선 브라우저가 서버에 HTML과 JS 파일을 요청한 후 로드되면 사용자의 상호작용에 따라 JS를 이용해서 동적으로 렌더링을 시킨다.
### :+1: 장점
* 첫 로딩만 기다리면, 동적으로 빠르게 렌더링이 되기 때문에 사용자 경험(UX)이 좋다.
* 서버에게 요청하는 횟수가 훨씬 적기 때문에 서버의 부담이 덜하다.
### :-1: 단점
* 모든 스크립트 파일이 로드될 때까지 기다려야 한다.
* 리소스를 청크(Chunk) 단위로 묶어서 요청할 때만 다운받게 하는 방식으로 완화시킬 수 있지만 완벽히 해결할 수는 없다.
* 검색엔진의 검색 봇이 크롤링을 하는데 어려움을 겪기 때문에 검색엔진 최적화(Search Engine Optimization)의 문제가 있다.
* 구글 봇의 경우는 JS를 지원하지만, 다른 검색엔진의 경우 그렇지 않기 때문에 문제가 된다.
<br>
## SSR
<img src="../../images/frontend/SSR.png">
[이미지 출처](https://medium.com/@adamzerner/client-side-rendering-vs-server-side-rendering-a32d2cf3bfcc)
SSR에선 브라우저가 페이지를 요청할 때마다 해당 페이지에 관련된 HTML, CSS, JS 파일 및 데이터를 받아와서 렌더링을 시킨다.
### :+1: 장점
* 초기 로딩 속도가 빠르기 때문에 사용자가 컨텐츠를 빨리 볼 수 있다.
* JS를 이용한 렌더링이 아니기 때문에 검색엔진 최적화가 가능하다.
### :-1: 단점
* 매번 페이지를 요청할 때마다 새로고침 되기 때문에 사용자 경험이 SPA에 비해서 좋지 않다.
* 서버에 매번 요청을 하기 때문에 서버의 부하가 커진다.
<br>
## 참고
* [Client-Side Rendering versus Server-Side Rendering!](https://altalogy.com/blog/client-side-rendering-vs-server-side-rendering/)
* [What are Single Page Applications(SPA)?](https://dev.to/kendyl93/what-are-single-page-applications-spa-32bh)
* [The Benefits of Server Side Rendering Over Client Side Rendering](https://medium.com/walmartlabs/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8)
* [싱글 페이지 어플리케이션에서의 검색 엔진 최적화 (SEO)](https://funnygangstar.tistory.com/entry/싱글-페이지-어플리케이션에서의-검색-엔진-최적화-SEO)
* [Google I/O 2019: Day 3 후기](https://hyunseob.github.io/2019/05/26/google-io-2019-day-3/)
* [[주니어탈출기] 서버사이드렌더링(SSR) & 클라이언트사이드렌더링(CSR)](https://velog.io/@zansol/확인하기-서버사이드렌더링SSR-클라이언트사이드렌더링CSR)
* [SPA 단점에 대한 단상](https://m.mkexdev.net/374)
* [CSR vs SSR](https://medium.com/@adamzerner/client-side-rendering-vs-server-side-rendering-a32d2cf3bfcc)
================================================
FILE: Notes/frontend/css-js-animation.md
================================================
# CSS 애니메이션 vs JS 애니메이션
웹사이트에 애니메이션 효과를 부여할 때 CSS의 `transition` / `animation` 속성을 사용할 수 있고 JS의 `setInterval()` / `requestAnimationFrame()` 을 사용할 수 있다. 하지만 각각을 사용할 때의 특징이 다르고 장단점이 있기 때문에 어떤 차이가 있는지 알아두는 것이 좋다. 기술면접에도 나온적이 있다.
<br>
## CSS 애니메이션
일반적으로, 마우스를 올렸을 때 혹은 메뉴 버튼의 전환과 같은 간단하게 처리하는 애니메이션의 경우 CSS로 처리한다. 예를 들어, 200 크기의 정사각형을 왼쪽 위에서 오른쪽 아래로 350px 움직이게 하는 애니메이션을 구현한다고 하면, `transform` 의 `translate` 를 사용해서 구현할 수 있다. 하지만 이를 JS로 구현하기 위해선 `setInterval` 을 통해서 계속해서 `style.top` 과 `style.left` 속성을 변화시켜줘야 한다. 이렇게 되면 이 속성은 브라우저의 렌더링 과정에서 reflow(layout) 단계를 발생시키기 때문에 애니메이션이 부자연스럽게 끊기는 듯한 느낌을 받게 된다. 이런 점에서 바닐라 JS로 애니메이션을 구현하는 것보다 CSS로 구현하는 것이 좋다고 할 수 있다. 이외에도 다양한 장점들이 있으며 정리하자면 다음과 같다.
* 반응형으로 애니메이션을 구현하기에 유용한데, 미디어 쿼리로 애니메이션을 적용하면 된다.
* 외부 라이브러리를 필요로 하지 않는다.
* CSS 자체가 선언형(declarative)이기 때문에 어떤 요소가 애니메이션을 가져야 한다는 직관적인 표현이 가능하다.
* 메인 쓰레드가 아닌 별도의 컴포지터 쓰레드(Compositor Thread)에서 그려지기 때문에 메인 쓰레드에서 작업하는 JS보다 효율적이다.
<br>
## JS 애니메이션
CSS로 처리하기에는 훨씬 복잡하고 무거운 애니메이션 작업들을 효율적이고, 세밀하게 다루기 위해 사용한다. 바닐라 자바스크립트로 구현할 경우 위에서 살펴본 바와 같이 계속해서 요소의 위치를 재계산하기 때문에 비효율적이며 사용자 눈에 가장 부드러운 60fps가 유지되지 않는다. 이때문에 RAF(RequestAnimationFrame) API가 등장했고 구현방식은 동일하지만 60fps를 보장할 수 있게 되었다. 이외에도 외부 라이브러리인 [Velocity.js](http://velocityjs.org/) 와 [GSAP](https://greensock.com/gsap/) 같은 라이브러리를 통해서 성능 좋은 애니메이션을 구현할 수 있다. 최근에 Web Animations API가 나오기도 했는데 현재(2020년 4월 28일) 기준으로 지원하는 브라우저가 현저히 적기 때문에 아직까진 기존의 방법들이 더 높은 생산성을 가진다고 할 수 있다. 보통 복잡한 애니메이션을 구현하려고 하면 외부 라이브러리를 사용할텐데 이것이 CSS에 비해 가지는 장점은 다음과 같다.
* 요소의 스타일이 변하는 순간마다 제어할 수 있기 때문에 애니메이션의 세밀한 구성이 가능해진다.
* GPU를 통한 하드웨어 가속을 제어할 수 있다. 이는 CSS의 특정 속성으로 인한 가속을 막아주는데, 하드웨어 가속이 모바일에서 성능저하를 발생시킬 수 있기 때문에 이런 면에선 좋다.
* 브라우저 호환성 측면에서 `transition` / `animation` 속성보다 뛰어나다.
<br>
## 참고
* [Naver D2, 최신 브라우저의 내부 살펴보기 3 - 렌더러 프로세스의 내부 동작](https://d2.naver.com/helloworld/5237120)
* [애니메이션 성능을 높이는 방법](http://sculove.github.io/blog/2013/12/05/animation-for-performance/)
* [Julian Shapiro, CSS vs. JS Animation: Which is Faster?](https://davidwalsh.name/css-js-animation)
* [손찬욱님, Web Animation API 프레젠테이션](https://sculove.github.io/slides/webAnimation/#/)
================================================
FILE: Notes/frontend/engine.md
================================================
# 자바스크립트 엔진이 코드를 실행하는 과정
자바스크립트를 실행하기 위해선 자바스크립트 엔진이 필요하고 웹 브라우저는 자바스크립트 엔진을 내장하고 있다. 브라우저마다 엔진의 종류가 다르지만 코드를 실행하는 방식은 비슷하기 때문에 보통 어떻게 실행하는지 알아두는 것이 좋다. (V8, SpiderMonkey, Javascript core 등의 구현이 각각 다르다)
<img src="../../images/javascript/engine-overview.png">
[이미지 출처](https://mathiasbynens.be/notes/shapes-ics)
* 소스코드를 만나면 파싱하여 **AST(Abstract Syntax Tree)** 로 변환한다.
* **인터프리터(Interpreter)** 는 AST를 기반으로 **바이트코드(Bytecode)를 생성** 한다.
* 인터프리터가 바이트코드를 실행할 때, 자주 사용되는 함수 및 타입 정보 등이 있는 **프로파일링 데이터(Profiling data)** 와 같이 **최적화 컴파일러(Optimizing compiler)** 에게 보낸다.
* 최적화 컴파일러는 프로파일링 데이터를 기반으로 **최적화된 코드(Optimized code)를 생성** 한다.
* 하지만, 프로파일링 데이터 중에 **잘못된 부분이 있다면 최적화 해제(Deoptimize)** 를 하고 다시 바이트코드를 실행해서 이전 동작을 반복한다.
<br>
## 참고
* [JavaScript engine fundamentals: Shapes and Inline Caches](https://mathiasbynens.be/notes/shapes-ics)
* [JavaScript 엔진 톺아보기 (1)](https://velog.io/@godori/JavaScript-engine-1)
================================================
FILE: Notes/html/data.md
================================================
# data- 속성
**DOM에 데이터를 저장할 수 있는 사용자 정의 데이터 속성** 으로 `data-` 다음 오는 값이 데이터가 된다. 이 속성은 사용하고자 하는 용도에 적합한 속성이나 요소가 없을 때 사용하며 해당 웹페이지가 **독자적으로 사용하는 값** 이다. 즉, 웹페이지와 독립적인 소프트웨어가 이 속성을 사용해서는 안된다.
예를 들어, 음악 사이트에서 앨범 트랙의 음악을 리스트 형식으로 나타내는데 그걸 시간 순으로 정렬하기 위해서 `data-` 속성으로 음악 시간을 삽입한다고 하자.
```html
<ol>
<li data-length="2m11s">빨간맛</li>
...
</ol>
```
만약 이 음악 사이트와 전혀 상관이 없는 외부에서 음악 시간을 알아내기 위해 사용한다면 목적에 부합하지 않는 것이다. 따라서, `data-` 속성은 해당 사이트만의 자체 스크립트를 위한 속성이라고 할 수 있다.
<br>
## 참고
* [W3, Custom Data Attribute](https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#custom-data-attribute)
* [프론트엔드 인터뷰 핸드북, `data-` 속성은 무엇에 좋은가요?](https://www.frontendinterviewhandbook.com/kr/html-questions/#data-%EC%86%8D%EC%84%B1%EC%9D%80-%EB%AC%B4%EC%97%87%EC%97%90-%EC%A2%8B%EC%9D%80%EA%B0%80%EC%9A%94)
================================================
FILE: Notes/html/doctype.md
================================================
# DOCTYPE
Document Type의 약자로, **HTML이 어떤 버전으로 작성되었는지 미리 선언하여 웹브라우저가 내용을 올바로 표시할 수 있도록 해주는 것** 이다. `<!DOCTYPE>` 으로 선언하는데 이걸 해주지 않으면 **호환 모드(quirks mode)** 로 동작한다. 호환 모드의 경우 각 브라우저마다 문서를 나타내는 방식이 다르기 때문에 크로스 브라우징 이슈가 훨씬 심해지게 된다.
## DTD(Document Type Definition)
DTD(Document Type Definition)란 문서 형식을 정의해놓은 것으로 DOCTYPE을 명시할 때 사용한다. 즉, HTML 문서가 어떤 문서 형식을 따르는지 DOCTYPE에서 DTD를 지정하는 것이다.
예시로 아래와 같은 것들이 있고 [W3C Recommended list of Doctype declarations](https://www.w3.org/QA/2002/04/valid-dtd-list.html) 에서 더욱 자세하게 확인 가능하다.
* XHTML 1.1
* XHTML 1.0
* Strict DTD
* Transitional DTD
* Frameset DTD
* HTML 4.01
* Strict DTD
* Transitional DTD
* Frameset DTD
* HTML 5
현 시점에선, HTML 5의 DTD로 DOCTYPE을 명시하는 것이 제일 바람직하다.
```html
<!DOCTYPE html>
```
<br>
## 참고
* [What is DOCTYPE?](https://stackoverflow.com/questions/414891/what-is-doctype)
* [비표준 모드 quirks mode, 표준 모드 standards mode 차이와 DOCTYPE](https://aboooks.tistory.com/169)
* [DOCTYPE(문서형 정의) 선언](https://webdir.tistory.com/40)
* [What is difference between XHTML and HTML?](https://stackoverflow.com/questions/4153403/what-is-difference-between-xhtml-and-html)
================================================
FILE: Notes/html/script-tag-type.md
================================================
# script, script async, script defer
* `<script>` : HTML 파싱이 중단되고 즉시 스크립트가 로드되며 로드된 스크립트가 실행되고 파싱이 재개된다.
* `<script async>` : HTML 파싱과 병렬적으로 로드가 되는데, 스크립트를 실행할 때는 파싱이 중단된다. 구글 애널리틱스와 같이 다른 스크립트가 의존하지 않는 독자적인 스크립트를 로드할 때 적합하다.
* `<script defer>` : HTML 파싱과 병렬적으로 로드가 되는데, 파싱이 끝나고 스크립트를 로드한다. 보통 `<body>` 태그 직전에 `<script>` 를 삽입하는 것과 동작은 같지만 브라우저 호환성에서 다를 수 있으므로 그냥 `<body>` 태그 직전에 삽입하는 것이 좋다.
**주의할 점은 async와 defer의 경우 `src` 속성이 없으면 적용되지 않는다.**
아래 그림을 통해 보다 확실하게 확인할 수 있다.
<img src="../../images/html/script.png">
<br>
## 참고
* [Script Tag - async & defer](https://stackoverflow.com/questions/10808109/script-tag-async-defer)
* [프론트엔드 인터뷰 핸드북, `<script>`, `<script async>`, `<script defer>` 사이의 차이점을 설명하세요](https://github.com/yangshun/front-end-interview-handbook/blob/master/Translations/Korean/questions/html-questions.md#script-script-async-script-defer-사이의-차이점을-설명하세요)
================================================
FILE: Notes/html/semantic.md
================================================
# 시맨틱 마크업
시맨틱(Semantic)이란 "의미론적인" 의 뜻을 가지며 마크업(Markup)이란 HTML 태그로 문서를 작성하는 것을 말한다. 따라서, 시맨틱 마크업이란 **의미를 잘 전달하도록 문서를 작성하는 것을 말한다.**
## 작성방법
시맨틱 마크업을 하기 위해선 각 태그를 그 용도에 맞게 사용하여야 한다. 즉, 다음과 같은 것들을 말한다.
* 헤더/푸터에 `<header>` 와 `<footer>` 사용
* 메인 컨텐츠에 `<main>` 과 `<section>` 사용
* 독립적인 컨텐츠에 `<article>` 사용
* 최상위 제목으로 `<h1>` 사용
* 순서가 없는 목록으로 `<ul>` 과 `<li>` 사용
* 내비게이션에 `<nav>` 사용
이런 식으로 태그가 가지고 있는 의미에 맞게 사용하는 것인데, 이런 점 이외에도 CSS 스타일을 명시하는 태그를 사용하지 않는 것 또한 시맨틱 마크업의 한 종류이다. **즉, 태그가 가지는 의미 자체가 스타일이라면 이는 마크업 자체가 스타일을 갖는 것이기 때문에 시맨틱 마크업에 적합하지 않다.**
예를 들어, 동일한 효과를 부여하는 `<strong>` 과 `<b>` 태그가 있다. 둘은 동일하게 글자색을 진하게 하지만 `<b>` 태그의 경우는 그 자체가 "bold" 의 약어이기 때문에 태그 자체가 스타일을 가진다고 할 수 있다. 하지만 `<strong>` 의 경우는 "그 안의 내용이 다른 내용보다 더 강조되어야 한다" 라는 의미를 가지기 때문에 시맨틱 마크업에 더 적합하다.
<br>
## 특징
* 검색엔진이 시맨틱 태그를 중요한 키워드로 간주하기 때문에 **검색엔진 최적화(SEO)에 유리하다.**
* **웹 접근성** 측면에서, 시각장애가 있는 사용자로 하여금 그 의미를 훨씬 잘 파악할 수 있다.
* 단순한 `div` , `span` 으로 둘러싸인 요소들보다 코드를 볼 때 **가독성이 더 좋다.**
실무에서 시맨틱 마크업이 완벽하게 쓰이는 것은 이상적이긴 하지만, 이러한 특징들을 고려하고 웹사이트를 구성하는 것이 많은 측면에서 바람직하다.
<br>
## 참고
* [Stackoverflow, What are the benefits of using semantic HTML?](https://stackoverflow.com/questions/1729447/what-are-the-benefits-of-using-semantic-html)
* [Stackoverflow, What's the difference between and , and ?](https://stackoverflow.com/questions/271743/whats-the-difference-between-b-and-strong-i-and-em)
* [MDN, Semantics](https://developer.mozilla.org/ko/docs/Glossary/Semantics)
================================================
FILE: Notes/html/standard-quirks.md
================================================
# 표준 모드와 호환 모드
과거의 웹 페이지는 넷스케이프와 익스플로러 버전이 따로 존재했고 웹 표준이 없었다. 그러나 W3C가 웹 표준을 만들면서 브라우저가 웹사이트를 제대로 표현할 수 없게 되자 렌더링을 할 때 표준 모드(Standards mode)와 호환 모드(Quirks mode)로 렌더링을 할 수 있게 옵션을 제공하였다.
**브라우저는 HTML 문서가 DOCTYPE을 가지고 있지 않으면 호환 모드로 렌더링을 하고, 가지고 있다면 주어진 DOCTYPE에 맞게 표준 모드로 렌더링을 한다**. 호환 모드로 렌더링을 하게 되면 오래된 웹페이지들을 최신 버전의 브라우저에서도 깨지지 않게 하기 때문에 각 브라우저마다 다르게 보일 수 있다. 예를 들어, IE의 경우 호환 모드에서 박스 모델(Box model)을 잘못 해석하지만, 나머지 브라우저들은 그렇지 않다.
결론적으로, 정말 특별한 경우가 아니라면 DOCTYPE을 명시하여 브라우저가 표준 모드로 렌더링 하게 하자. 현재 시점에서 HTML5에서 권장하는 방식인 `<!DOCTYPE html>` 을 사용하는 것이 가장 바람직하다.
<br>
## 참고
* [MDN, 호환 모드와 표준 모드](https://developer.mozilla.org/ko/docs/Web/HTML/Quirks_Mode_and_Standards_Mode)
* [쿼크모드(Quirks mode)와 표준모드(Standard mode)](http://chongmoa.com/441)
* [What is quirks mode?](https://stackoverflow.com/questions/1695787/what-is-quirks-mode)
================================================
FILE: Notes/html/web-storage-api.md
================================================
# local storage vs session storage vs cookie
모두 클라이언트 상에서 key/value 쌍을 저장할 수 있는 메커니즘으로 **value는 반드시 문자열** 이어야 한다. 또한 모두 [동일 출처 정책(SOP)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/security/sop.md) 을 따르기 때문에 다른 도메인에서 접근할 수 없다.
| | cookie | local storage | session storage |
| ------------- | ---------------- | --------------------- | ----------------------- |
| 생성자 | 클라이언트/서버 | 클라이언트 | 클라이언트 |
| 지속시간 | 설정 여부에 따름 | 명시적으로 지울때까지 | 탭 / 윈도우 닫을 때까지 |
| 용량 | 5KB | 5MB / 10MB | 5MB |
| 서버와의 통신 | O | X | X |
| 취약점 | XSS / CSRF 공격 | XSS 공격 | XSS 공격 |
<br>
## 참고
* [What is the difference between localStorage, sessionStorage, session and cookies?](https://stackoverflow.com/questions/19867599/what-is-the-difference-between-localstorage-sessionstorage-session-and-cookies)
* [프론트엔드 인터뷰 핸드북, `cookie`, `sessionStorage`, `localStorage` 사이의 차이점을 설명하세요](https://github.com/yangshun/front-end-interview-handbook/blob/master/Translations/Korean/questions/html-questions.md#cookie-sessionstorage-localstorage-사이의-차이점을-설명하세요)
* [Local Storage vs Cookies](https://stackoverflow.com/questions/3220660/local-storage-vs-cookies)
================================================
FILE: Notes/javascript/ajax.md
================================================
# AJAX
## AJAX란 무엇인가?
Asynchronous Javascript And XML의 약자로, 비동기적으로 JS를 사용해서 데이터를 받아와 동적으로 DOM을 갱신 및 조작하는 웹 개발 기법을 의미한다. 여기서 XML이 있는 이유는 예전엔 데이터 포맷으로 XML을 많이 사용했기 때문이다.
<br>
## 어떻게 동작하는가?
<img src="../../images/javascript/ajax.png">
사용자가 AJAX가 적용된 UI와 상호작용하면, 서버에 AJAX 요청을 보내게 된다. 서버는 DB에서 데이터를 가져와서 JS 파일에 정의되어 있는 대로 HTML/CSS와 데이터를 융합하여 만든 DOM 객체를 UI에 업데이트 시킨다. 비동기로 이루어지며, 기존의 페이지를 전부 로딩하는 방식이 아닌 **일부만 업데이트 하는 방식이다.**
<br>
## 어떻게 사용하는가?
### XMLHttpRequest
일반적으로 `XMLHttpRequest` 객체를 사용하여 인스턴스를 만들어 인스턴스의 `open()` , `send()` 등의 메소드를 이용한다.
```javascript
var ourRequest = new XMLHttpRequest();
ourRequest.open(
"GET",
"https://learnwebcode.github.io/json-example/animals-1.json"
);
ourRequest.onload = () => {
var ourData = JSON.parse(ourRequest.responseText);
console.log(ourData[0]);
};
ourRequest.send();
```
`open()` 으로 요청할 메소드와 URL을 설정한 뒤, 모두 로드되었을 경우의 콜백함수를 초기화한다.
### Fetch API
새로나온 `fetch` 를 사용해서 요청을 할 수도 있는데 IE를 지원하지 않는다는 점을 제외하고는 `XMLHttpReqeust` 보다 훨씬 직관적이다. ES6(ES2015) 에서 표준이 되었고, Promise를 리턴한다.
```javascript
fetch("https://learnwebcode.github.io/json-example/animals-1.json")
.then(res => res.json())
.then(resJson => console.log(resJson));
```
응답객체는 `json()` , `blob()` 과 같은 내장 메서드로 body를 추출해내고 이는 다시 Promise를 리턴한다.
CodeSandBox를 통해서 둘을 비교해보자.
[](https://codesandbox.io/s/fetch-api-dzqoj?fontsize=14&hidenavigation=1&theme=dark)
<br>
## 장단점
### 장점
* 페이지를 전환하지 않고 빠르게 화면 일부분 업데이트 할 수 있다.
* 수신하는 데이터 양을 줄일 수 있고 클라이언트에게 처리를 맡길 수 있다.
* 서버 처리를 기다리지 않고 비동기 요청이 가능하다.
### 단점
* 지원하지 않는 브라우저가 있다.
* 페이지 전환없이 서버와 통신을 하기 때문에 보안상에 문제가 있을 수 있다.
* 무분별하게 사용하면 역으로 서버의 부하가 늘어날 수 있다.
* [동일 출처 정책](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/security/sop.md) 문제가 발생할 수 있다.
<br>
## 참고
* [JSON and AJAX Tutorial: With Real Examples(유튜브)](https://www.youtube.com/watch?v=rJesac0_Ftw)
* [How is Ajax independent from a server?](https://www.quora.com/How-is-Ajax-independent-from-a-server)
* [MDN, Ajax 시작하기](https://developer.mozilla.org/ko/docs/Web/Guide/AJAX/Getting_Started)
* [위키백과, Ajax](https://ko.wikipedia.org/wiki/Ajax)
* [Stackoverflow, Difference between fetch, ajax, and xhr](https://stackoverflow.com/questions/52261136/difference-between-fetch-ajax-and-xhr)
* [AJAX, XMLHttpRequest와 Fetch 살펴보기](https://junhobaik.github.io/ajax-xhr-fetch/)
================================================
FILE: Notes/javascript/closure.md
================================================
# 클로저(Closure)
클로저란 **함수가 속한 렉시컬 스코프를 기억하여 함수가 렉시컬 스코프 밖에서 실행될 때도 그 스코프에 접근할 수 있게 하는 기능** 을 말한다.
```javascript
function outer() {
var a = 2;
function inner() {
console.log(a);
}
return inner;
}
var func = outer();
func(); // 2
```
여기서 GC(Garbage Collector)가 `outer()` 의 참조를 없앨 것 같지만 내부함수인 `inner()` 가 해당 스코프의 변수인 a를 참조하고 있기 때문에 없애지 않는다. 따라서 스코프 외부에서 `inner()` 가 실행되도 해당 스코프를 기억하기 때문에 2를 출력하게 된다. 즉, 여기서 클로저는 `inner()` 가 되며 `func` 에 담겨 밖에서도 실행되고 렉시컬 스코프를 기억한다.
<br>
## 예제
클로저를 사용하는 대표적인 예제는 역시 "반복문 클로저"이다.
```javascript
function func() {
for (var i=1; i<5; i++) {
setTimeout(function() { console.log(i); }, i*500);
}
}
func(); // 5 5 5 5
```
코드의 의도한 바는 1부터 4까지 간격을 두고 출력하는 것이었지만 5가 4번 출력된다. 왜 이렇게 되는 것일까?
`setTimeout()` 을 반복문 안에서 돌리면 콜백함수가 계속해서 task queue에 쌓이게 되고 반복문이 끝나고 나서 call stack으로 돌아와서 실행된다. 콜백함수는 클로저이기 때문에 상위 스코프에게 `i` 의 값을 물어보고 상위 스코프인 `func` 의 스코프에선 `i` 가 5까지 증가했기 때문에 5가 4번 출력된다.
<br>
## 해결방법
위 문제를 해결하기 위해선 2가지 방법이 있다.
* **새로운 함수 스코프로 해결하기**
```javascript
function func() {
for (var i=1; i<5; i++) {
(function (j) {
setTimeout(function() { console.log(j); }, j*500);
})(i);
}
}
func(); // 1 2 3 4
```
`setTimeout()` 을 IIFE(Immediately Invoked Function Expression, 즉시실행함수 표현식)로 감싸게 되면, 새로운 스코프를 형성하고 나중에 콜백함수가 `j` 를 참조할 때 그 시점의 `i` 값을 갖기 때문에 원하는 결과를 얻을 수 있게 된다.
* **블록 스코프로 해결하기**
```javascript
function func() {
for (let i=1; i<5; i++) {
setTimeout(function() { console.log(i); }, i*500);
}
}
func(); // 1 2 3 4
```
함수 스코프가 아닌 블록 스코프를 갖는 `let` 을 사용하면 `for` 문 내의 새로운 스코프를 갖기 때문에 매 반복마다 새로운 `i` 가 선언되고 반복이 끝난 이후의 값으로 초기화가 된다. 따라서, `setTimeout()` 의 클로저인 콜백함수가 `i` 를 참조하기 위해 상위 스코프를 검색할 때 블록 스코프에서 매 반복마다 선언 및 초기화 된 `i` 를 참조하는 것이다.
실제 클로저를 사용하는 예를 알고 싶다면 [Stackoverflow의 답변](https://stackoverflow.com/a/39045098/11789111) 을 참고하자.
<br>
## 참고
* [TOAST, 자바스크립트의 스코프와 클로저](https://meetup.toast.com/posts/86)
* 카일 심슨, 『You don't know JS - 타입과 문법, 스코프와 클로저』, 최병현, 한빛미디어(2017)
================================================
FILE: Notes/javascript/es11.md
================================================
# ES11 (ES2020) 의 특징들
### `String.prototype.matchAll`
기존의 `String.prototype.match` 의 기능은 일치하는 결과값 외에는 아무런 정보도 주지 않는다. 따라서 이 기능에서 다양한 정보들을 주도록 확장된 함수이다.
* `String.prototype.match`
```javascript
const text = "From 2019.01.29 to 2019.01.30";
const regexp = /(?<year>\d{4}).(?<month>\d{2}).(?<day>\d{2})/gu;
const results = text.match(regexp);
console.log(results);
// [ '2019.01.29', '2019.01.30' ]
```
* `String.prototype.matchAll`
```javascript
const text = "From 2019.01.29 to 2019.01.30";
const regexp = /(?<year>\d{4}).(?<month>\d{2}).(?<day>\d{2})/gu;
const results = Array.from(text.matchAll(regexp));
console.log(results);
// [
// [
// '2019.01.29',
// '2019',
// '01',
// '29',
// index: 5,
// input: 'From 2019.01.29 to 2019.01.30',
// groups: [Object: null prototype] { year: '2019', month: '01', day: '29' }
// ],
// [
// '2019.01.30',
// '2019',
// '01',
// '30',
// index: 19,
// input: 'From 2019.01.29 to 2019.01.30',
// groups: [Object: null prototype] { year: '2019', month: '01', day: '30' }
// ]
// ]
```
### Dynamic import
동적으로 모듈을 불러오는 함수로 프라미스를 반환하며 완료(fulfilled)되면 요청한 모듈의 네임스페이스에 해당하는 객체를 반환한다.
```javascript
(async () => {
const module = await import('./test-module.js');
module.func();
});
```
### BigInt
7번째 원시타입으로, `MAX_SAFE_INTEGER` 를 넘어가는 값을 사용할 수 있으며 `n` 이 접미사로 붙는다.
```javascript
const bigint = BigInt(Number.MAX_SAFE_INTEGER + 1);
console.log(bigint, typeof bigint);
// 9007199254740992n bigint
```
### `Promise.allSettled`
기존의 `Promise.all` 은 거부(rejected)되는 프라미스가 하나라도 있을 경우 해당 결과값만 리턴했지만 이 함수를 사용하면 거부/완료 모두에 대한 결과값을 배열로 반환한다.
```javascript
const p1 = Promise.resolve("완료1");
const p2 = Promise.reject("거부");
const p3 = Promise.resolve("완료2");
Promise.all([p1, p2, p3]).then(console.log).catch(console.log);
Promise.allSettled([p1, p2, p3]).then(console.log);
/*
[
{ status: 'fulfilled', value: '완료1' },
{ status: 'rejected', reason: '거부' },
{ status: 'fulfilled', value: '완료2' }
]
거부
*/
```
### `globalThis`
호스트 환경마다 `this` 객체의 값이 달랐는데 이 부분을 알아서 통합시켜주었다. Node.js에선 `global` 객체로, 브라우저에선 `window` 객체로 나온다.
### Optional chaining
객체의 깊이가 깊어짐에 따라서 프로퍼티의 존재여부를 먼저 판단해야 하는데 그 때마다 `&&` 연산자를 사용해서 가독성에 좋지 못했다. 이를 `?.` 로 해결하였다.
```javascript
const book = {
entities: {
hashtags: ['test']
}
};
const hashtags = book.entities && book.entities.hashtags;
// Optional chaining
const hashtags = book.entities?.hashtags;
```
### Nullish coalescing operator (null 병합 연산자)
보통 기본 값을 할당하기 위해서 `||` 를 사용하여 좌변이 `null` 이나 `undefined` 이면 다른 값을 사용하는 방식을 많이 사용하였다. 이를 `??` 로 해결하였다.
```javascript
const values = {
nullValue: null
};
const value = values.nullValue ?? "default value";
```
이외에도 for-in 메커니즘 확정, `import.meta` 등이 있으니 필요하다면 공부하도록 하자.
<br>
## 참고
* [TOAST UI, ECMAScript 2020의 새로운 점](https://ui.toast.com/weekly-pick/ko_20200409/)
* [DEV, ES2020 Features in simple examples](https://dev.to/carlillo/es2020-features-in-simple-examples-1513)
================================================
FILE: Notes/javascript/es6.md
================================================
# ES6 (ES2015) 의 특징들
모든 특징들을 나열하진 않고 중요하다고 생각하는 특징들만 나열한다.
<br>
### 화살표 함수(Arrow Function)
`=>` 로 사용할 수 있으며 함수와 달리 `this` 가 함수 스코프에 바인딩 되지 않고 렉시컬 스코프를 가진다. 즉, 자신을 감싸는 코드와 동일한 `this` 를 공유한다. 또한 표현식과 문에서도 사용할 수 있다.
```javascript
// 표현식(expression)
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
var pairs = evens.map(v => ({even: v, odd: v + 1}));
// 문(Statement)
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
// 렉시컬 this
var bob = {
_name: "Bob",
_friends: [],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f));
}
}
```
### 클래스(Classes)
프로토타입 기반의 객체지향 패턴을 쉽게 만든 장치로, 상속과 생성자 및 인스턴스와 정적 메서드 등을 지원한다.
```javascript
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
get boneCount() {
return this.bones.length;
}
set matrixType(matrixType) {
this.idMatrix = SkinnedMesh[matrixType]();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
```
### 향상된 객체 리터럴
객체 리터럴로 객체를 만들 때 프로퍼티 지정을 좀 더 유연하게 할 수 있도록 기능이 확장되었다.
```javascript
var obj = {
// 프로토타입 객체 지정
__proto__: theProtoObj,
// 프로퍼티이름과 값이 동일할 경우 줄일 수 있음
handler,
// 메서드
toString() {
// super 호출
return "d " + super.toString();
},
// 계산된 프로퍼티
[ 'prop_' + (() => 42)() ]: 42
};
```
### 템플릿 문자열(Template String)
복잡한 문자열을 쉽게 만들어주는 장치로 문자열 안에 문자열 및 변수를 넣을 수 있고 여러 줄의 문자열이 가능하다.
```javascript
// 문자열 안에 문자열 사용하기
`In JavaScript '\n' is a line-feed.`
// 여러 줄 문자열
`In JavaScript this is
not legal.`
// 문자열 보간(interpolation)
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
```
### 비구조화(Destructuring)
배열과 객체의 패턴 매칭을 통해서 바인딩을 하는 기법이다.
```javascript
// 배열 매칭
var [a, , b] = [1,2,3];
// 객체 매칭
var { op: a, lhs: { op: b }, rhs: c }
= getASTNode()
// 객체 매칭을 단축해서 사용
// op, lhs, rhs가 스코프 내에서 바인딩됨
var {op, lhs, rhs} = getASTNode()
// 매개변수 위치에도 사용 가능
function g({name: x}) {
console.log(x);
}
g({name: 5})
// Fail-soft 비구조화 (Fail-soft는 고장이 나도 작동하도록 짠 프로그램을 말한다)
var [a] = [];
a === undefined;
// 기본 값이 있는 Fail-soft 비구조화
var [a = 1] = [];
a === 1;
```
### 기본 값 + Rest + Spread
기본 값은 주어지는 값이 없을 때 초기화시키는 값이고 rest 문법은 명시한 변수 외에 나머지를 배열로 가져오는 것이다. Spread 문법은 배열을 반대로 펼치는 역할이다.
```javascript
function f(x, y=12) {
// y가 없거나 undefined이면 12이다.
return x + y;
}
f(3) == 15
```
```javascript
function f(x, ...y) {
// y는 배열이다.
return x * y.length;
}
f(3, "hello", true) == 6
```
```javascript
function f(x, y, z) {
return x + y + z;
}
// 각 배열의 원소를 인자로 넘긴다.
f(...[1,2,3]) == 6
```
### Let + Const
블록 스코프를 갖고 재선언이 불가능하며 선언 이전에 사용할 수 없다.
```javascript
function f() {
{
let x;
{
// 블록 스코프를 갖기 때문에 허용!
const x = "sneaky";
// const는 재할당 불가, 에러!
x = "foo";
}
// 해당 블록에 이미 선언됨, 재선언 불가이므로 에러!
let x = "inner";
}
}
```
### 반복자(Iterator) + For...Of
반복자는 자신만의 반복을 정의하는 규약이고 이는 `for...of` 를 통해 순회할 수 있다. `[Symbol.iterator]` 라는 이름의 메서드를 정의해야하며 그 메서드는 반드시 `next()` 메서드를 가진 객체를 반환해야 한다.
```javascript
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1;
return {
next() {
[pre, cur] = [cur, pre + cur];
return { done: false, value: cur }
}
}
}
}
for (var n of fibonacci) {
if (n > 1000)
break;
console.log(n);
}
```
### 제너레이터(Generator)
반복자를 쉽게 생성해주는 것으로 `function*` 과 `yield` 를 사용한다. 반복자의 하위 타입으로, `next` 와 `throw` 를 포함한다. 또한 ES7의 `await` 과 같이 사용할 수 있다.
```javascript
var fibonacci = {
[Symbol.iterator]: function*() {
var pre = 0, cur = 1;
for (;;) {
var temp = pre;
pre = cur;
cur += temp;
yield cur;
}
}
}
for (var n of fibonacci) {
if (n > 1000)
break;
console.log(n);
}
```
### 모듈(Module)
* **import 로 모듈 불러오기**
```javascript
// lib/math.js
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
```
```javascript
// app.js
import * as math from "lib/math";
alert("2π = " + math.sum(math.pi, math.pi));
```
```javascript
// otherApp.js
import {sum, pi} from "lib/math";
alert("2π = " + sum(pi, pi));
```
* **export 로 모듈 내보내기**
```javascript
// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
return Math.log(x);
}
```
### Map + Set + WeakMap + WeakSet
자주 쓰이는 자료구조로, Weak이 붙은 것은 가비지 컬렉션을 허용하며 `size` 프로퍼티를 가지지 않는다.
```javascript
// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;
// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;
// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size === undefined
// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });
// WeakSet에 들어간 객체가 어떠한 참조도 가지지 않으므로 가비지 컬렉션이 된다.
```
### 심볼(Symbol)
새로 추가된 **원시타입** 으로 유일한 값을 가지며 객체의 접근제어를 가능하게 한다. `description` 매개변수를 이용해 디버깅이 가능하며 `Object.getOwnPropertySymbols` 를 통해 객체의 심볼 프로퍼티들을 볼 수 있다.
```javascript
var MyClass = (function() {
// IIFE 안의 심볼, 모듈화 된 것.
// 즉, 심볼로 private 데이터 만듦
var key = Symbol("key");
function MyClass(privateData) {
this[key] = privateData;
}
MyClass.prototype = {
doStuff: function() {
... this[key] ...
}
};
return MyClass;
})();
var c = new MyClass("hello");
// "key"와 Symbol("key")는 다르다.
c["key"] === undefined
```
### Number + String + Array + Object 에 추가된 것들
```javascript
Number.isInteger(Infinity) // false
Number.isNaN("NaN") // false
"abcde".includes("cd") // true
"abc".repeat(3) // "abcabcabc"
Array.from(document.querySelectorAll('*')) // 유사배열객체를 배열로 변환
Array.of(1, 2, 3) // [1,2,3]
[0, 0, 0].fill(7, 1) // [0,7,7]
[1, 2, 3].find(x => x == 3) // 3
[1, 2, 3].findIndex(x => x == 2) // 1
[1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]
["a", "b", "c"].entries() // 반복자 [0, "a"], [1,"b"], [2,"c"]
["a", "b", "c"].keys() // 반복자 0, 1, 2
["a", "b", "c"].values() // 반복자 "a", "b", "c"
Object.assign(Point, { origin: new Point(0,0) }) // 얕은 복사
```
### 프라미스(Promise)
비동기 작업이 맞이할 미래의 완료/실패와 결과 값을 나타내는 객체이다.
```javascript
function timeout(duration = 0) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration);
})
}
var p = timeout(1000).then(() => {
return timeout(2000);
}).then(() => {
throw new Error("hmm");
}).catch(err => {
return Promise.all([timeout(100), timeout(200)]);
})
```
<br>
## 참고
* [lukehoban, es6features github repo](https://github.com/lukehoban/es6features)
* 각 특징들의 MDN 관련 문서들
================================================
FILE: Notes/javascript/es7-es8.md
================================================
# ES7 (ES2016) ~ ES8 (ES2017) 의 특징들
## ES7 (ES2016)
### `Array.prototype.includes`
* `arr.includes(찾는원소, [, 인덱스시작점])`
특정 원소를 포함했는지의 여부를 반환하는 메서드이다. 첫번째 인자로는 타겟 원소를, 두번째 인자로는 어느 인덱스부터 검사할 것인지를 줄 수 있다.
```javascript
[1, 2, 3].includes(2); // true
[1, 2, NaN].includes(NaN); // true
[1, 2, 3].includes(2,2); // 인덱스 2부터 시작하는데 3밖에 없으므로 false
[1, 2, 3].includes(3,4); // 인덱스 범위 넘어가면 자동 false
```
### 멱법(Exponentiation)
* `피연산자 ** 피연산자`
숫자를 제곱하는 방법을 말하며 이를 짧게 나타냈다.
```javascript
2 ** 2; // 4
Math.pow(2, 2); // 4
```
<br>
## ES8 (ES2017)
### `async - await`
* `async function 함수이름 (매개변수들...) {}`
비동기 함수를 보다 직관적으로 사용하는 문법으로 함수 앞에 `async` 키워드를 달면 내부에서 `await` 을 사용하여 Promise 객체의 완료를 기다릴 수 있다.
```javascript
const promiseFunc1 = function() {
return new Promise((res, rej) => {
setTimeout(() => {
res("첫번째 Promise 끝");
}, 1000);
});
};
const promiseFunc2 = function() {
return new Promise((res, rej) => {
setTimeout(() => {
res("두번째 Promise 끝");
}, 1000);
});
};
const handleAsyncFunc = async function() {
const promiseMessage1 = await promiseFunc1();
const promiseMessage2 = await promiseFunc2();
console.log(promiseMessage1, promiseMessage2);
};
handleAsyncFunc(); // 첫번째 Promise 끝 두번째 Promise 끝
```
### `Object.entries()`
* `Object.entries(객체)`
key/value 쌍을 배열로 가져오는 메서드이다.
```javascript
const obj = { one: 1, two: 2, three: 3 };
console.log(Object.entries(obj));
// [['one', 1], ['two', 2], ['three', 3]]
```
### `Object.values()`
* `Object.values(객체)`
value 만 배열로 가져오는 메서드이다.
```javascript
const obj = { one: 1, two: 2, three: 3 };
console.log(Object.values(obj));
// [1, 2, 3]
```
### `Object.getOwnPropertyDescriptors()`
* `Object.getOwnPropertyDescriptors(객체)`
모든 프로퍼티의 디스크립터인 `value`, `writable`, `enumerable`, `configurable`, `set`, `get` 을 가져오는 메서드이다.
```javascript
const obj = { one: 1, two: 2, three: 3 };
console.log(Object.getOwnPropertyDescriptors(obj));
```
```
{
one: { value: 1, writable: true, enumerable: true, configurable: true },
two: { value: 2, writable: true, enumerable: true, configurable: true },
three: { value: 3, writable: true, enumerable: true, configurable: true }
}
```
### Trailing 콤마
함수 선언문, 함수 호출에서 마지막에도 콤마를 쓸 수 있다.
```javascript
function test(a,b,){
console.log(a,b,);
}
```
<br>
## 참고
* [ECMAScript-new-feature-list, ES2016](https://github.com/daumann/ECMAScript-new-features-list/blob/master/ES2016.MD)
* [ECMAScript-new-feature-list, ES2017](https://github.com/daumann/ECMAScript-new-features-list/blob/master/ES2017.MD)
================================================
FILE: Notes/javascript/es9-es10.md
================================================
# ES9 (ES2018) ~ ES10 (ES2019) 의 특징들
## ES9 (ES2018)
### async 반복자
기존 반복자(Iterator)의 경우 `next()` 메서드는 `value` 와 `done` 을 가진 객체를 리턴했지만 각각이 Promise로 감싸진 Promise 객체를 리턴할 수도 있게 되었다.
```javascript
const asyncIterator = function() {
let num = 3;
return {
next() {
if (num) {
return Promise.resolve({
value: num--,
done: false,
});
} else {
return Promise.resolve({
done: true
});
}
}
}
}
const iterator = asyncIterator();
(async function() {
await iterator.next().then(console.log); // { value: 3, done: false }
await iterator.next().then(console.log); // { value: 2, done: false }
await iterator.next().then(console.log); // { value: 1, done: false }
await iterator.next().then(console.log); // { done: true }
})();
```
### Object rest/spread 문법
배열에서 사용되던 rest/spread 문법이 객체에서도 사용가능하게 되었다.
```javascript
const obj = { one: 1, two: 2, three: 3 };
const { one, ...rest } = obj;
const newObj = { ...rest, four: 4 };
console.log(rest, newObj); // { two: 2, three: 3 } { two: 2, three: 3, four: 4 }
```
### `Promise.prototype.finally`
Promise 객체를 `then` 이나 `catch` 로 처리한 후에 try-catch 문처럼 `finally` 를 쓸 수 있게 되었다.
```javascript
const timeout = () => {
return new Promise((res) => {
setTimeout(() => { res("Promise 끝"); }, 1000);
});
};
timeout()
.then(console.log)
.finally(() => console.log("무조건"));
```
<br>
## ES10 (ES2019)
### `Array.prototype.flat()/flatMap()`
배열안에 배열 혹은 비어있는 원소가 있을 때 하나의 배열로 합쳐주는 메서드가 `flat` 이고 `map` 을 한 다음에 `flat` 하는 메서드가 `flatMap` 이다.
```javascript
const arr = [[1,2,3], 4, , 5];
console.log(arr.flat()); // [ 1, 2, 3, 4, 5 ]
console.log(arr.flatMap(a => {
if (a instanceof Array) {
return a.length;
} else if (Number.isInteger(a)) {
return a*2;
} else {
return undefined;
}
})); // [ 3, 8, 10 ]
```
### `Object.fromEntries()`
`Object.entries` 와는 반대로 key/value 쌍의 배열로부터 객체를 만드는 메서드이다.
```javascript
const arr = [['one', 1], ['two', 2], ['three', 3]];
console.log(Object.fromEntries(arr)); // { one: 1, two: 2, three: 3 }
```
### `String.prototype.trimStart()/trimEnd()`
앞/뒤의 공백을 지우는 메서드로, 기존에 `String.prototype.trimLeft/trimRight` 이 있지만 `String.prototype.padStart/padEnd` 와 일치시키기 위해 나왔다.
```javascript
const target = " target ";
console.log(target.trimStart());
console.log(target.trimEnd());
```
```
target
target
```
### `Symbol.prototype.description`
심볼을 정의할 때 디버깅 목적으로 문자열을 인자로 전달하여 만들기도 하는데 이를 보기 위한 프로퍼티이다.
```javascript
const symbol = Symbol('description');
console.log(symbol.description);
```
### catch의 에러인자 생략 가능
try-catch 문에서 catch의 인자로 에러인자가 오는데 이를 사용하지 않는다면 생략가능하다.
```javascript
try { console.log('try'); } catch {} // try
```
<br>
## 참고
* [ECMAScript-new-feature-list, ES2018](https://github.com/daumann/ECMAScript-new-features-list/blob/master/ES2018.MD)
* [ECMAScript-new-feature-list, ES2019](https://github.com/daumann/ECMAScript-new-features-list/blob/master/ES2019.MD)
* [ZeroCho님, ES2019(ES10)의 변화](https://www.zerocho.com/category/ECMAScript/post/5c909bfe5a8005001ffb3f14)
================================================
FILE: Notes/javascript/event-delegation.md
================================================
# 이벤트 위임
## 이벤트 버블링과 캡쳐링
이벤트 위임을 알기 위해선 선수지식으로 이벤트 버블링과 캡쳐링의 동작방식을 알아야 한다.
**이벤트 버블링** 이란, 하위 엘리먼트에 이벤트가 발생할 때 그 엘리먼트부터 시작해서 상위요소까지 이벤트가 전달되는 방식을 말한다.
**이벤트 캡쳐링** 이란, 하위 엘리먼트에 이벤트 핸들러가 있을 때 상위 엘리먼트부터 이벤트가 발생하기 시작해서 하위 엘리먼트까지 이벤트가 전달되는 방식을 말한다.
아래 예시를 보면 확실히 알 수 있다.
```html
<div>
<ul>
<li>예시</li>
</ul>
</div>
```
```javascript
document.querySelector('li').addEventListener('click', () => console.log('li 클릭'));
document.querySelector('ul').addEventListener('click', () => console.log('ul 클릭'));
document.querySelector('div').addEventListener('click', () => console.log('div 클릭'));
```
이렇게 각 엘리먼트들에 이벤트 핸들러를 달고 `li` 태그를 클릭해보면 콘솔에는 아래와 같이 찍히게 된다.
```
li 클릭
ul 클릭
div 클릭
```
즉, 기본적으로는 동작방식이 "이벤트 버블링" 인 것이다. 이 방식을 "이벤트 캡쳐링" 으로 바꾸기 위해선 `addEventListener()` 의 마지막 인자로 `{ capture: true }` 를 전달해주면 된다. 이렇게 하면, 클릭한 엘리먼트의 상위요소 중 이벤트 캡쳐링이 적용된 엘리먼트부터 콘솔에 찍히고 그 다음부터는 다시 "이벤트 버블링" 방식을 동작한다. `ul` 의 이벤트 핸들러에 캡쳐링을 적용해보자.
```javascript
document.querySelector('ul').addEventListener('click', () => console.log('ul 클릭'), { capture: true });
```
```
ul 클릭
li 클릭
div 클릭
```
`li` 부터는 다시 "이벤트 버블링" 이 동작해서 `div` 에 이벤트가 발생하는 것이다.
<br>
## 이벤트 위임
**이벤트 위임** 이란 하위 엘리먼트들이 여러개 있을 때, 하위 엘리먼트들에 각각 이벤트 핸들러를 달지 않고 상위 엘리먼트에 이벤트 핸들러를 달아 하위 엘리먼트들을 제어하는 방식이다. 이 패턴으로 얻는 이점들은 다음과 같다.
* 동적으로 엘리먼트를 추가할 때마다 핸들러를 고려할 필요가 없다.
* 상위 엘리먼트에 하나의 이벤트 핸들러만 추가하면 되기 때문에 코드가 훨씬 깔끔해진다.
* 메모리에 있게되는 이벤트 핸들러가 적어지기 때문에 퍼포먼스 측면에서 이점이 있다.
예시를 살펴보자.
```html
<ul onclick="alert(event.type + '!')">
<li>첫번째</li>
<li>두번째</li>
<li>세번째</li>
</ul>
```
`li` 에 각각 핸들러를 달지 않고 상위 엘리먼트인 `ul` 에만 달았다는 걸 확인할 수 있다. 무조건 이벤트 위임이 좋은 것은 아니기 때문에 상황에 맞게 잘 사용하도록 하자.
<br>
## 참고
* [이벤트 버블링, 이벤트 캡처 그리고 이벤트 위임까지](https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/)
* [JavaScript Event Delegation is Easier than You Think](https://www.sitepoint.com/javascript-event-delegation-is-easier-than-you-think/)
* [What is DOM Event delegation?](https://stackoverflow.com/questions/1687296/what-is-dom-event-delegation)
================================================
FILE: Notes/javascript/event-loop.md
================================================
# 이벤트 루프 (Event loop)
> [콜 스택(Call stack)과 힙(Heap)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/stack-heap.md) 을 보고 오자.
자바스크립트는 **단일 스레드(Single-threaded) 기반 언어** 로, 자바스크립트 엔진이 단일 콜 스택을 갖는다. 이 말은 요청이 동기적으로 처리된다는 것을 의미한다. 그렇다면 비동기 요청은 어떻게 처리될 수 있을까? 그것은 바로 자바스크립트를 실행하는 환경인 브라우저나 Node.js가 담당한다. **여기서 자바스크립트 엔진과 그 실행 환경을 상호 연동시켜주는 장치가 바로 이벤트 루프이다.** 따라서, 이벤트 루프는 자바스크립트 엔진에 있지 않고 그 환경에 속한다.
<br>
## 태스크 큐(Task queue)와 마이크로태스크 큐(Microtask queue)
자바스크립트의 실행 환경은 2가지 큐를 가지고 있으며 **각각 스크립트 실행, 이벤트 핸들러, 콜백함수 등의 태스크(Task) 담기는 공간이다.** 태스크가 콜백함수라면 그 종류에 따라 다른 큐에 담기며 대표적인 예로는 다음과 같은 것들이 있다.
* **태스크 큐**
* `setTimeout()` , `setInterval()` , UI 렌더링, `requestAnimationFrame()`
* **마이크로태스크 큐**
* Promise, MutationObserver
이벤트 루프는 2개의 큐를 감시하고 있다가 콜 스택이 비게 되면, 콜백함수를 꺼내와서 실행한다. 이 때 **마이크로태스크 큐의 콜백함수가 우선순위를 가지기 때문에** 마이크로태스크 큐의 콜백함수를 전부 실행하고 나서 태스크 큐의 콜백함수들을 실행한다. (단, UI 렌더링이 태스크 큐에 속하기 때문에 마이크로태스크 큐의 태스크가 많으면 렌더링이 지연될 수 있다.)
<br>
## 예시를 통한 동작방식의 이해
```javascript
console.log('콜 스택!');
setTimeout(() => console.log('태스크 큐!'), 0);
Promise.resolve().then(() => console.log('마이크로태스크 큐!'));
```
결과는 다음과 같다.
```
콜 스택!
마이크로태스크 큐!
태스크 큐!
```
처음 스크립트가 로드될 때 **"스크립트 실행"** 이라는 태스크가 먼저 태스크 큐에 들어간다. 그리고 나서 이벤트 루프가 태스크 큐에서 해당 태스크를 가져와 콜 스택을 실행하는 것이다. 즉, 콜 스택에는 이미 GEC(Global Execution Context)가 생성되어 있는 상태에서 "스크립트 실행" 이라는 태스크를 실행하게 되면 그제서야 GEC에 속한 코드가 실행되는 방식이다.
그럼 하나하나 어떻게 동작하는지 그림으로 살펴보자.
<img src="../../images/javascript/task0.png" width="600px">
제일 먼저, "스크립트 실행" 태스크가 태스크 큐에 들어가게 된다.
<img src="../../images/javascript/task1.png" width="600px">
이후, 이벤트 루프가 그 태스크를 가져와서 로드된 스크립트를 실행시킨다. 따라서 맨 처음에 `console.log` 가 실행된다.
<img src="../../images/javascript/task2.png" width="600px">
그 다음, `setTimeout()` 이 콜 스택으로 가고 브라우저가 이를 받아서 타이머를 동작시킨다.
<img src="../../images/javascript/task3.png" width="600px">
타이머가 끝나면 `setTimeout()` 의 콜백함수를 태스크 큐에 넣는다.
<img src="../../images/javascript/task4.png" width="600px">
`Promise` 가 콜 스택으로 가고 콜백함수를 마이크로태스크 큐에 넣는다.
<img src="../../images/javascript/task5.png" width="600px">
이벤트 루프는 마이크로태스크 큐에서 제일 오래된 태스크인 `Promise` 의 콜백함수를 가져와 콜 스택에 넣는다.
<img src="../../images/javascript/task6.png" width="600px">
`Promise` 의 콜백함수가 끝나고 태스크 큐에서 제일 오래된 태스크인 `setTimeout()` 의 콜백함수를 가져와 콜 스택에 넣는다.
<img src="../../images/javascript/task7.png" width="600px">
`setTimeout()` 의 콜백함수가 끝나면 콜 스택이 비게 되고 프로그램이 종료된다.
<br>
## 참고
* [자바스크립트와 이벤트 루프](https://meetup.toast.com/posts/89)
* [what the heck is the event loop anyway](https://www.youtube.com/watch?v=8aGhZQkoFbQ) → 굉장히 좋은 영상, 꼭 1번은 보자.
* [Event loop: microtasks and macrotasks](https://javascript.info/event-loop)
================================================
FILE: Notes/javascript/execution-context.md
================================================
# 실행 컨텍스트 (Execution Context)
## 정의
**코드의 실행환경에 대한 여러가지 정보를 담고 있는 개념** 으로, 간단히 말하자면 자바스크립트 엔진에 의해 만들어지고 사용되는 코드 정보를 담은 객체의 집합이라고 할 수 있다.
<br>
## 종류
자바스크립트의 코드는 3가지 종류로 이루어지는데, 글로벌 스코프에서 실행하는 글로벌 코드, 함수 스코프에서 실행하는 함수 코드 그리고 여기서 다루진 않지만 `eval()` 로 실행되는 코드가 있다. 이 각각의 코드는 자신만의 실행 컨텍스트를 생성한다.
엔진이 스크립트 파일을 실행하기 전에 **글로벌 실행 컨텍스트(Global Execution Context, GEC)** 가 생성되고, 함수를 호출할 때마다 **함수 실행 컨텍스트(Function Execution Context, FEC)** 가 생성된다. 주의할 점은, 글로벌의 경우 실행 이전에 생성되지만 함수의 경우 호출할 때 생성된다는 점이다.
<br>
## 실행 컨텍스트 스택 (Execution Context Stack)
실행 컨텍스트가 생성되면 흔히 콜 스택(Call Stack)이라고도 불리는 실행 컨텍스트 스택에 쌓이게 된다. GEC는 코드를 실행하기 전에 쌓이고 모든 코드를 실행하면 제거된다. FEC는 호출할 때 쌓이고 호출이 끝나면 제거된다. 예시 코드를 통해 살펴보자.
```javascript
function func() {
console.log('함수 실행 컨텍스트');
}
console.log('글로벌 실행 컨텍스트');
func();
```
제일 처음, 코드를 실행하기 전에 GEC가 쌓이고 코드를 실행하면서 콘솔에 "글로벌 실행 컨텍스트" 가 출력된다. 그 다음 `func()` 을 호출하고 그에 대한 FEC가 만들어져 쌓이고 FEC를 실행하며 콘솔에 "함수 실행 컨텍스트" 가 출력된다. 이후 `func()` 이 종료되고 FEC가 스택에서 제거된 후, 모든 코드의 실행이 끝나면서 GEC가 스택에서 제거된다. [GIF](https://miro.medium.com/max/1100/1*dUl6qPEaDJJTXWythQsEtQ.gif) 를 통해서 더 쉽게 이해할 수 있으니 꼭 보자.
<br>
## 구성요소
실행 컨텍스트는 다음과 같은 구성요소를 갖는다.
* Lexical Environment
* Variable Environment
* this 바인딩
### Lexical Environment
Lexical Environment는 **변수 및 함수 등의 식별자(Identifier) 및 외부 참조에 관한 정보를 가지고 있는 컴포넌트** 이다. 이 컴포넌트는 2개의 구성요소를 갖는다.
* **Environment Record**
* **outer 참조**
Environment Record가 식별자에 관한 정보를 가지고 있으며 outer 참조는 외부 Lexical Environment를 참조하는 포인터이다.
```javascript
var x = 10;
function foo() {
var y = 20;
console.log(x);
}
```
위와 같은 코드가 있을 때는 아래와 같이 Lexical Environment가 형성된다.
```
globalEnvironment = {
environmentRecord = { x: 10 },
outer: null
}
fooEnvironment = {
environmentRecord = { y: 20 },
outer: globalEnvironment
}
```
따라서, `foo()` 에서 `x` 를 참조할 때는 현대 Environment Record를 찾아보고 없기 때문에 outer 참조를 사용하여 외부의 Lexical Environment에 속해 있는 Environment Record를 찾아보는 방식이다.
### Variable Environment
Variable Environment는 Lexical Environment와 동일한 성격을 띠지만 **`var` 로 선언된 변수만 저장한다는 점에서 다르다.** 즉, Lexical Environment는 `var` 로 선언된 변수를 제외하고 나머지(`let` 으로 선언되었거나 함수 선언문)를 저장한다. ( 코드로 확인해 볼려면 [여기](https://stackoverflow.com/a/45788048/11789111) 를 보자 )
### this 바인딩
this의 바인딩은 실행 컨텍스트가 생성될 때마다 this 객체에 어떻게 바인딩이 되는지를 나타낸 것이다. (ES6부터 this의 바인딩이 LexicalEnvironment 안에 있는 EnvironmentRecord 안에서 일어난다는 사실을 기억해두도록 하자. 그렇게 중요하진 않으니 알고만 있자.)
* **GEC의 경우**
* strict mode라면 `undefined` 로 바인딩된다.
* 아니라면 글로벌 객체로 바인딩된다. (브라우저에선 window, 노드에선 global)
* **FEC의 경우**
* 해당 함수가 어떻게 호출되었는지에 따라 바인딩된다.
<br>
## 과정
EC는 2가지 과정을 거친다.
1. **Creation Phase (생성단계)**
2. **Execution Phase (실행단계)**
### 생성단계
생성단계는 다시 3가지 단계로 이루어진다.
1. Lexical Environment 생성
2. Variable Environment 생성
3. this 바인딩
여기서 **주의할 점은 값이 변수에 매핑되지 않는다는 것** 이다. `var` 의 경우는 `undefined` 로 초기화되고 `let` 이나 `const` 는 아무 값도 가지지 않는다.
### 실행단계
이제 코드를 실행하면서 **변수에 값을 매핑시킨다.** 예시를 통해 보자.
```javascript
var a = 3;
let b = 4;
function func(num) {
var t = 9;
console.log(a + b + num + t);
}
var r = func(4);
```
* **GEC의 생성 단계**
여기서 생성이 될 때 실행 컨텍스트 스택에 쌓인다.
```
GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: <uninitialized>,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: undefined,
r: undefined
},
outer 참조: null
}
}
```
* **GEC의 실행 단계**
```
GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: 4,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: 3,
r: undefined
},
outer 참조: null
}
}
```
이제 `func()` 을 호출하고 FEC를 생성한다.
* **FEC의 생성 단계**
```
FEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
arguments: { num: 4, length: 1 },
},
outer: GEC의 LexicalEnvironment
},
VariableEnvironment: {
EnvironmentRecord: {
t: undefined
},
outer: GEC의 LexicalEnvironment
}
}
```
* **FEC의 실행 단계**
```
FEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
arguments: { num: 4, length: 1 },
},
outer: GEC의 LexicalEnvironment
},
VariableEnvironment: {
EnvironmentRecord: {
t: 9
},
outer: GEC의 LexicalEnvironment
}
}
```
FEC가 스택에서 제거 되고 GEC의 `r` 이 20으로 초기화된다.
```
GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: 4,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: 3,
r: 20
},
outer 참조: null
}
}
```
모든 코드를 실행하고 GEC가 스택에서 제거된 뒤 프로그램이 종료된다. [GIF](https://miro.medium.com/max/1100/1*SBP65hdVDW5j0LuVryTiXw.gif) 를 보면 더 확실히 이해할 수 있으니 꼭 보자.
<br>
## 참고
* [What is the 'Execution Context' in JavaScript exactly?](https://stackoverflow.com/questions/9384758/what-is-the-execution-context-in-javascript-exactly)
* [[JS] 자바스크립트의 The Execution Context (실행 컨텍스트) 와 Hoisting (호이스팅)](https://velog.io/@imacoolgirlyo/JS-자바스크립트의-Hoisting-The-Execution-Context-호이스팅-실행-컨텍스트-6bjsmmlmgy)
* [자바스크립트 함수 (2) - 함수 호출](https://meetup.toast.com/posts/123)
* [The ECMAScript “Executable Code and Execution Contexts” chapter explained](https://medium.com/@g.smellyshovel/the-ecmascript-executable-code-and-execution-contexts-chapter-explained-fa6e098e230f#f88f)
* [ECMA-262-5 in detail. Chapter 3.2. Lexical environments: ECMAScript implementation.](http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-2-lexical-environments-ecmascript-implementation/#this-binding)
* [ECMAScript 5 spec: LexicalEnvironment versus VariableEnvironment](https://2ality.com/2011/04/ecmascript-5-spec-lexicalenvironment.html)
* [Variable Environment vs lexical environment](https://stackoverflow.com/questions/23948198/variable-environment-vs-lexical-environment)
* [ECMAScript 2020 Language Specification](https://tc39.es/ecma262/)
* [JavaScript Internals: Execution Context](https://medium.com/better-programming/javascript-internals-execution-context-bdeee6986b3b)
================================================
FILE: Notes/javascript/hoisting.md
================================================
# 호이스팅(Hoisting)
> [스코프](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/scope.md) 의 개념을 이해하지 못했다면 이해하고 오자.
호이스팅이란 "끌어올린다" 라는 뜻으로 **변수 및 함수 선언문이 스코프 내의 최상단으로 끌어올려지는 현상** 을 말한다. 여기서 주의할 점은 **"선언문"** 이라는 것이며 "대입문"은 끌어올려지지 않는다. 아래 코드를 보자.
```javascript
console.log(a);
var a = 2;
```
컴파일러는 자바스크립트 엔진이 인터프리팅(Interpreting)을 하기 전에 컴파일을 하는데 이 때, `var a = 2;` 를 2개의 구문으로 본다.
* `var a`
* `a = 2`
`var a` 는 변수 선언문으로 컴파일을 할 때 처리하고, `a = 2` 는 실행할 때까지 내버려둔다. 따라서, 변수 a는 호이스팅 되고 콘솔에는 다음과 같은 결과가 나온다.
```javascript
undefined
```
함수 선언문의 경우도 호이스팅 된다.
```javascript
func();
function func() { console.log('함수 호이스팅'); }
```
```
함수 호이스팅
```
<br>
## 함수 호이스팅에서 주의할 점
함수 호이스팅에서 주의할 점이 더 있다.
* **함수 표현식(Function Expression)은 호이스팅 되지 않는다.**
```javascript
func();
var func = function() {}
```
여기서는 변수 func의 호이스팅이 발생해서 참조할 수는 있기 때문에 ReferenceError가 발생하지 않지만 그 값이 `undefined` 이기 때문에 TypeError가 발생한다.
* **함수와 변수 선언문 중에는 함수 선언문이 먼저다.**
```javascript
func();
var func = function(){ console.log('변수 호이스팅') }
function func() {
console.log('함수 호이스팅');
}
```
동일한 이름으로 함수 선언문과 변수 선언문(= 함수표현식)이 있지만 함수 선언문의 호이스팅이 먼저이기 때문에 결과는 다음과 같다.
```
함수 호이스팅
```
<br>
## 참고
* [You don't know JS, Scope and Closures : Chapter 5: The (not so) Secret Lifecycle of Variables](https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch5.md)
================================================
FILE: Notes/javascript/identity-equal.md
================================================
# == vs ===
둘 다 동일한 비교를 하지만 엄격한 동등 비교 연산자(===)의 경우, **타입변환(Type conversion)이 일어나지 않으며 타입이 일치해야한다.**
```javascript
'' == '0' // false
0 == '' // true
0 == '0' // true
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true
```
위 경우를 보면, 동등 비교 연산자(==) 를 사용해서 여러가지 원시타입을 비교해보았는데, 타입변환이 발생함을 볼 수 있다.
단, 객체/배열의 경우는 참조타입이기 때문에 두 연산자 모두 동일하게 동작한다.
```javascript
var a = {}
var b = {}
a == b // false
a === b // false
var c = [];
var d = [];
c == d // false
c === d // false
```
문자열의 경우는 좀 특별한데, 자바스크립트에서 문자열은 원시타입이지만 객체로도 만들 수 있기 때문에 그 동등 비교가 다르다.
```javascript
var a = "string"
var b = new String("string")
a == b // true
a === b // false
```
퍼포먼스 측면에서는 아주 미묘한 차이가 있기 때문에 신경쓸 바가 못되고, **안전한 타입 체크와 더 좋은 코드를 위해 엄격한 동등 비교 연산자(===)를 사용하는 것이 바람직하다.** 물론, 각 타입에 따라 변환이 어떻게 일어나는지에 대한 원리는 따로 공부해서 이해하도록 하자.
<br>
## 참고
* [Stackoverflow, Which equals operator (== vs ===) should be used in JavaScript comparisons?](https://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons)
* [JS, 강제변환](https://baeharam.netlify.com/posts/javascript/JS-강제변환)
================================================
FILE: Notes/javascript/iife.md
================================================
# IIFE (Immediately-Invoked Function Expression)
IIFE는 직역하면 즉시-실행 함수 표현식이다. 즉, 2가지 조건을 지닌다.
* **즉시 실행하여야 한다.**
* **함수 표현식이어야 한다. ( = 함수 선언문이 아니어야 한다. )**
결국, 정의하자면 함수 표현식을 즉시 실행하는 것을 말하며 해당 함수는 **익명함수와 기명함수 모두 가능** 하다. 다음과 같이 만들 수 있다.
```javascript
(function(){
console.log('IIFE');
})();
```
실행하면 바로 "IIFE"가 출력된다. 여기서 함수는 익명함수를 사용했고 괄호로 감쌌는데, 이것은 함수 표현식으로 만들겠다는 것으로 괄호로 감싸지 않으면 함수 선언문이 되기 때문이다.
<br>
## 2가지 형태와 화살표 함수
IIFE는 2가지 형태로 사용할 수 있다.
```javascript
(function(){ console.log('IIFE'); })();
(function(){ console.log('IIFE'); }());
```
더글라스 크락포드는 아래의 방식이 에러를 덜 발생시키는 표현이라고 선호하는데, 반대하는 개발자들도 있어서 **단순히 스타일의 차이** 로 인식하면 된다.
### 화살표 함수(Arrow Function)으로 사용
ES2015(ES6)에 등장한 화살표 함수를 사용해서도 IIFE를 만들 수 있다.
```javascript
(() => console.log('IIFE'))();
```
단, 주의할 점은 이 방식의 경우 크락포드가 선호하는 방식을 사용할 수 없다.
```javascript
(() => console.log('IIFE')());
```
위 코드는 동작하지 않는데, 그 이유는 함수를 호출하기 위해선 호출대상이 명세에서 말하는 *MemberExpression*이어야 한다. 그러나 화살표 함수의 경우 *AssignmentExpression* 이기 때문에 불가능한 것이다. 이게 무슨 말인지 모르겠다면 [스택오버플로우의 답변](https://stackoverflow.com/a/34589765/11789111) 을 참고하자.
<br>
## 사용 이유
IIFE를 사용하는 이유는, 보통 전역 스코프(Global Scope)를 오염시키지 않기 위해서 사용한다. 즉, 변수를 전역 스코프에 선언하는 것을 피하기 위함이다. 이런 기법이 다음과 같은 상황에 이용된다.
### 클로저와 private 데이터
IIFE안에서 클로저를 생성하면 private 데이터를 만들 수 있고 외부에서 접근할 수 없다.
```javascript
const getCount = (function(){
let count = 1;
return function() {
++count;
return count;
}
})();
console.log(getCount()); // 2
console.log(getCount()); // 3
```
IIFE안의 익명함수는 클로저가 되고 변수 `count` 는 private 데이터가 되므로 밖에 보여지지 않는다. 흔히 말하는 모듈 패턴이 바로 이 방식에 의존한다.
### 변수의 별칭(alias)
예를 들어, 동일한 전역 변수를 갖는 2개의 라이브러리를 사용한다고 했을 때 충돌을 해결하기 위해 사용할 수도 있다. jQuery의 경우 `$` 라는 전역 변수를 갖는데 이를 갖는 또 다른 라이브러리가 있다고 하면 다음과 같이 해결할 수 있다.
```javascript
window.$ = funciton(){};
(function($){...})(jQuery);
```
### 최소화(Minification)를 활용한 최적화(Optimization)
[UglifyJS](https://github.com/mishoo/UglifyJS2) 와 같은 라이브러리는 최소화를 통해서 최적화를 하는데, 여기에는 변수명을 짧게 만드는 것도 포함한다.
```javascript
(function(window, document, undefined) {...})(window, document);
```
위와 같은 IIFE가 있다고 하면, 다음과 같이 줄일 수 있다.
```javascript
(function(w, d, u) {...})(window, document);
```
이를 통해 파일의 크기를 줄일 수 있게 된다.
<br>
## 참고
* [Explain the encapsulated anonymous function syntax](https://stackoverflow.com/questions/1634268/explain-the-encapsulated-anonymous-function-syntax)
* [What is the practical use of an IIFE with a name?](https://stackoverflow.com/questions/18365801/what-is-the-practical-use-of-an-iife-with-a-name)
* [Use Cases for JavaScript's IIFEs](https://mariusschulz.com/blog/use-cases-for-javascripts-iifes)
* [What is the (function() { } )() construct in JavaScript?](https://stackoverflow.com/questions/8228281/what-is-the-function-construct-in-javascript)
================================================
FILE: Notes/javascript/module.md
================================================
# 모듈 시스템: CommonJS, AMD, UMD, ES6
## 모듈(module)이란?
모듈이란 **여러 기능들에 관한 코드가 모여있는 하나의 파일** 로 다음과 같은 것들을 위해 사용한다.
* **유지보수성** : 기능들이 모듈화가 잘 되어있다면, 의존성을 그만큼 줄일 수 있기 때문에 어떤 기능을 개선한다거나 수정할 때 훨씬 편하게 할 수 있다.
* **네임스페이스화** : 자바스크립트에서 전역변수는 전역공간을 가지기 때문에 코드의 양이 많아질수록 겹치는 네임스페이스가 많아질 수 있다. 그러나 모듈로 분리하면 모듈만의 네임스페이스를 갖기 때문에 그 문제가 해결된다.
* **재사용성** : 똑같은 코드를 반복하지 않고 모듈로 분리시켜서 필요할 때마다 사용할 수 있다.
이런 장점들을 살리기 위해서 모듈 개념이 필요했고 자바스크립트에선 모듈을 개발하기 위한 여러가지 시도들이 있었다. CommonJS, AMD, UMD 및 ES6 등 각각의 특징과 사용법을 알아보자.
<br>
## CommonJS
자바스크립트의 공식 스펙이 브라우저만 지원했기 때문에 이를 서버사이드 및 데스크탑 어플리케이션에서 지원하기 위한 노력이 있었다. 그걸 위해 만든 그룹이 CommonJS이며 여기선 자바스크립트가 범용적인 언어로 쓰이기 위한 스펙을 정의하고 있다. 그룹을 만들었을 때, 범용적인 언어로 만들기 위해서는 모듈화의 개념이 필요했고 이 그룹만의 모듈 방식을 정의하게 되었는데 그것이 바로 CommonJS 방식의 모듈화다.
다른 모듈을 사용할 때는 **require** 를, 모듈을 해당 스코프 밖으로 보낼 때에는 **module.exports** 를 사용하는 방식으로, Node.js에선 현재 이 방식을 사용하고 있다. hello world를 출력하는 함수를 가진 파일을 `a.js` 라고 하고 그 함수를 가져와서 사용하는 파일을 `b.js` 라고 하면 다음과 같이 사용할 수 있다.
* `a.js`
```javascript
const printHelloWorld = () => {
console.log('Hello Wolrd');
};
module.exports = {
printHelloWorld
};
```
* `b.js`
```javascript
const func = require('./a.js'); // 같은 디렉토리에 있다고 가정
func.printHelloWorld();
```
여기서 `module.exports` 의 `module` 은 현재 모듈에 대한 정보를 갖고 있는 객체이다. 이는 예약어이며 그 안에 `id` , `path` , `parent` 등의 속성이 있고 `exports` 객체를 가지고 있다.
### exports vs module.exports
`module.exports` 외에도 `exports` 를 사용하기도 하는데 이 관계에 대해서 명확히 이해하고 있어야 한다. 정리하자면 아래와 같다.
* `module.exports` 는 빈 객체를 참조한다.
* `exports` 는 `module.exports` 를 참조한다.
* `require` 는 항상 `module.exports` 를 리턴받는다.
즉, 함수를 모듈 밖으로 내보내고자 할 때는 위에 예시에서 2가지 모두 사용할 수 있다.
```javascript
exports.printHelloWorld = printHelloWorld;
module.exports = { printHelloWorld };
```
그렇다면 왜 2가지를 설정해놓았을까? 그 이유는 `exports` 는 항상 `module.exports` 를 참조하기 때문에 `exports` 를 사용하면 직접 `module.exports` 를 수정하지 않고 객체의 멤버를 만들거나 수정하는 방식으로 사용한다. 따라서, `exports` 에 어떤 값을 할당하거나 새로운 객체를 할당했다고 하더라도 결국 `require` 는 `module.exports` 를 리턴받기 때문에 잠재적인 버그를 피할 수가 있다.
<br>
## AMD(Asynchronous Module Definition)
CommonJS 그룹에서 의견이 맞지 않아 나온 사람들이 만든 그룹으로 비동기 모듈에 대한 표준안을 다루는 그룹이다. CommonJS가 서버쪽에서 장점이 많은 반면에 AMD는 브라우저 쪽에서 더 큰 효과를 발휘한다. 브라우저에서는 모든 모듈이 다 로딩될 때까지 기다릴 수 없기 때문에 비동기 모듈 로딩방식으로 구현을 해놓았다. 이 방식에서 사용하는 함수는 `define()` 과 `require()` 이며 AMD 스펙을 가장 잘 구현한 모듈로더는 RequireJS 이다. 한번 간단한 예시로 사용해보자.
* `index.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<script data-main="index.js" src="require.js"></script>
</body>
</html>
```
`require.js` 파일을 받아서 `<script>` 태그에 넣어주고 `data-main` 속성으로 `require.js` 가 로드된 후에 실행할 자바스크립트 파일 경로를 넣어준다. 즉, `require.js` 가 로드되자마자 `index.js` 가 실행되는 구조이다.
* `index.js`
```javascript
require.config({
baseUrl: '/',
paths: {
a: 'a',
b: 'b',
}
});
require(['a'], (a) => {
a.printA();
});
```
`require.config` 는 설정부분으로 기본 경로와 각 모듈에 해당하는 경로를 설정해준다. 그 다음 `require` 를 통해서 첫번째 인자에 해당하는 모듈이 로드되었을 경우에 그걸 `a` 로 받아서 `printA()` 함수를 호출하는 콜백함수를 실행한다. 의존성 모듈을 지정해주는 것이다.
* `a.js`
```javascript
define(() => {
return {
printA: () => console.log('a')
}
});
```
모듈 a는 위와 같이 만들어져 있고 `define()` 을 통해서 정의된다. 여기서도 `require()` 에서 의존성 모듈을 설정해준 것처럼 콜백함수가 실행되기 전에 로드되어야 할 모듈들을 지정해줄 수 있다.
<br>
## UMD(Universal Module Definition)
위에서 살펴본 바로, 모듈 구현방식이 CommonJS 와 AMD로 나뉘기 때문에 그걸 통합하기 위한 하나의 패턴이라고 할 수 있다. [공식 umd 소스코드](https://github.com/umdjs/umd/blob/master/templates/returnExports.js) 를 살펴보면 아래와 같다.
```javascript
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.returnExports = factory();
}
}(typeof self !== 'undefined' ? self : this, function () {
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {};
}));
```
AMD, CommonJS, Browser 방식의 모듈을 지원하기 위한 것으로 확인하는 방식은 코드를 살펴보면 다음과 같다.
* **AMD**: `define()` 이 함수이고 `define.amd` 속성의 객체를 가지고 있다.
* **CommonJS**: `module` 이 객체이고 `module.exports` 속성의 객체를 가지고 있다.
* **Browser**: 따로 특이사항이 없다.
통합하는 방식은 2개의 인자를 전달받는 함수를 실행하는 것으로, 첫번째 인자는 Browser 쪽을 구현할 `root` 에 넘길 값으로 `undefined` 이면 `this` 로 아니라면 `self` , 즉 `window` 로 설정한다. 그리고 2번째 인자로 빈 객체 리터럴을 리턴하는 함수를 보낸다. 이렇게 되면 각각의 환경에서 모두 모듈개념을 사용할 수 있게 된다.
<br>
## ES6(ES2015) 방식
`import` 와 `export` 구문을 사용하는 방식으로 나에게는 이 방식이 가장 익숙하다. 하지만 모든 브라우저가 지원하는 것이 아니기 때문에 Babel의 `@babel/plugin-transform-modules-commonjs` 를 통해 변환시켜서 사용한다. 모듈 A,B가 있고 각각을 `export` 로 내보내는 방식과 그에 따라 어떻게 `import` 로 불러오는지 살펴보자.
* `moduleA.js`
```javascript
const A = () => {};
export default A;
```
* `moduleB.js`
```javascript
export const B = () => {};
```
* `index.js`
```javascript
import A from 'moduleA';
import { B } from 'moduleB';
```
여기서 눈여겨봐야될 것은 `default` 의 유무인데 `export` 를 사용할 때는 **named export** 와 **default export** 를 사용할 수 있다. 단, default export는 모듈 내에서 한번만 사용할 수 있고 named export는 여러번 사용할 수 있다는 것이다. 그렇게 default export로 내보내면 `import` 에선 내보낸 이름 그대로 바로 사용할 수 있지만, named export로 내보내면 `{}` 로 묶어서 불러와야 한다. 이것이 기본적인 사용법이고 별칭(alias)을 `as` 로 주어서 다른 이름으로 사용할 수도 있고 `*` 와일드카드를 사용하여 한번에 불러오거나 내보낼 수도 있다. 이런 여러가지 변형기법의 사용은 [여기](https://velog.io/@doondoony/JavaScript-Module-System#-es6-modulesesm) 를 참고하자.
<br>
## 참조
* [JavaScript Modules: A Beginner’s Guide](https://www.freecodecamp.org/news/javascript-modules-a-beginner-s-guide-783f7d7a5fcc/)
* [AMD, CommonJS, UMD 모듈](https://www.zerocho.com/category/JavaScript/post/5b67e7847bbbd3001b43fd73)
* [[NodeJS] module.exports와 exports의 차이점](https://programmingsummaries.tistory.com/340)
* [module.exports vs exports in Node.js](https://stackoverflow.com/questions/7137397/module-exports-vs-exports-in-node-js)
* [JavaScript 표준을 위한 움직임: CommonJS와 AMD](https://d2.naver.com/helloworld/12864)
* [RequireJS - AMD의 이해와 개발](https://d2.naver.com/helloworld/591319)
* [requireJS를 통한 모듈화 및 의존성 관리 - (1)](https://wckhg89.github.io/archivers/requirejs1#requirejs를-이용한-모듈화-및-의존성-관리)
================================================
FILE: Notes/javascript/native-host.md
================================================
# 네이티브 객체 vs 호스트 객체
## 네이티브 객체 (Native Object)
ECMAScript 명세에서 의미론적인 부분을 완전히 정의해놓은 객체들로, 다음과 같은 것들이 있다.
* `Object`
* `Function`
* `Date`
* `Math`
* `parseInt`
* `eval` ...
<br>
## 호스트 객체 (Host Object)
자바스크립트를 실행하는 환경에 종속된 객체로 그 환경에서만 찾아볼 수 있는 객체이다. 만약 브라우저 환경이라면 다음과 같은 것들이 있다.
* `window`
* `document`
* `location`
* `XMLHttpRequest`
* `querySelectorAll` ...
<br>
## 참고
* [Stackoverflow, What is the difference between native objects and host objects?](https://stackoverflow.com/questions/7614317/what-is-the-difference-between-native-objects-and-host-objects)
* [MDN, Standard built-in objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)
* [Poiemaweb, 빌트인 객체](https://poiemaweb.com/js-built-in-object)
================================================
FILE: Notes/javascript/new.md
================================================
# new의 동작방식
자바스크립트에선 `new` 연산자를 통해 함수를 생성자로 호출할 수 있고 그에따라 새로운 객체를 생성할 수 있다. 다음과 같은 과정으로 이루어진다.
* 빈 객체를 생성한다.
* `[[Prototype]]` 속성을 생성자 호출할 함수의 `prototype` 속성으로 지정한다.
* 만약 함수의 `prototype` 속성이 원시값이라면 `Object.prototype` 으로 지정된다.
* 객체를 생성하고 이 객체를 `this` 로 지정한다.
* 함수를 호출하고 해당 함수의 `this` 로 위에서 지정한 객체를 사용한다.
* 함수의 리턴값이 원시값이라면 새로 만들어진 객체가 리턴되고 리턴값이 객체라면 해당 객체가 리턴된다.
이를 코드로 보면 다음과 같다.
```javascript
function Func() {}
const f = new Func();
```
* 빈 객체 생성 `{}`
* 해당 객체의 `[[Prototype]]` 을 `Func.prototype` 으로 지정
* 이 객체를 `this` 로 지정
* `Func()` 을 호출하고 이 함수에서 `this` 를 위 객체로 지정
* 함수의 리턴값이 `undefined` 원시값이므로 생성한 객체를 리턴
<br>
## 참고
* [Stackoverflow, What is the 'new' keyword in JavaScript?](https://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript)
* [Stackoverflow, How does the new operator work in JavaScript?](https://stackoverflow.com/questions/6750880/how-does-the-new-operator-work-in-javascript)
================================================
FILE: Notes/javascript/prototype.md
================================================
# 프로토타입 (Prototype)
자바스크립트에서 정말 헷갈리는 개념으로, 자바스크립트를 다루는데 있어서 굉장히 중요한 역할을 하기 때문에 반드시 이해하여야 한다.
## 정의
자바스크립트의 모든 객체는 자신의 **"원형(Prototype)"** 이 되는 객체를 가지며 이를 프로토타입이라고 한다. 보이지 않는 속성인 `[[Prototype]]` 이 자신의 프로토타입 객체를 참조한다. 이를 `__proto__` 라는 속성으로 참조할 수 있으나 이는 비표준이고 모든 브라우저에서 동작하는 것은 아니기 때문에 실제로 사용하는 것은 피해야 한다.
<br>
## .prototype과 [[Prototype]]
프로토타입이 헷갈리는 이유는 그 명명법과 연결방식에 있는데, 모든 객체는 은닉 속성인 `[[Prototype]]` 을 갖는데 특별히 **함수 객체** 는 접근할 수 있는 속성인 `prototype` 을 갖는다. 이름만 보면 같은 것으로 보이기 때문에 관계를 명확히 파악하여야 한다.
* `[[Prototype]]` : 자신의 프로토타입 객체를 참조하는 속성이다.
* `.prototype` : `new` 연산자로 자신을 생성자 함수로 사용한 경우, 그걸로 만들어진 새로운 객체의 `[[Prototype]]` 이 참조하는 값이다.
다음 코드를 보자.
```javascript
function Func() {}
var a = new Func();
```
`Func` 을 생성자로 호출하여 새로운 객체 `a` 를 생성한다. 이는 아래와 같은 구조로 프로토타입이 연결된다.
<img src="../../images/javascript/prototype1.png">
그림을 보면 위에서 언급하지 않은 2가지가 있는데. `constructor` 는 모든 `.prototype` 객체의 속성에 있는 것으로 실제 객체를 참조한다. 따라서 위와 같이 `Func` 을 가리키는 것이다. 그 다음, `Func.prototype` 의 `[[Prototype]]` 이 `Object.prototype` 으로 연결되는데 이는 모든 객체의 프로토타입 객체로 마지막으로 연결되는 프로토타입 객체이다. 즉, 정리하자면 다음과 같다.
* `new` 연산자로 새로운 객체 `a` 를 생성하면, `a` 의 프로토타입 객체는 생성자 함수로 사용한 `Func` 의 속성인 `Func.prototype` 이 된다.
* `Func.prototype` 은 `constructor` 속성을 가지며 이는 실제 객체 `Func` 을 가리킨다.
* `Func.prototype` 또한 객체이므로 `[[Prototype]]` 을 가지고 이는 모든 객체의 원형이 되는 객체인 `Object.prototype` 을 가리킨다.
<br>
## 프로토타입 체인
어떤 객체의 프로퍼티를 참조하거나 값을 할당할 때 **해당 객체에 프로퍼티가 없을 경우, 그 객체의 프로토타입 객체를 연쇄적으로 보면서 프로퍼티를 찾는 방식** 을 프로토타입 체인이라고 한다. 단, 참조할 때와 값을 할당할 때의 메커니즘이 다르니 기억해두어야 한다.
* **프로퍼티를 참조할 때**
* 찾고자 하는 프로퍼티가 객체에 존재하면 사용한다.
* 없으면 `[[Prototype]]` 링크를 타고 끝까지 올라가면서 해당 프로퍼티를 찾는다.
* 찾으면 그 값을 사용하고 없으면 `undefined` 를 반환한다.
* **프로퍼티에 값을 할당할 때**
* 찾고자 하는 프로퍼티가 객체에 존재하면 값을 바꾼다.
* 프로퍼티가 없고 `[[Prototype]]` 링크를 타고 올라가서 해당 프로퍼티를 찾았을 경우
* 그 프로퍼티가 변경가능한 값, 즉 `writable: true` 라면 새로운 직속 프로퍼티를 할당해서 상위 프로퍼티가 가려지는 현상이 발생한다.
* 그 프로퍼티가 변경불가능한 값, 즉 `writable: false` 라면 비엄격 모드에선 무시되고 엄격 모드에선 에러가 발생한다.
* 해당 프로퍼티가 세터(setter) 일 경우, 이 세터가 호출되고 가려짐이 발생하지 않는다.
여기서 말하는 **"가려짐"** 이란, 상위 프로토타입 객체에 동일한 이름의 프로퍼티가 있는 경우, 하위 객체의 프로퍼티에 의해 가려지는 현상을 말한다.
```javascript
function Func() {}
Func.prototype.num = 2;
var a = new Func();
a.num = 1;
console.log(a.num); // 1
```
위 코드의 경우 객체 `a` 의 프로토타입 객체인 `Func.prototype` 에 `num` 이 있지만 `a.num = 1` 로 인해 가려짐 현상이 발생해서 1을 출력한다.
```javascript
function Func() {}
Object.defineProperty(Func.prototype, "num", {
value: 2,
writable: false
})
var a = new Func();
a.num = 1; // 무시됨
console.log(a.num); // 2
```
그러나 `defineProperty()` 를 사용해서 변경불가능한 프로퍼티로 만들면, 비엄격모드에서 무시되서 2를 출력한다.
<br>
## 관련 함수 및 연산자
### Object.create()
**프로토타입 객체를 받아 연결시켜서 새 객체를 만드는 함수** 로, 프로토타입 객체를 바꾸기 때문에 원래의 `constructor` 를 잃어버린다.
```javascript
function Func1() {}
function Func2() {}
Func2.prototype = Object.create(Func1.prototype);
console.log(Func2.prototype.constructor); // Func1
```
기대하는 결과는 `Func2` 이겠지만 프로토타입 객체가 `Func1.prototype` 으로 바뀌었고 이에 따라 `constructor` 값을 잃어버렸다. 따라서, 프토토타입 체인을 통해서 `Func1.prototype` 의 `constructor` 인 `Func1` 을 출력하게 된다.
### instanceof vs isPrototypeOf
instanceof는 2개의 피연산자를 받는 연산자이고 isPrototypeOf는 `Object.prototype` 에 있는 함수이다. **둘 다 특정 객체의 프로토타입 체인에 찾고자 하는 객체가 있는지 검사할 때 사용** 된다.
```javascript
function A() {}
function B() {}
B.prototype = new A();
B.prototype.constructor = B;
function C() {}
C.prototype = new B();
C.prototype.constructor = C;
var c = new C();
console.log(c instanceof A, A.prototype.isPrototypeOf(c)); // true
console.log(c instanceof B, B.prototype.isPrototypeOf(c)); // true
console.log(c instanceof C, C.prototype.isPrototypeOf(c)); // true
```
### getPrototypeOf, setPrototypeOf
각각 특정 객체의 프로토타입 객체를 가져오고 할당하는 함수이다.
```javascript
function A() {}
function B() {}
var a = new A();
console.log(Object.getPrototypeOf(a)); // A.prototype
Object.setPrototypeOf(a, B.prototype);
console.log(Object.getPrototypeOf(a)); // B.prototype
```
<br>
## 참고
* You don't know JS, 프로토타입 (책)
* [Stackoverflow, What's the difference between isPrototypeOf and instanceof in Javascript?](https://stackoverflow.com/questions/2464426/whats-the-difference-between-isprototypeof-and-instanceof-in-javascript)
* [Poiemaweb, 프로토타입](https://poiemaweb.com/js-prototype)
* MDN 문서의 프로토타입 관련 함수들
================================================
FILE: Notes/javascript/scope.md
================================================
# 스코프
> [실행 컨텍스트(Execution Context)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/execution-context.md) 를 모른다면 보고 오도록 하자.
## 정의
스코프란 **자바스크립트 엔진이 참조의 대상이 되는 식별자(Identifier)를 검색할 때 사용하는 규칙의 집합** 이다. 즉, 어떤 변수를 사용하거나 함수를 호출하려고 할 때 해당하는 식별자로 사용하는데, 그 식별자를 검색하는 메커니즘이라고 이해하면 된다.
<br>
## 렉시컬 스코프
**프로그래머가 코드를 짤 때, 변수 및 함수/블록 스코프를 어디에 작성하였는가에 따라 정해지는 스코프** 를 렉시컬 스코프라고 한다. "렉시컬(Lexical)" 이라는 명칭이 붙은 이유는 자바스크립트 컴파일러가 소스코드를 토큰(Token)으로 쪼개서 의미를 부여하는 렉싱(Lexing) 단계에 해당 스코프가 확정되기 때문이다. 다시 쉽게 말하면, 변수 혹은 함수/블록이 어디에 써있는가를 보고 그 스코프를 판단하면 된다.
<br>
## 스코프 체인
**현재 스코프에서 식별자를 검색할 때 상위 스코프를 연쇄적으로 찾아나가는 방식** 을 말한다. 실행 컨텍스트를 배웠다면 생성될 때마다 LexicalEnvironment가 만들어지고 그 안에 outer 참조 값이 있다는 것을 알 것이다. 바로 이 outer 참조 값이 상위 스코프의 LexicalEnvironment를 가리키기 때문에 이를 통해 체인처럼 연결되는 것이다.
즉, 다음과 같은 과정으로 스코프 체인을 검색한다.
1. 현재 실행 컨텍스트의 LexicalEnvironment의 EnvironmentRecord에서 식별자를 검색한다.
2. 없으면 outer 참조 값으로 스코프 체인을 타고 올라가 상위 스코프의 EnvironmentRecord에서 식별자를 검색한다.
3. 이를 outer 참조 값이 `null` 일 때까지 계속하고 찾지 못한다면 에러를 발생시킨다.
<br>
## 참조
* [You don't know JS, Scope and Closures](https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch1.md)
* [PoiemaWeb, 스코프](https://poiemaweb.com/js-scope)
================================================
FILE: Notes/javascript/stack-heap.md
================================================
# 콜 스택(Call stack)과 힙(Heap)
자바스크립트 엔진이 자바스크립트를 실행할 때 원시 타입 및 참조 타입을 저장하는 메모리 구조로 콜 스택과 힙을 가진다.
* **콜 스택** : **원시타입 값** 과 함수 호출의 **실행 컨텍스트(Execution Context)** 를 저장하는 곳이다.
* **힙** : 객체, 배열, 함수와 같이 크기가 **동적으로 변할 수 있는 참조타입 값** 을 저장하는 곳이다.
<br>
## 예시를 통한 동작 원리 보기
```javascript
let a = 10;
let b = 35;
let arr = [];
function func() {
const c = a + b;
const obj = { d: c };
return obj;
}
let o = func();
```
위 코드로 콜 스택과 힙의 동작을 보면 다음과 같다.
제일 처음, GEC(Global Execution Context)가 생성되고 원시 값은 콜 스택에, 참조 값은 힙에 저장된다.
<img src="../../images/javascript/memory1.png">
그 다음 함수 `func()` 을 실행하게 되고 새로운 FEC(Function Execution Context)가 생성되며 동일하게 원시 값은 스택에, 참조 값은 힙에 저장된다.
<img src="../../images/javascript/memory2.png">
이후, 함수 `func()` 이 객체 `obj` 를 리턴해서 `o` 에 저장된다. 리턴하기 때문에 FEC는 콜 스택에서 제거된다.
<img src="../../images/javascript/memory3.png">
전체 코드가 실행이 끝나고 GEC가 콜 스택에서 제거된다. GEC가 제거됨에 따라서, 힙의 객체를 참조하는 스택의 값이 없기 때문에 가비지 컬렉터(Garbage Collector, GC)에 의해 제거된다.
<br>
## 참고
* [JavaScript V8 Engine Explained](https://hackernoon.com/javascript-v8-engine-explained-3f940148d4ef)
* [<번역>자바스크립트의 메모리 모델](https://junwoo45.github.io/2019-11-04-memory_model/)
* [V8 Memory usage(Stack & Heap)](https://speakerdeck.com/deepu105/v8-memory-usage-stack-and-heap?slide=9)
* [V8 엔진(자바스크립트, NodeJS, Deno, WebAssembly) 내부의 메모리 관리 시각화하기](https://ui.toast.com/weekly-pick/ko_20200228/)
================================================
FILE: Notes/javascript/strict-mode.md
================================================
# 엄격 모드 (Strict mode)
ECMAScript5 부터 도입된 기능으로 **기존에 무시되던 에러들로 하여금 에러를 발생시키게 한다.** 파일 전체에 적용시킬 수도 있고 함수 스코프에 적용시킬 수 있지만 블록 스코프는 불가능하다.
```javascript
"use strict"; // 파일 전체에 적용
function f() {
"use strict"; // 함수 스코프에 적용
}
```
이를 통해서 실수를 잡아낼 수 있고 안전한지 않은 것들을 예방할 수 있다. 다음 특징들을 갖는다.
* `var` 가 생략된 변수를 전역객체에 바인딩 하지 않는다.
* `NaN = 5` 같은 할당 구문은 불가능하다.
* 제거할 수 없는 프로퍼티를 제거할 수 없다. (`delete Object.prototype`)
* 함수의 매개변수 이름은 중복될 수 없다. (`function sum(x,x){}`)
* `with` 키워드 사용할 수 없다.
* 일반 변수를 삭제할 수 없다. (`delete x`)
* `arguments.callee` 를 사용할 수 없다.
* `arguments` 객체는 항상 원본 인자를 저장한다, 즉 매개변수를 바꿔도 `arguments` 의 값은 바뀌지 않는다.
* 8진수를 사용할 수 없다. (`var a = 013`)
* `eval` 은 새로운 변수를 스코프에 추가하지 않는다.
JSLint나 ESLint와 같은 린터(Linter)를 사용할 수 있으면 사용하되 사용할 수 없으면 `"use strict"` 를 사용하는 것이 좋다.
<br>
## 참고
* [MDN, Strict mode](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Strict_mode)
* [Stackoverflow, What does “use strict” do in JavaScript, and what is the reasoning behind it?](https://stackoverflow.com/questions/1335851/what-does-use-strict-do-in-javascript-and-what-is-the-reasoning-behind-it)
================================================
FILE: Notes/javascript/this.md
================================================
# this의 바인딩
EC(Execution Context)가 생성될 때마다 this의 바인딩이 일어나며 우선순위 순으로 나열해보면 다음과 같다.
1. `new` 를 사용했을 때 해당 객체로 바인딩된다.
```javascript
var name = "global";
function Func() {
this.name = "Func";
this.print = function f() { console.log(this.name); };
}
var a = new Func();
a.print(); // Func
```
2. `call`, `apply`, `bind` 와 같은 명시적 바인딩을 사용했을 때 인자로 전달된 객체에 바인딩된다.
```javascript
function func() {
console.log(this.name);
}
var obj = { name: 'obj name' };
func.call(obj); // obj name
func.apply(obj); // obj name
(func.bind(obj))(); // obj name
```
3. 객체의 메소드로 호출할 경우 해당 객체에 바인딩된다.
```javascript
var obj = {
name: 'obj name',
print: function p() { console.log(this.name); }
};
obj.print(); // obj name
```
4. 그 외의 경우
* strict mode: `undefined` 로 초기화된다.
* 일반: 브라우저라면 `window` 객체에 바인딩 된다.
<br>
## 참고
* [김정환 블로그, 자바스크립트 this 바인딩 우선순위](http://jeonghwan-kim.github.io/2017/10/22/js-context-binding.html#암시적-바인딩과-new-바인딩의-우선순위)
* [How does the “this” keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work)
================================================
FILE: Notes/javascript/var-let-const.md
================================================
# var vs let vs const
모두 변수를 선언하는 키워드라는 것은 동일하다. 하지만, let과 const는 ES2015(ES6)에서 등장했고 여러가지 다른 특성을 갖는다.
## 스코프 규칙
> 스코프의 개념을 모른다면 [스코프](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/scope.md) 를 보고 오자.
* var는 함수 스코프를 갖는다.
* let과 const는 블록 스코프를 갖는다.
```javascript
function run() {
var foo = "Foo";
let bar = "Bar";
console.log(foo, bar);
{
let baz = "Bazz";
console.log(baz);
}
console.log(baz); // ReferenceError
}
run();
```
따라서, 위 코드를 실행했을 때 블록 안에 있는 `baz` 를 출력하게 되면 ReferenceError가 발생하는 것이다.
<br>
## 호이스팅
> 호이스팅의 개념을 모른다면 [호이스팅](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/Hoisting.md) 을 보고 오자.
* var는 **함수 스코프의 최상단으로 호이스팅** 되고 선언과 동시에 `undefined` 로 초기화 된다.
* let과 const는 **블록 스코프의 최상단으로 호이스팅** 되고 선언만 되고 값이 할당되기 전까지 어떤 값으로도 초기화되지 않는다.
```javascript
function run() {
console.log(foo); // undefined
var foo = "Foo";
console.log(foo); // Foo
}
run();
```
따라서, var의 경우 위와 같이 선언 전에 출력하면 `undefined` 가 출력된다.
```javascript
function checkHoisting() {
console.log(foo); // ReferenceError
let foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
```
반면에, let의 경우는 선언 전에 호이스팅 되긴 하지만 어떤 값도 가지지 않기 때문에 ReferenceError가 발생한다. 이런 현상을 **TDZ(Temporal Dead Zone)** 라고 한다. 즉, 선언은 되었지만 참조는 할 수 없는 사각지대를 갖는 것이다.
<br>
## 글로벌 객체로의 바인딩
**strict mode가 아니라는 가정 하에,**
* var는 글로벌 스코프에서 선언되었을 경우 글로벌 객체에 바인딩된다.
* let과 const는 글로벌 스코프에서 선언되었을 경우 글로벌 객체에 바인딩되지 않는다.
```javascript
var foo = "Foo"; // globally scoped
let bar = "Bar"; // globally scoped
console.log(window.foo); // Foo
console.log(window.bar); // undefined
```
브라우저 환경에서 글로벌 객체는 `window` 인데, var의 경우 바인딩이 되었고 let의 경우는 되지 않았다는 걸 볼 수 있다.
<br>
## 재선언 (Redeclaration)
* var는 재선언이 가능하다.
* let과 const는 재선언이 불가능하다.
```javascript
var foo = "foo1";
var foo = "foo2"; // 문제없음
let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared
```
<br>
## let vs const
* var와 let은 재할당이 가능하다.
* const는 선언과 초기화가 반드시 동시에 일어나야 하며 재할당이 불가능하다. 즉, 상수와 같은 고정값을 선언할 때 사용하는 키워드이다.
<br>
## 참고
* [Stackoverflow, What's the difference between using “let” and “var”?](https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var)
* [Stackoverflow, Are variables declared with let or const not hoisted in ES6?](https://stackoverflow.com/questions/31219420/are-variables-declared-with-let-or-const-not-hoisted-in-es6)
* [PoiemaWeb, let, const](https://poiemaweb.com/es6-block-scope)
================================================
FILE: Notes/network/cdn.md
================================================
# CDN (Contents Delivery Network)
어느 스타트업의 기술 면접을 보러갔을 때, 웹사이트를 구성하는 수많은 리소스들이 있을 경우 어떻게 최적화하는가에 대한 질문을 받은 적이 있다. 예를 들어, 수십개의 이미지로 구성되어있을 경우 그 용량이 상당하기 때문에 동일한 웹서버에 요청해서 이를 가져온다면 사이트 로딩속도가 매우 느려지는데 어떻게 해결할 것인가에 관한 질문이었다. 나의 경우, 이미지 최적화에선 사용자가 보이는 부분의 이미지만 로딩하는 지연로딩(Lazy Loading) 기법을 언급했지만 면접관이 요구한 기술은 CDN이었다.
<br>
## 정의
CDN은 컨텐츠 전달 네트워크의 약자로 말 그대로, 컨텐츠를 전달하는 네트워크를 구성하는 것이다. 보통 웹사이트를 로딩할 때는 웹 서버에 HTTP 요청을 하여 리소스를 가져오지만 웹 서버가 아니라 현재 사용자가 접속한 위치에서 가장 가까운 서버에 리소스를 캐싱해놓고 보다 빠르게 가져오는 기법이다. 물론, CDN 네트워크를 구축하기 위해선 해당되는 지역의 ISP(인터넷 제공업체, Internet Service Provider), 네트워크 사업자, 이동통신 사업자에게 서버의 호스팅 비용을 지불해야 한다. 이렇게 네트워크를 구축하게 되면 정적 리소스를 더욱 빠른 속도로 서비스 할 수 있게 되는 것이다.
<br>
## 장점
* 리소스를 캐싱해놓기 때문에 로딩속도가 빨라진다.
* 1개의 웹서버에서만 리소스를 가져오지 않기 때문에 서버의 부하가 줄어든다.
* 보통 1개의 도메인이 10개의 병렬연결을 허용하는데 CDN을 사용하면 병렬연결이 늘어난다.
<br>
## 단점
* 서버를 구축하는 비용 때문에 돈이 더 많이 든다.
* 사용자가 해당되는 CDN을 막아놓으면 리소스 로딩이 막힌다.
* 배포과정이 다소 복잡해질 수 있다.
* 보통 CDN 서비스회사는 각 나라마다의 서버들을 구축해 놓지만, 자신의 나라에 없어서 해외 CDN을 사용하는 경우 더 느려질 수 있다.
<br>
## 참고
* [David Hall, Advantages and Disadvantages of a Content Delivery Network (CDN)](https://blog.webnames.ca/advantages-and-disadvantages-of-a-content-delivery-network/)
* [Stackoverflow, What are the advantages and disadvantages of using a content delivery network (CDN)?](https://stackoverflow.com/questions/2145277/what-are-the-advantages-and-disadvantages-of-using-a-content-delivery-network-c)
================================================
FILE: Notes/network/cookie-session.md
================================================
# Cookie vs Session
HTTP는 상태가 없는(Stateless) 프로토콜이기 때문에 사용자가 웹 브라우저를 통해서 특정 웹 사이트에 접속하게 될 경우 어떤 사용자가 접속했는지에 대한 정보를 파악할 수 없다. 따라서, 쿠키 또는 세션을 사용하여 사용자를 구분하고 각 사용자에 맞는 정보를 제공한다.
<br>
## Cookie
쿠키란 클라이언트의 웹 브라우저에 저장되는 작은 데이터 조각으로 서버가 클라이언트의 요청을 식별하는데 사용된다. 쿠키를 활용해서 사용자를 구분하는게 매우 유용하지만, 클라이언트가 수정할 수도 있고 해커가 탈취할 수도 있기 때문에 보안에 취약하다. 따라서, 아이디 및 비밀번호와 같은 민감한 정보들을 저장하는데 사용하지는 않고 아래와 같은 목적으로 사용한다.
* **세션 ID 관리**, 서버에 저장해야 할 민감한 정보에 대한 식별자 ID
* **개인화**, 사용자 선호 및 테마
* **트래킹**, 사용자 행동 기록 및 분석
<br>
## Session
세션이란 브라우저가 서버에 연결되어 있는 동안 유지하는 데이터 집합이다. 사용자가 웹 사이트에 방문하여 서버에 요청을 보내게 되면, 사용자의 정보를 서버에 저장하고 그 정보를 식별할 수 있는 "세션 ID"를 `Set-Cookie` 헤더로 클라이언트에게 전송한다. 위에서 말했던 것처럼 클라이언트는 쿠키로 세션 ID를 관리하고 해당 서버에 요청할 때마다 `Cookie` 헤더에 세션 ID를 포함시켜 전송하기 때문에 서버는 클라이언트를 식별하여 그에 맞는 정보를 응답으로 줄 수 있게 된다. 따라서, 아래와 같은 목적으로 사용한다고 할 수 있다.
* **민감한 정보 관리**, 사용자의 비밀번호 및 개인정보
<br>
## 차이점
* **쿠키**
* 클라이언트 쪽에 저장한다. (웹 브라우저)
* 브라우저가 꺼져도 삭제되지 않고 사용자가 삭제하거나 정해진 시간만큼 유지된다.
* 문자열만 저장할 수 있다.
* 클라이언트에서 보내기 때문에 속도가 빠르다.
* 민감한 데이터를 스니핑 당할수도 있기 때문에 보안에 취약하다.
* **세션**
* 서버쪽에 저장한다. (서버의 메모리 혹은 데이터베이스)
* 브라우저가 꺼질 경우 삭제된다.
* 문자열 뿐 아니라 객체도 저장할 수 있다.
* 서버쪽에서 처리하기 때문에 속도가 비교적 느리다.
* 서버에서 민감한 데이터를 갖고 있기 때문에 비교적 보안이 좋다.
<br>
## 참고
* [MDN, HTTP 쿠키](https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies)
* [쿠키,세션,캐시가 뭔가요? (유튜브)](https://www.youtube.com/watch?v=OpoVuwxGRDI)
* [What are sessions? How do they work?](https://stackoverflow.com/questions/3804209/what-are-sessions-how-do-they-work)
* [CS 142: Web Applications (Fall 2010)](https://web.stanford.edu/~ouster/cgi-bin/cs142-fall10/index.php)
* [Web - 쿠키와 세션의 차이, 용도, 사용법(cookie, session)](https://jeong-pro.tistory.com/80)
* [웹 서버 개발의 Session 전략](https://devhaks.github.io/2019/04/20/session-strategy/)
================================================
FILE: Notes/network/http.md
================================================
# HTTP
클라이언트-서버 모델을 따르는 프로토콜로 TCP/IP 위에서 동작하며 well-known 포트인 80번 포트를 사용하여 통신한다. 첫번째 표준은 HTTP/1.1이며 이후로 HTTP/2 및 HTTP/3가 등장하였다. 여기선 HTTP/1.1의 내용을 정리한다.
## 특징
### 비-연결 지향 (Connectionless)
클라이언트가 서버에게 리소스를 요청한 후 응답을 받으면 연결을 끊어버리는 특징이다. 연결을 유지하게 되면 서버에 많은 부담을 줄 수 있기 때문에 상당히 많은 클라이언트에게 요청을 받는 웹 서버의 경우 응답을 처리했으면 연결을 끊는다. 이로 인해 서버의 부담을 줄일 수 있지만, 리소스를 요청할 때마다 연결해야 하는 오버헤드 비용이 발생한다. 이를 해결하기 위해선, 요청 헤더의 `Connection: keep-alive` 속성으로 지속적 연결 상태(Persistent connection)를 유지할 수 있다. 즉, 요청을 할 때마다 연결하지 않고 기존의 연결을 재사용하는 방식이다. HTTP 1.1 부턴 지속적 연결 상태가 기본이며 이를 해제하기 위해선 명시적으로 요청 헤더를 수정해야 한다.
### 무상태성 (Stateless)
각각의 요청이 독립적으로 여겨지는 특징으로, 서버는 클라이언트의 상태를 유지하지 않는다. 즉, 각 클라이언트에 맞게 리소스를 응답하는 것은 불가능하다. 이를 해결하기 위해, 쿠키나 세션 또는 토큰 방식의 OAuth 및 JWT가 사용된다.
<br>
## Method
클라이언트가 서버에 요청방법을 정의하는 것으로 주어진 리소스에 수행하길 원하는 행동을 나타낸다.
* **GET** : 서버에게 조회할 리소스를 요청한다. (READ, 조회)
* **POST** : 서버에게 <u>본문(body)에 생성할 데이터를 삽입</u>하여 전송한다. (CREATE, 생성)
* **PUT** : 서버에게 <u>본문에 수정할 데이터를 삽입</u>하여 전송한다. (UPDATE, 수정)
* **DELETE** : 서버에게 삭제할 리소스를 요청한다. (DELETE, 삭제)
* **PATCH** : PUT과 비슷하지만 일부만 수정한다는 점에서 다르다.
<br>
## 응답 상태코드
서버가 클라이언트에게 요청을 받으면 응답상태에 따라서 다른 상태코드를 클라이언트에게 돌려준다.
* **1xx (요청에 대한 정보)** : 요청을 받았으면 작업을 계속한다.
* **2xx (성공)** : 요청을 성공적으로 수행했다.
* 200(성공), 201(새 리소스 작성), 202(요청 접수, 아직 처리는 안함)
* **3xx (리다이렉션)** : 클라이언트가 요청을 마지기 위해 추가적인 동작을 취해야 한다.
* 300(여러개의 응답, 선택해야 함), 301(영구이동, 요청한 페이지가 영구적으로 이동됨), 302(임시이동, 현재 응답잉 다른 페이지이긴 하지만 임시적임)
* **4xx (클라이언트 오류)** : 클라이언트에 오류가 있다.
* 401(권한 없음), 403(금지됨, 리소스에 대한 권한 없음), 404(찾을 수 없음, 서버에 없는 페이지)
* **5xx (서버 오류)** : 서버에 오류가 있다.
* 500(내부 서버오류), 501(요청수행 기능없음, 메서드 인식불가), 503(서비스 사용불가)
<br>
## 헤더
요청/응답 헤더 및 본문 헤더 등 다양한 속성들이 있지만 여기선 주요한 속성들만 명시한다.
### 요청 헤더
* Host : 서버의 도메인 이름과 TCP 포트번호 (표준 포트는 생략 가능)
* ```
Host: en.wikipedia.org:8080
```
* Content-Type : POST/PUT 메서드를 사용할 때 본문의 타입
* ```
Content-Type: application/x-www-form-urlencoded
```
* If-Modified-Since : 명시한 날짜 이후로 변경된 리소스만 획득
* ```
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
```
* Origin : 요청이 어느 도메인에서 왔는지 명시, 서버의 `Access-Control-*` 속성에 필요
* ```
Origin: http://www.example-social-network.com
```
* Cookie : 서버의 `Set-Cookie` 로 설정된 쿠키 값
* ```
Cookie: $Version=1; Skin=new;
```
### 응답 헤더
* Access-Control-* : CORS를 허용하기 위한 웹사이트 명시
* ```
Access-Control-Allow-Origin: *
```
* Set-Cookie : 클라이언트에 쿠키 설정
* ```
Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
```
* Last-Modified : 요청한 리소스가 마지막으로 변경된 시각
* ```
Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
```
* Location : 3xx 상태 코드일 때, 리다이렉션 되는 주소
* ```
Location: http://www.w3.org/pub/WWW/People.html
```
* Allow : 요청한 리소스에 대해 가능한 메서드들
* ```
Allow: GET, HEAD
```
<br>
## 참고
* [MDN, HTTP 요청 메서드](https://developer.mozilla.org/ko/docs/Web/HTTP/Methods)
* [위키백과, HTTP 상태 코드](https://ko.wikipedia.org/wiki/HTTP_상태_코드)
* [Wikipedia, List of HTTP header fields](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields)
* [🙈\[HTTP\] HTTP 특성(비연결성, 무상태)과 구성요소 그리고 Restful API🐵](https://victorydntmd.tistory.com/286)
* [[Network] HTTP 헤더의 종류 및 항목](https://gmlwjd9405.github.io/2019/01/28/http-header-types.html)
================================================
FILE: Notes/network/http1.1-2.md
================================================
# HTTP/1.1과 HTTP/2의 차이점
이제까지 전통적인 웹 브라우저와 웹 서버와의 통신 프로토콜은 HTTP/1.1 기준으로 동작했는데, 많은 문제점들과 개선할 부분들이 있었기 때문에 2015년에 HTTP/2가 등장하게 되었다.
<br>
## HTTP/1.1의 문제점
### HOLB(Head Of Line Blocking)
HTTP 요청을 할 때는 요청을 하고 나서 응답이 와야 다음 요청을 할 수 있었는데 HTTP/1.1에 들어오면서 파이프라이닝(Pipelining) 기법을 통해 응답을 받지 않고도 여러개의 요청을 연속적으로 할 수 있게 되었다. 하지만 이 또한 처음의 요청에 대한 응답이 오래 걸리는 경우, 그 다음 응답까지의 시간이 지연되는 현상이 발생한다. 이렇게 파이프라이닝 기법은 심각한 문제를 안고 있었으며 이를 Head of Line Blocking 문제라고 부른다.
### 무겁고 중복 많은 헤더 구조
요청을 할 때 요청헤더에 메타정보를 넣어서 보내게 되는데, 매 요청마다 보내는 정보가 많아져서 헤더가 무거워지고 쿠키 같은 경우는 계속 보내게 되기 때문에 중복도 많아지는 문제가 있다.
<br>
## HTTP/2가 나오기 전의 개선방법들
* CSS/JavaScript/이미지 압축
* Data URI 스키마(이미지를 이진 파일로 바꿔 HTML에 넣어놓는 기법)
* Image Sprite(여러개의 작은 이미지들을 1번의 요청으로 받아오는 기법)
* 도메인 샤딩(1개의 도메인을 여러개의 서브도메인으로 나눠서 병렬요청하는 기법)
* 스크립트 파일을 `</body>` 직전에 배치해서 HTML/CSS 파싱 중단 안되게 설정
<br>
## HTTP/2의 개선방법들
### 멀티플렉싱(Multiplexing)과 스트리밍(Streaming)
HTTP 요청 데이터는 헤더와 본문으로 구성되는데 이를 각각 프레임(Frame)이라는 단위로 지정하고 스트림(Stream)이라는 연결단위를 통해 헤더 프레임 혹은 본문 프레임을 보내도록 그 방식을 바꿨다. 하나의 스트림은 요청/응답으로 구성되고 여러개의 스트림을 생성할 수 있다. 바로 이것이 스트리밍을 통한 멀티플렉싱이다. 이를 통해 기존의 HTTP/1.1의 문제점인 HLOB를 해결할 수 있게 된다. 또한 요청한 리소스간의 우선순위를 설정하기 때문에 스트림 별로 가중치가 매겨지고 브라우저가 리소스들을 수신하는 순서를 적절하게 결정한다.
### 서버 푸시(Server Push)
브라우저가 요청하지 않으면 서버는 응답하지 않는 것이 보통이지만, 요청한 HTML 문서에 리소스가 포함되어 있는 경우 서버가 브라우저에게 밀어주는(push) 방식을 취하여 브라우저의 요청을 최소화시킨다.
### 헤더 압축(Header Compression)
헤더 테이블(Header Table)을 사용하여 이전 헤더 정보를 유지하고 허프만 인코딩 기법으로 헤더를 압축해서 전송하여 중복과 크기를 줄인다.
<br>
## 참고
* [MDN, HTTP/1.x의 커넥션 관리](https://developer.mozilla.org/ko/docs/Web/HTTP/Connection_management_in_HTTP_1.x)
* [Google, HTTP/2 소개](https://developers.google.com/web/fundamentals/performance/http2)
================================================
FILE: Notes/network/https.md
================================================
# HTTPS
<img src="../../images/network/https.png">
HTTPS(HyperText Transfer Protocol over TLS/SSL)는 **기존의 HTTP를 암호화한 프로토콜** 로 보안이 강화된 버전이다. 약어에서의 "S"가 원래 SSL(Secure Socket Layer)의 약자였지만 SSL 버전 3.1부터 TLS(Transport Layer Security)로 명칭이 바뀌고 TLS와 혼용하고 있다. TCP의 연결이 이루어진 후 TLS를 통해 암호화 설정이 되고 통신을 하는 방식이다.
<br>
## 필요한 개념
* **공개키(Public Key)와 비밀키(Private Key)** : 공개키는 모두가 볼 수 있는 키이며 비밀키는 소유자만이 가지고 있는 키로 암/복호화에 사용된다.
* **대칭키 암호화** : 서버와 클라이언트가 암호화/복호화에 동일한 비밀키를 사용하는 방식, 키를 공유하는데 어려움이 있으나 속도가 빠르다.
* **비대칭키 암호화** : 서버와 클라이언트가 암호화/복호화에 각각 다른 비밀키를 사용하는 방식, 공개키를 통해서 암호화를 하고 비밀키를 통해서 복호화를 한다. 공개키는 공개해도 상관없으니 키 관리에 어려움이 없으나, 속도가 느리다.
* **인증기관(Certificate Authority, CA)** : 클라이언트가 접속을 요청한 서버가 의도한 서버가 맞는지 인증해주는 역할을 하는 보증된 기업들이다. 클라이언트는 서버에 요청을 해서 CA가 발급한 인증서를 받은 뒤 CA의 공개키로 복호화하여 신뢰할 만한 인증서인지 검증한다. CA의 공개키로 복호화되는 암호화는 오직 CA의 비밀키로 암호화한 경우밖에 없기 때문에 복호화되면 신뢰할 만한 것이다.
<br>
## 동작방식
HTTPS는 **대칭키 암호화를 사용** 하며 다음과 같은 과정을 거친다.
1. 클라이언트가 서버에게 접속요청을 하면 서버는 CA에서 발급받은 인증서를 보낸다. 인증서에는 CA의 비밀키로 암호화된 사이트정보와 공개키가 들어있다.
2. 클라이언트는 인증서를 받아 CA의 공개키로 복호화하여 접속요청한 서버가 신뢰할만한지 검증한다.
3. 복호화가 되면 인증서가 신뢰할 만하기 때문에 데이터를 주고받을 대칭키를 생성한다.
4. 대칭키를 서버의 공개키로 암호화하여 서버에게 전송한다.
5. 서버는 자신의 비밀키로 클라이언트가 보낸 대칭키를 복호화한 뒤 그 대칭키를 통해 데이터를 주고받는다.
더 상세하게 들어가면 암호화 알고리즘, 난수 등 좀 더 복잡하지만 이런 과정을 알면 충분하다고 생각한다. [SSL.com의 영상](https://vimeo.com/135666049) 이 정말 알기쉽게 설명했기 때문에 정리하면서 이걸 보도록 하자.
<br>
## 참고
* [SSL 동작 방식을 간단히 알아보기](https://offbyone.tistory.com/274)
* [HTTPS와 SSL인증서](https://opentutorials.org/course/228/4894)
================================================
FILE: Notes/network/rest-api.md
================================================
# REST API
학술적으로 엄밀한 내용을 보고 싶다면 REST를 만든 [로이필딩의 논문](https://www.ics.uci.edu/~taylor/documents/2002-REST-TOIT.pdf) 을 보는 것이 좋다. 여기선 최대한 REST와 API가 무엇인지에 대해 체감하는 것을 목표로 한다.
## REST란 무엇인가?
REpresentational State Transfer의 약자로 전반적인 웹 어플리케이션에서 상호작용하는데 사용되는 웹 아키텍쳐 모델이다. 즉, 자원을 주고받는 **웹 상에서의 통신 체계에 있어서 범용적인 스타일을 규정한 아키텍쳐** 라고 할 수 있다.
## API란 무엇인가?
Application Programming Interface의 약자로 구글 맵 API, 카카오 비전 API 등 **기존에 있는 응용 프로그램을 통해서 데이터를 제공받거나 기능을 사용하고자 할 때 사용하는 인터페이스 및 규격** 을 말한다. API는 프로그래밍 언어, 운영체제 등에서도 사용되는 범용적인 용어이다. 따라서, REST API라는 것은 REST 원칙을 적용하여 서비스 API를 설계한 것을 말하며 대부분의 서비스가 REST API를 제공한다.
<br>
## REST의 특징들
### 균등한 인터페이스 (Uniform Interface)
REST가 HTTP의 표준만 따른다면 어떠한 기술이던지 접목하여 사용할 수 있기 때문에 플랫폼이나 언어의 제약에 구애받지 않는다. 요즘은 REST API를 정의할 때 JSON(JavaScript Object Notation) 방식을 가장 많이 사용하지만 XML(eXtensible Markup Language)도 적용할 수 있다.
### 무상태성 (Stateless)
서버는 클라이언트의 상황을 고려하지 않고 API 요청에 대해서만 처리하기 때문에 이를 **"상태가 없다"** 라고 표현한다. 이렇게 되면 클라이언트를 고려하지 않아도 되기 때문에 구현이 간결해진다.
### 캐싱 가능 (Cacheable)
REST는 HTTP 표준을 기반으로 만들어졌기 때문에 HTTP의 특징인 캐싱을 사용할 수 있다. REST API를 활용하여 `GET` 메소드를 `Last-Modified` 값과 함께 보낼 경우, 컨텐츠의 변화가 없을 때 캐시된 값을 사용하게 된다. 이렇게 되면 네트워크 응답시간 뿐만 아니라 API 서버에 요청을 발생시키지 않기 때문에 부담이 덜 하다는 장점 또한 가지게 된다.
### 자체 표현성 (Self-Descriptiveness)
REST API의 자원명시 규칙 및 메소드는 그 자체로 의미를 지니기 때문에 어떠한 요청에 있어서 그 요청 자체로 어떤 것을 표현하는지 알아보기 쉽다. 물론 API를 규정한 각 서비스들이 문서를 제공하지만 이 특성에 따라서 요청하는 방식만으로 어떠한 의미인지 알 수 있어야 좋은 REST API라고 할 수 있다.
### 클라이언트-서버 구조 (Client-Server Architecture)
REST 서버가 API를 제공하는 방식이기 때문에 클라이언트에서 처리하는 부분과 독립적으로 동작한다. 따라서, 서로간의 의존성이 줄어들고 클라이언트와 서버를 최대한 독립적으로 개발할 수 있도록 도와준다.
### 계층형 구조 (Layered System)
클라이언트는 계층형 구조가 불가능하지만 REST 서버의 경우, 보안/로드 밸런싱/암호화 등을 추가할 수 있고 Proxy 및 게이트웨이 등의 중간매체를 사용할 수 있다.
<br>
## REST API의 핵심
### URI는 리소스를 표현해야 한다.
* **리소스 명은 동사가 아닌 명사를 사용해야 한다.**
```
/students/1
```
* **리소스는 Collection과 Document로 표현할 수 있다.**
이 때 Collection은 **복수** 를 사용함을 주의하자.
```
/locations/seoul/schools/3
```
여기서 `locations` 는 Collection을, `seoul` 은 Document를 표현한다.
<br>
### 그 리소스에 대한 행위는 HTTP의 Method로 표현해야 한다.
* **GET은 리소스를 조회한다. (학생 목록 조회)**
```
GET /students
```
* **POST는 리소스를 생성한다. (학생 생성)**
```
POST /students
```
* **PUT은 리소스를 업데이트한다. (1번 학생 정보 업데이트)**
```
PUT /students/1
```
* **DELETE는 리소스를 삭제한다. (1번 학생 삭제)**
```
DELETE /students/1
```
<br>
## HTTP 상태코드
요청에 대한 응답의 상태코드 또한 명확하게 돌려주는 것이 잘 설계된 REST API이다.
* **2xx** : 성공 관련 (200 Ok, 201 Created)
* **3xx** : 리다이렉션 관련 (304 Not Modified)
* **4xx** : 클라이언트 에러 관련 (400 Bad Request, 401 Unauthorized)
* **5xx** : 서버 에러 관련 (500 Internal Server Error)
<br>
## 잘못된 REST 사용
* **GET/POST의 부적합한 사용** : 기존의 조회/생성의 기능이 아닌 다른 방식으로 사용하는 경우이다.
* **자체 표현적이지 않음** : REST의 특징 중 하나인 자체표현성에서 떨어지는 경우로 이해하기 어렵다.
* **HTTP 응답 코드 미사용** : 위에서 정리한 응답에 관한 상태코드를 명확하게 정의하지 않은 경우이다.
* 그 외에 리소스 표현 가이드 및 REST의 특징을 위반한 경우들을 주의하자.
<br>
마지막으로 아래 그림을 보고 정리해보자.
<img src="../../images/network/REST.png">
<br>
## 참고
* [REST API concepts and examples(유튜브)](https://www.youtube.com/watch?v=7YcW25PHnAA)
* [REST API가 뭔가요?(유튜브)](https://www.youtube.com/watch?v=iOueE9AXDQQ)
* [REST API 제대로 알고 사용하기](https://meetup.toast.com/posts/92)
* [REST API의 이해와 설계-#1 개념 소개](https://bcho.tistory.com/953)
* [REST 아키텍처를 훌륭하게 적용하기 위한 몇 가지 디자인 팁](https://spoqa.github.io/2012/02/27/rest-introduction.html)
* [Why Should We Choose REST (Client-Server) Model to Develop Web Apps ?](https://medium.com/@audira98/why-should-we-choose-rest-client-server-model-to-develop-web-apps-c3bb2451b13a)
================================================
FILE: Notes/network/tcp-udp.md
================================================
# TCP와 UDP
OSI 7계층에서 전송계층(Transport layer)에 속하는 데이터 전송 프로토콜이다. 여기선 중요한 것만 살펴보고 깊게는 들어가지 않는다.
## TCP (Transmission Control Protocol)
데이터가 반드시 전달되는 것을 보장하는 프로토콜로 다음 특징들을 갖는다.
* **연결지향(Connection-oriented)** 으로 2개의 호스트가 통신을 하기 전 연결이 이루어져야 한다.
* **높은 신뢰성(Reliability)** 과 **순서대로 전송하는 것(In-order delivery)** 을 보장한다.
* **흐름 제어(Flow control)** 를 통해 송신자의 데이터 양을 조절한다.
* **혼잡 제어(Congestion control)** 를 통해 네트워크 상황을 감지하고 송신자의 데이터 양을 조절한다.
* **에러 감지(Error detection)** 를 통해 잘못 전송되었을 경우 재전송한다.
* **전 이중(Full duplex) 방식** 으로 두 호스트 모두 송신자와 수신자가 될 수 있다.
* **바이트 스트림(Byte stream)** 을 사용하여 데이터를 연속적인 바이트로 보고, **세그먼트(Segment)** 라는 단위의 패킷으로 쪼개서 보낸다.
* HTTP, FTP, SMTP, TELNET 등에서 사용된다.
### 3-way handshaking
TCP가 호스트 간에 연결을 설정하는 방법으로 SYN/ACK 패킷을 통해 이루어진다. SYN 패킷은 동기화(SYNchronize)를 의미하는 패킷이며 ACK 패킷은 확인(ACKnowledgement)을 의미하는 패킷이다.
<img src="../../images/network/3-way-handshake.png">
* **LISTEN** : 서버가 클라이언트의 연결요청을 기다리고 있다.
* **SYN_SENT** : 클라이언트가 능동적으로 서버에게 연결요청을 하자고 시퀀스 번호를 생성하여 SYN 패킷에 담아 보낸다. (능동 개방)
* **SYN_RECEIVED** : SYN 패킷을 받은 서버는 자신만의 시퀀스 번호를 생성하여 SYN 패킷에 담고 클라이언트의 SYN 패킷에 있는 시퀀스 번호에 1을 더해서 ACK 패킷에 담아 같이 보낸다.
* **클라이언트 ESTABLISHED** : SYN+ACK 패킷을 받은 클라이언트는 ACK 패킷의 시퀀스 번호를 보고 자신이 보낸 시퀀스 번호와 차이가 1임을 확인한다. 차이가 1이라면 제대로 연결되었다고 판단하고 서버의 SYN 패킷에 있는 시퀀스 번호에 1을 더해 ACK 패킷에 담아 보낸다.
* **서버 ESTABLISHED** : 클라이언트의 ACK 패킷을 받고 그 안의 시퀀스 번호가 보냈던 SYN 패킷의 시퀀스 번호 + 1이라면 연결이 되었다고 판단한다. 이후부터 본격적인 통신을 할 수 있게 된다.
<br>
## UDP (User Datagram Protocol)
TCP와 달리 데이터의 신뢰성을 보장하지 않는 프로토콜이며 다음 특징들을 갖는다.
* **비연결형(Connection-less)** 으로 연결을 설정하고 해제하는 과정이 없다.
* **신뢰성이 없고** 전송되는 **데이터의 순서를 보장하지 않는다.**
* 흐름제어, 혼잡제어가 없다.
* 에러감지는 헤더의 체크섬(Checksum)을 이용한 정도밖에 없다.
* 패킷의 단위가 **데이터그램(Datagram)** 으로 **경계가 분명** 하여 수신자는 송신자가 보낸 그대로의 크기로 받게 된다.
* 서버와 클라이언트는 유니캐스트(1:1), 브로드캐스트(1:N), 멀티캐스트(1:M)가 가능하다. (N은 전체, M은 일부)
* TCP에 비해서 하는 작업들이 굉장히 적기 때문에 **속도가 빠르다.**
* DNS, DHCP, 비디오/오디오 스트리밍 등에 사용된다.
<br>
## 참고
* [TCP/UDP\] TCP와 UDP의 특징과 차이](https://mangkyu.tistory.com/15)
* [TCP가 연결을 생성하고 종료하는 방법, 핸드쉐이크](https://evan-moon.github.io/2019/11/17/tcp-handshake/)
* [RFC793, TCP Specification](https://tools.ietf.org/html/rfc793#section-3.4)
* [정보통신기술용어해설, UDP](http://www.ktword.co.kr/abbr_view.php?m_temp1=323)
* [정보통신기술용어해설, TCP](http://www.ktword.co.kr/abbr_view.php?nav=2&choice=map&id=428&m_temp1=347)
* [Wikipedia, UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol)
* [Difference between TCP and UDP?](https://stackoverflow.com/questions/5970383/difference-between-tcp-and-udp)
================================================
FILE: Notes/network/type-url-process.md
================================================
# URL을 입력하고 벌어지는 일
* URL을 웹 브라우저의 주소창에 입력한다.
* 웹 브라우저가 URL을 해석하고, 문법에 맞지 않으면 기본 검색엔진으로 검색한다.
* 문법에 맞으면 URL의 호스트 부분을 인코딩한다.
* HSTS(HTTP Strict Transport Security) 목록을 확인하고 있으면 HTTPS로, 없으면 HTTP로 요청한다.
* DNS(Domain Name Server) 조회
* 브라우저/로컬 캐시 확인해서 도메인에 해당하는 IP가 있는지 확인한다.
* 없으면 OS에게 DNS 서버에 요청하라고 지시한다.
* DNS 서버는 해당 도메인에 해당하는 IP를 돌려준다.
* TCP 소켓을 열고 3-way handshake로 연결을 설정한다.
* HTTPS 요청이라면 TLS(Transport Layer Security) handshake 과정을 통해 세션키를 생성한다.
* 세션이 유지되는 동안 서버에게 요청하고 응답을 받는 과정을 반복한다.
* 응답 상태코드에 따라 다르게 처리한다.
* 응답을 디코딩(Decoding)하고 캐싱 가능하다면 캐싱한다.
* 웹브라우저는 응답받은 HTML/CSS/JS 및 이미지,폰트 등의 리소스를 사용하여 렌더링 한다.
* 서버와의 세션이 종료되면 4-way handshake로 연결을 종료한다.
<br>
## 참고
* [Github, what-happens-when-KR](https://github.com/SantonyChoi/what-happens-when-KR)
* [Stackoverflow, what happens when you type in a URL in browser](https://stackoverflow.com/questions/2092527/what-happens-when-you-type-in-a-url-in-browser)
================================================
FILE: Notes/network/uri.md
================================================
# URL과 URN을 포함하는 URI
## URI(Uniform Resource Identifier)
통합 자원 식별자라는 의미로 **인터넷 상의 리소스** 를 고유하게 식별할 수 있는 식별자이다. URI에는 위치를 알려주는 **URL(Uniform Resource Locator)** 와 전 세계를 통틀어 고유한 이름을 의미하는 **URN(Uniform Resource Name)** 이 존재한다.
<img src="../../images/network/URI.png" width="400px">
<br>
## URL(Uniform Resource Locator)
**해당 위치에서 어떻게 리소스를 얻어낼 것인가에 대한 정보를 포함한다.**
현재 내가 거주하고 있는 기숙사를 대학교라고 가정한다면, 그 주소는 다음과 같이 쓸 수 있다.
> 경북 포항시 북구 흥해읍 한동로 558, 한동대학교 벧엘관 303호
여기서 이 방에 **나 혼자 산다면** 나라는 자원에 대한 유일한 지시자가 된다. 또한 이는 내가 거주하고 있다는 것을 간접적으로 알려주기 때문에 식별의 역할도 하고 있다. 그러나 룸메이트가 오게 되면 나라는 자원을 유일하게 지시하는 기준은 달라지게 된다. 따라서, 자원의 위치가 바뀔 수 있다고 할 수 있는 것이다. 이러한 문제점은 URN의 출현을 야기시켰다.
<br>
## URN(Uniform Resource Name)
**리소스를 유일하고 영구적인 이름으로 식별하지만 인터넷 상의 위치는 알려주지 않는다.**
만약, 지구상에 "배하람" 이라는 이름이 유일하다면 URN의 조건에 부합하게 된다. 즉, 매번 바뀌는 위치가 아닌 **유일한 식별자인 이름을 기준** 으로 자원을 식별하겠다는 의도이다.
<br>
## 사용 예시
* **URL**
* http://example.com/mypage.html (프로토콜: http)
* ftp://example.com/download.zip (프로토콜: ftp)
* mailto:user@example.com (프로토콜: mailto)
* **URN**
* urn:isbn:0451450523 (책을 식별하는 ISBN 번호)
* urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66 (전 세계에서 유일한 번호)
<br>
## 참고
* [URI vs URL vs URN :: 마이구미](https://mygumi.tistory.com/139)
* [URI](https://johngrib.github.io/wiki/URI/)
* [What is the difference between a URI, a URL and a URN?](https://stackoverflow.com/a/1984225/11789111)
================================================
FILE: Notes/security/sop.md
================================================
# 동일 출처 정책 (Same-Origin Policy)
어떠한 문서나 스크립트가 다른 **프로토콜 / 포트 / 호스트** 에 있는 리소스 사용하는 것을 제한하는 정책. 예를 들어, 다음과 같은 사이트에서 리소스를 다른 곳으로 요청한다고 하자.
```
http://website.com/ex/ex.html
```
| 리소스 요청 | 허용여부 |
| :------------------------------: | :-----------------: |
| http://website.com/ex/ | 성공 |
| http://website.com/ex1/ | 성공 |
| http://website.com:81/ex/ex.html | 실패, 포트가 다름 |
| http://wwebsite.com/ex/ | 실패, 호스트가 다름 |
| https://website.com/ex/ex.html | 실패, 프로토콜 다름 |
위와 같이 호스트, 포트, 프로토콜 중 하나라도 다르면 동일 출처 정책이 적용되서 요청에 실패한다.
<br>
## 해결방법
### `document.domain`
단편적인 방법으로, 동일한 도메인으로 설정함을 통해 SOP 정책을 피할 수 있다. 만약, 현재 도메인이`http://store.company.com/index.html` 이라면,
```javascript
document.domain = "company.com";
```
과 같이 설정해서 `http://company.com/index.html` 에 요청을 보낼 수 있다. 단, 2개의 html 파일에 관련된 스크립트 파일에 모두 위와 같이 설정해줘야 하며 파이어폭스에서는 안된다는 제약사항이 있다. 또한 서버-클라이언트 통신에 쓰이는 방법이 아니라 **클라이언트 상에서 출처가 다른 프레임(frame)들에 대해 쓰인다.** 따라서, 이 방법으로 서버와 통신할 수는 없다.
### CORS(Cross-Origin Resource Sharing)
HTTP 헤더를 사용하여 클라이언트와 서버로 하여금 서로에 대해 인지하고 한 출처에서 다른 출처의 자원을 사용할 수 있게 하는 메커니즘이다. 클라이언트가 서버에 HTTP 요청을 보낼 때 HTTP 헤더의 `Origin` 속성에 자동으로 값이 할당된다.
```
Origin: http://company.com
```
이 도메인에서 다른 출처의 자원을 사용하기 위해 ajax 요청을 했다고 하면 SOP 정책 때문에 에러가 발생한다. 따라서 이를 해결하기 위해, 서버의 HTTP 응답 헤더에 다음과 같이 요청을 허용하는 도메인을 명시한다.
```
Access-Control-Allow-Origin: http://company.com
```
### `window.postMessage`
이것 또한 프레임에서 사용하는 개념으로, 페이지에서 프레임으로 문자열 값을 보낼 수 있고 받는 프레임에선 이벤트 핸들러를 통해서 받을 수 있다. 그렇게 중요한 방법은 아니기 때문에 더 자세한 내용은 [MDN 공식문서](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) 를 참고하도록 하자.
### 프록시 서버
프록시 서버는 클라이언트와 서버 사이에서 정보교환을 도와주는 서버이다. 리소스를 요청하고자 하는 서버의 `Access-Control-Allow-Origin` 속성을 수정할 수 없는 경우에 굉장히 유용하다. 프록시 서버가 실제 서버에 요청을 보내서 받아온 다음 그걸 `Access-Control-Allow-Origin` 설정을 적절히 하여 클라이언트에게 돌려주는 방법이다.
Apache나 Nginx와 같은 웹서버에서 프록시 기능을 활성화할 수 있고 CRA(Create-React-App)를 사용하고 있다면 `package.json` 의 `proxy ` 값을 설정하여 프록시 서버 기능을 활성화할 수 있다. 단, 이 방법의 경우 서버를 한단계 더 거치기 때문에 기존의 요청보다 느리다는 단점이 있다.
### JSONP(JSON with Padding)
CORS가 나오기 이전에 사용하던 방식으로, `<script>` 태그를 사용하면 SOP 정책을 피할 수 있기 때문에 JSON 데이터를 받아올 때 태그를 사용해서 받아올 수 있다.
```html
<script src="http://company.com/example.json"></script>
```
하지만 JSON 데이터의 포맷이
```json
{
name: 'john',
age: 19
}
```
위와 같이 생겼기 때문에 다음과 같이 삽입된다.
```html
<script>
{ name: 'john', age: 19 }
</script>
```
이는 자바스크립트의 문법에 맞지 않고 애초에 요청을 한 이유가 데이터를 가공하기 위함이기 때문에 이걸 가공하는 콜백함수를 넘기는 방식이 바로 JSONP이다. 즉, 받은 JSON 데이터를 파라미터로 콜백함수에 넘겨서 실행하는 방식이다.
```html
<script src="http://company.com/example.json?callback=callbackFunction"></script>
```
위와 같이 넘기며, 결국 태그에는 아래와 같이 나타난다.
```html
<script>callbackFunction(데이터)</script>
```
최신 브라우저에서는 거의 사용 안하고 오래된 브라우저에서 사용하는데 보안문제가 있어서 CORS를 권장한다.
<br>
## 참고
* [document.domain이 하는 역할이 뭔가요](https://oybso.tistory.com/entry/documentdomain이-하는-역할이-뭔가요)
* [Velog, CORS: Real examples](https://velog.io/@leejh3224/CORS-Real-examples-8yjnloovl5)
* [Velog, CORS에 대한 간단한 고찰](https://velog.io/@wlsdud2194/cors)
* [Stackoverflow, Ways to circumvent the same-origin policy](https://stackoverflow.com/questions/3076414/ways-to-circumvent-the-same-origin-policy)
* [Stackoverflow, Why doesn't setting document.domain work to allow AJAX requests to a parent domain?](https://stackoverflow.com/questions/15563611/why-doesnt-setting-document-domain-work-to-allow-ajax-requests-to-a-parent-doma)
* [Stackoverflow, What is JSONP, and why was it created?](https://stackoverflow.com/questions/2067472/what-is-jsonp-and-why-was-it-created)
* [위키백과, 동일-출처 정책](https://ko.wikipedia.org/wiki/동일-출처_정책)
* [MDN, 교차 출처 리소스 공유 (CORS)](https://developer.mozilla.org/ko/docs/Web/HTTP/CORS)
================================================
FILE: Notes/security/xss-csrf.md
================================================
# XSS와 CSRF
## XSS(Cross Site Scripting, 사이트간 스크립팅)
**웹사이트 관리자가 아닌 사람이 웹사이트에 악성 스크립트를 삽입할 수 있는 취약점을 이용한 공격기법이다.** 사용자로부터 받은 입력을 제대로 검증하지 않을 때 나타나며 사용자의 정보를 탈취하거나 비정상적인 기능을 실행할 수 있다.
* **저장 XSS** : 웹사이트에 취약점이 있는 웹 서버에 스크립트를 저장시켜서 해당 웹사이트를 요청하는 사용자로 하여금 스크립트를 실행하게 하는 기법이다.
* **반사 XSS** : 검색을 사용할 때 결과가 없으면 브라우저에서 입력한 값을 문서에 포함하여 응답하는데 이를 사용하여 스크립트를 실행하는 기법으로 악성 URL을 배포하여 클릭하도록 유도하는 방법을 사용한다.
* **DOM 기반 XSS** : 공격 스크립트가 DOM 생성의 일부로 실행되면서 공격하는 기법으로 반사 XSS와 마찬가지로 악성 URL을 배포하여 클릭하도록 유도한다.
XSS 를 사용해서 사용자의 쿠키 정보 및 세션 ID를 획득할 수 있으며 시스템 관리자 권한을 획득할 수도 있다. 대응방안은 아래와 같다.
* **입/출력 값 검증 및 무효화** : 스크립트를 실행할 때는 기본적으로 `<script>` 태그를 사용하니 `<` 를 `<` 로 바꾼다거나 하는 방법으로 무효화시킬 수 있다.
* **보안 라이브러리 사용** : 입/출력이 스크립트를 실행하는지에 대한 필터를 구현한 기존 라이브러리를 사용할 수 있다.
<br>
## CSRF(Cross Site Request Forgery, 사이트간 요청변조)
**사용자가 의도치 않게 공격자가 의도한 행동을 하여 취약점을 노출시키거나 수정/삭제/생성 등을 하게 만드는 공격 기법이다.** 이메일을 열어보거나 악성 사이트에 접근했을 때 특정한 요청을 하는 CSRF 스크립트를 실행하는 방식이다. 다음과 같은 시나리오가 있을 수 있다.
* `www.mybank.com` 에 접속해 있는 상태이다.
* 이 사이트에서 돈을 보낼 때 `http://www.mybank.com/transfer?to=<계좌번호>&amount=<액수>` 형식으로 보낸다고 하자.
* `www.cute-cat.org` 사이트에 접속한다. (악성 사이트이다)
* 해당 사이트의 관리자가 위에서 말한 돈을 보내는 URL과 쿼리 방식을 알고 있다면 그 요청을 실행하는 CSRF 스크립트를 사이트에 넣을 수 있다.
* 사이트에 접속하면 해당 스크립트를 실행하게 되고 `www.mybank.com` 에 요청이 가게 되서 돈을 보내게 된다.
이렇게 사용자가 의도하지 않은 요청을 실행함으로 피해를 줄 수 있는 기법이다. 대응방안은 아래와 같다.
* **`referrer` 검증** : 요청 헤더에 있는 `referrer` 속성을 검증하여 신뢰할 수 있는 도메인에서 들어오는 요청인지 검증한다.
* **CSRF 토큰** : 난수(Random Number)를 서버쪽 사용자의 세션에 저장하고 요청할 때 난수를 CSRF 토큰으로 지정하여 사용자게 전송한다. 이후 요청부터 토큰이 일치하는지 확인하여 검증한다.
* **캡챠(Captcha) 사용** : 사용자와의 상호작용을 통해서 숫자/문자를 입력하여 검증한다.
<br>
## 참고
* [KISA, 크로스 사이트 스크립팅(XSS) 공격 종류 및 대응 방법](https://www.kisa.or.kr/uploadfile/201312/201312161355109566.pdf)
* [Stackoverflow, Difference between XSS and CSRF?](https://security.stackexchange.com/questions/138987/difference-between-xss-and-csrf)
* [Stackoverflow, What is a CSRF token ? What is its importance and how does it work?](https://stackoverflow.com/questions/5207160/what-is-a-csrf-token-what-is-its-importance-and-how-does-it-work)
* [[보안] CSRF(Cross Site Request Forgery)란 무엇인가?](https://sj602.github.io/2018/07/14/what-is-CSRF/)
================================================
FILE: README.md
================================================
# 취준생이 반드시 알아야 할 프론트엔드 지식들
## 목차
* [소개](#tada-소개)
* [프론트엔드 전반](#computer-프론트엔드-전반)
* [HTML](#page_with_curl-html)
* [CSS](#lipstick-css)
* [Javascript](#fire-javascript)
* [네트워크](#chart_with_upwards_trend-네트워크)
* [보안](#lock-보안)
<br>
## :tada: 소개
취업 전 반드시 알아야 한다고 생각하는 프론트엔드 분야의 기초지식들을 모아놓았습니다. 실제 면접질문들과 구글링을 통해 검색한 필수지식 및 질문들을 통해서 하나하나 정리했습니다.
* 기초지식을 너무 얕게 혹은 너무 깊게 말고 **적당한 선으로 정리** 했습니다.
* 컴퓨터공학의 전반적인 것이 아닌 오직 **프론트엔드 쪽만 정리** 했습니다.
* 개인적으로 정리한 내용이라 **틀린 부분이 있을 수 있으니** 언제든지 PR과 이슈를 날려주세요.
<br>
## :computer: 프론트엔드 전반
* [CSR (Client Side Rendering) vs SSR(Server Side Rendering)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/frontend/csr-ssr.md)
* [브라우저의 렌더링 과정](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/frontend/browser-rendering.md)
* [자바스크립트 엔진이 코드를 실행하는 과정](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/frontend/engine.md)
* [BOM과 DOM](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/frontend/bom-dom.md)
* [모듈 번들러와 트랜스파일러](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/frontend/bundler-transpiler.md)
* [CI와 CD](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/frontend/ci-cd.md)
* [CSS와 JS 애니메이션의 차이점](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/frontend/css-js-animation.md)
<br>
## :page_with_curl: HTML
* [DOCTYPE](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/html/doctype.md)
* [표준모드와 호환모드](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/html/standard-quirks.md)
* [data- 속성](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/html/data.md)
* [local storage vs session storage vs cookie](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/html/web-storage-api.md)
* [script vs script async vs script defer](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/html/script-tag-type.md)
* [시맨틱 마크업](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/html/semantic.md)
<br>
## :lipstick: CSS
* [박스 모델 (Box Model)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/box-model.md)
* [float를 해제하는 방법들](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/float-clear.md)
* [마진겹침 현상](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/margin-collapsing.md)
* [BFC (Block Formatting Context)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/bfc.md)
* [z-index의 동작방식](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/z-index.md)
* [block vs inline vs inline-block](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/block-inline-inline-block.md)
* [가로/세로 가운데 정렬하기](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/center.md)
* [Reset.css vs Normalize.css](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/reset-normalize.md)
* [그리드 시스템](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/grid.md)
* [img 아래쪽 공백 제거](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/css/img-space.md)
<br>
## :fire: Javascript
* [Ajax](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/ajax.md)
* [이벤트 위임 (Event Delegation)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/event-delegation.md)
* [실행 컨텍스트 (Execution Context)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/execution-context.md)
* [스코프 (Scope)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/scope.md)
* [호이스팅 (Hoisting)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/hoisting.md)
* [클로저 (Closure)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/closure.md)
* [네이티브 객체 vs 호스트 객체](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/native-host.md)
* [this의 바인딩](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/this.md)
* [var vs let vs const](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/var-let-const.md)
* [IIFE (Immediately-Invoked Function Expression)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/iife.md)
* [모듈 시스템: CommonJS, AMD, UMD, ES6](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/module.md)
* [콜 스택(Call stack)과 힙(Heap)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/stack-heap.md)
* [이벤트 루프 (Event loop)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/event-loop.md)
* [프로토타입 (Prototype)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/prototype.md)
* [== vs ===](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/identity-equal.md)
* [엄격 모드 (Strict mode)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/strict-mode.md)
* [new의 동작방식](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/new.md)
* [ES6 (2015) 의 특징들](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/es6.md)
* [ES7 (ES2016) ~ ES8 (ES2017) 의 특징들](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/es7-es8.md)
* [ES9 (ES2018) ~ ES10 (ES2019) 의 특징들](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/es9-es10.md)
* [ES11 (ES2020) 의 특징들](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/es11.md)
<br>
## :chart_with_upwards_trend: 네트워크
* [TCP와 UDP](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/tcp-udp.md)
* [HTTP](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/http.md)
* [HTTPS](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/https.md)
* [HTTP/1.1 vs HTTP/2](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/http1.1-2.md)
* [URL과 URN을 포함하는 URI](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/uri.md)
* [REST API](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/rest-api.md)
* [Cookie vs Session](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/cookie-session.md)
* [URL을 입력하고 벌어지는 일](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/type-url-process.md)
* [CDN](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/network/cdn.md)
<br>
## :lock: 보안
* [동일 출처 정책 (Same Origin Policy)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/security/sop.md)
* [XSS와 CSRF](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/security/xss-csrf.md)
gitextract_qcdtrx2_/ ├── .github/ │ └── PULL_REQUEST_TEMPLATE.md ├── Notes/ │ ├── css/ │ │ ├── bfc.md │ │ ├── block-inline-inline-block.md │ │ ├── box-model.md │ │ ├── center.md │ │ ├── float-clear.md │ │ ├── grid.md │ │ ├── img-space.md │ │ ├── margin-collapsing.md │ │ ├── reset-normalize.md │ │ └── z-index.md │ ├── frontend/ │ │ ├── bom-dom.md │ │ ├── browser-rendering.md │ │ ├── bundler-transpiler.md │ │ ├── ci-cd.md │ │ ├── csr-ssr.md │ │ ├── css-js-animation.md │ │ └── engine.md │ ├── html/ │ │ ├── data.md │ │ ├── doctype.md │ │ ├── script-tag-type.md │ │ ├── semantic.md │ │ ├── standard-quirks.md │ │ └── web-storage-api.md │ ├── javascript/ │ │ ├── ajax.md │ │ ├── closure.md │ │ ├── es11.md │ │ ├── es6.md │ │ ├── es7-es8.md │ │ ├── es9-es10.md │ │ ├── event-delegation.md │ │ ├── event-loop.md │ │ ├── execution-context.md │ │ ├── hoisting.md │ │ ├── identity-equal.md │ │ ├── iife.md │ │ ├── module.md │ │ ├── native-host.md │ │ ├── new.md │ │ ├── prototype.md │ │ ├── scope.md │ │ ├── stack-heap.md │ │ ├── strict-mode.md │ │ ├── this.md │ │ └── var-let-const.md │ ├── network/ │ │ ├── cdn.md │ │ ├── cookie-session.md │ │ ├── http.md │ │ ├── http1.1-2.md │ │ ├── https.md │ │ ├── rest-api.md │ │ ├── tcp-udp.md │ │ ├── type-url-process.md │ │ └── uri.md │ └── security/ │ ├── sop.md │ └── xss-csrf.md └── README.md
Condensed preview — 57 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (131K chars).
[
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 69,
"preview": "## 무엇이 잘못되었나요?\n\n\n\n## 어떻게 해결하셨나요?\n\n\n\n## 리뷰어들이 주의깊게 봤으면 하는 부분이 있으신가요?\n\n"
},
{
"path": "Notes/css/bfc.md",
"chars": 2246,
"preview": "# Block Formatting Context\n\nMDN의 정의를 보면,\n\n> *BFC는 웹페이지의 블록 레벨 요소를 렌더링하는데 사용되는 CSS의 비주얼 서식 모델 중 하나이다.*\n\n즉, 블록 레벨 요소가 포함되는"
},
{
"path": "Notes/css/block-inline-inline-block.md",
"chars": 1090,
"preview": "# block vs inline vs inline-block\n\n| 특징 | block | inline | inline-block"
},
{
"path": "Notes/css/box-model.md",
"chars": 1021,
"preview": "# Box Model\n\n<p align=\"center\">\n\t<img src=\"../../images/css/box model.png\"> \n</p>\n\n문서상의 요소들을 시각적인 목적을 위해서, 모든 요소를 하나의 \""
},
{
"path": "Notes/css/center.md",
"chars": 2420,
"preview": "# 가로/세로 가운데 정렬하기\n\n## div의 가운데 정렬\n\n```html\n<div class=\"position-margin\"></div>\n<div class=\"position-transform\"></div>\n<di"
},
{
"path": "Notes/css/float-clear.md",
"chars": 1092,
"preview": "# float를 해제하는 방법들\n\nfloat 속성을 자식 엘리먼트에 사용하게 되면 부모 엘리먼트가 자식의 높이를 감지할 수 없기 때문에 이를 반영하기 위한 방법이 필요하다. 다음 코드를 가정으로 한다.\n\n```htm"
},
{
"path": "Notes/css/grid.md",
"chars": 4009,
"preview": "# 그리드 시스템\n\n그리드 레이아웃을 구현하기 위해 설계한 시스템으로 너비 960px 혹은 1200px 기준으로 정해놓은 시스템들이 있다. 열(Column)의 개수에 따라 12단/16단/24단 그리드라고 부르기도 한"
},
{
"path": "Notes/css/img-space.md",
"chars": 1420,
"preview": "# img 아래쪽 공백 제거\n\n## img의 공백\n\n`<img>` 태그를 사용할 때 기본적으로 아래쪽에 공백이 생긴다.\n\n```html\n<div class=\"container\">\n <img src=\"https://"
},
{
"path": "Notes/css/margin-collapsing.md",
"chars": 2519,
"preview": "# 마진겹침 현상\n\n마진겹침(Margin-Collpasing)이란 블록 레벨 엘리먼트(Block-level element)에 한해서 발생하는 현상으로, 좌우 방향으로는 적용되지 않고 **오로지 수직방향** 으로 적용"
},
{
"path": "Notes/css/reset-normalize.md",
"chars": 1617,
"preview": "# Reset.css vs Normalize.css\n\n크롬, 사파리, IE 등 각 브라우저마다 HTML 요소의 기본 스타일을 가지고 있다. 따라서, CSS로 스타일링을 적용할 때 이러한 특징이 동일한 스타일 적용을 "
},
{
"path": "Notes/css/z-index.md",
"chars": 2592,
"preview": "# z-index의 동작방식\n\n## z-index와 쌓임 맥락\n\nz-index를 이해하기 위해선 먼저, 쌓임 맥락(Stacking Context)의 개념을 이해해야 한다. **쌓임 맥락이란, HTML 요소들에 사용자"
},
{
"path": "Notes/frontend/bom-dom.md",
"chars": 1421,
"preview": "# BOM과 DOM\n\n## BOM (Browser Object Model)\n\n**브라우저의 창이나 프레임을 프로그래밍적으로 제어할 수 있게 해주는 객체모델** 이다. 이를 통해서 브라우저의 새 창을 열거나 다른 문서"
},
{
"path": "Notes/frontend/browser-rendering.md",
"chars": 2093,
"preview": "# 브라우저의 렌더링 원리\n\n브라우저가 화면에 나타나는 요소를 렌더링 할 때, 웹킷(Webkit)이나 게코(Gecko) 등과 같은 **렌더링 엔진** 을 사용한다. 렌더링 엔진이 HTML, CSS, Javascrip"
},
{
"path": "Notes/frontend/bundler-transpiler.md",
"chars": 1175,
"preview": "# 모듈 번들러와 트랜스파일러\n\n## 모듈 번들러\n\n> 모듈의 개념을 모른다면 이 문서의 [모듈시스템](https://github.com/baeharam/Must-Know-About-Frontend/blob/mast"
},
{
"path": "Notes/frontend/ci-cd.md",
"chars": 1073,
"preview": "# CI와 CD\n\n## CI (Continuous Integration, 지속적 통합)\n\nCI는 빌드와 테스트를 자동화해서 공유 저장소에 병합시키는 프로세스를 뜻한다. git과 같은 버전관리 시스템을 사용할 때 여러"
},
{
"path": "Notes/frontend/csr-ssr.md",
"chars": 2351,
"preview": "# CSR(Client Side Rendering)과 SSR(Server Side Rendering)\n\n## SPA와 MPA\n\n* **SPA (Single Page Application)**\n\n하나의 HTML 파일을"
},
{
"path": "Notes/frontend/css-js-animation.md",
"chars": 2070,
"preview": "# CSS 애니메이션 vs JS 애니메이션\n\n웹사이트에 애니메이션 효과를 부여할 때 CSS의 `transition` / `animation` 속성을 사용할 수 있고 JS의 `setInterval()` / `reque"
},
{
"path": "Notes/frontend/engine.md",
"chars": 902,
"preview": "# 자바스크립트 엔진이 코드를 실행하는 과정\n\n자바스크립트를 실행하기 위해선 자바스크립트 엔진이 필요하고 웹 브라우저는 자바스크립트 엔진을 내장하고 있다. 브라우저마다 엔진의 종류가 다르지만 코드를 실행하는 방식은 "
},
{
"path": "Notes/html/data.md",
"chars": 792,
"preview": "# data- 속성\n\n**DOM에 데이터를 저장할 수 있는 사용자 정의 데이터 속성** 으로 `data-` 다음 오는 값이 데이터가 된다. 이 속성은 사용하고자 하는 용도에 적합한 속성이나 요소가 없을 때 사용하며 "
},
{
"path": "Notes/html/doctype.md",
"chars": 1124,
"preview": "# DOCTYPE\n\nDocument Type의 약자로, **HTML이 어떤 버전으로 작성되었는지 미리 선언하여 웹브라우저가 내용을 올바로 표시할 수 있도록 해주는 것** 이다. `<!DOCTYPE>` 으로 선언하는데"
},
{
"path": "Notes/html/script-tag-type.md",
"chars": 879,
"preview": "# script, script async, script defer\n\n* `<script>` : HTML 파싱이 중단되고 즉시 스크립트가 로드되며 로드된 스크립트가 실행되고 파싱이 재개된다.\n* `<script asy"
},
{
"path": "Notes/html/semantic.md",
"chars": 1431,
"preview": "# 시맨틱 마크업\n\n시맨틱(Semantic)이란 \"의미론적인\" 의 뜻을 가지며 마크업(Markup)이란 HTML 태그로 문서를 작성하는 것을 말한다. 따라서, 시맨틱 마크업이란 **의미를 잘 전달하도록 문서를 작성하"
},
{
"path": "Notes/html/standard-quirks.md",
"chars": 829,
"preview": "# 표준 모드와 호환 모드\n\n과거의 웹 페이지는 넷스케이프와 익스플로러 버전이 따로 존재했고 웹 표준이 없었다. 그러나 W3C가 웹 표준을 만들면서 브라우저가 웹사이트를 제대로 표현할 수 없게 되자 렌더링을 할 때 "
},
{
"path": "Notes/html/web-storage-api.md",
"chars": 1365,
"preview": "# local storage vs session storage vs cookie\n\n모두 클라이언트 상에서 key/value 쌍을 저장할 수 있는 메커니즘으로 **value는 반드시 문자열** 이어야 한다. 또한 모두"
},
{
"path": "Notes/javascript/ajax.md",
"chars": 2401,
"preview": "# AJAX\n\n## AJAX란 무엇인가?\n\nAsynchronous Javascript And XML의 약자로, 비동기적으로 JS를 사용해서 데이터를 받아와 동적으로 DOM을 갱신 및 조작하는 웹 개발 기법을 의미한다"
},
{
"path": "Notes/javascript/closure.md",
"chars": 1951,
"preview": "# 클로저(Closure)\n\n클로저란 **함수가 속한 렉시컬 스코프를 기억하여 함수가 렉시컬 스코프 밖에서 실행될 때도 그 스코프에 접근할 수 있게 하는 기능** 을 말한다.\n\n```javascript\nfunctio"
},
{
"path": "Notes/javascript/es11.md",
"chars": 2987,
"preview": "# ES11 (ES2020) 의 특징들\n\n### `String.prototype.matchAll`\n\n기존의 `String.prototype.match` 의 기능은 일치하는 결과값 외에는 아무런 정보도 주지 않는다. "
},
{
"path": "Notes/javascript/es6.md",
"chars": 6643,
"preview": "# ES6 (ES2015) 의 특징들\n\n모든 특징들을 나열하진 않고 중요하다고 생각하는 특징들만 나열한다.\n\n<br>\n\n### 화살표 함수(Arrow Function)\n\n`=>` 로 사용할 수 있으며 함수와 달리 `"
},
{
"path": "Notes/javascript/es7-es8.md",
"chars": 2542,
"preview": "# ES7 (ES2016) ~ ES8 (ES2017) 의 특징들\n\n## ES7 (ES2016)\n\n### `Array.prototype.includes`\n\n* `arr.includes(찾는원소, [, 인덱스시작점])`"
},
{
"path": "Notes/javascript/es9-es10.md",
"chars": 3089,
"preview": "# ES9 (ES2018) ~ ES10 (ES2019) 의 특징들\n\n## ES9 (ES2018)\n\n### async 반복자\n\n기존 반복자(Iterator)의 경우 `next()` 메서드는 `value` 와 `done"
},
{
"path": "Notes/javascript/event-delegation.md",
"chars": 2011,
"preview": "# 이벤트 위임\n\n## 이벤트 버블링과 캡쳐링\n\n이벤트 위임을 알기 위해선 선수지식으로 이벤트 버블링과 캡쳐링의 동작방식을 알아야 한다.\n\n**이벤트 버블링** 이란, 하위 엘리먼트에 이벤트가 발생할 때 그 엘리먼트"
},
{
"path": "Notes/javascript/event-loop.md",
"chars": 2628,
"preview": "# 이벤트 루프 (Event loop)\n\n> [콜 스택(Call stack)과 힙(Heap)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/No"
},
{
"path": "Notes/javascript/execution-context.md",
"chars": 5831,
"preview": "# 실행 컨텍스트 (Execution Context)\n\n## 정의\n\n**코드의 실행환경에 대한 여러가지 정보를 담고 있는 개념** 으로, 간단히 말하자면 자바스크립트 엔진에 의해 만들어지고 사용되는 코드 정보를 담"
},
{
"path": "Notes/javascript/hoisting.md",
"chars": 1358,
"preview": "# 호이스팅(Hoisting)\n\n> [스코프](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/scope.md) 의 "
},
{
"path": "Notes/javascript/identity-equal.md",
"chars": 1241,
"preview": "# == vs ===\n\n둘 다 동일한 비교를 하지만 엄격한 동등 비교 연산자(===)의 경우, **타입변환(Type conversion)이 일어나지 않으며 타입이 일치해야한다.**\n\n```javascript\n'' ="
},
{
"path": "Notes/javascript/iife.md",
"chars": 2735,
"preview": "# IIFE (Immediately-Invoked Function Expression)\n\nIIFE는 직역하면 즉시-실행 함수 표현식이다. 즉, 2가지 조건을 지닌다.\n\n* **즉시 실행하여야 한다.**\n* **함수 "
},
{
"path": "Notes/javascript/module.md",
"chars": 6229,
"preview": "# 모듈 시스템: CommonJS, AMD, UMD, ES6\n\n## 모듈(module)이란?\n\n모듈이란 **여러 기능들에 관한 코드가 모여있는 하나의 파일** 로 다음과 같은 것들을 위해 사용한다.\n\n* **유지보수"
},
{
"path": "Notes/javascript/native-host.md",
"chars": 751,
"preview": "# 네이티브 객체 vs 호스트 객체\n\n## 네이티브 객체 (Native Object)\n\nECMAScript 명세에서 의미론적인 부분을 완전히 정의해놓은 객체들로, 다음과 같은 것들이 있다.\n\n* `Object`\n* "
},
{
"path": "Notes/javascript/new.md",
"chars": 925,
"preview": "# new의 동작방식\n\n자바스크립트에선 `new` 연산자를 통해 함수를 생성자로 호출할 수 있고 그에따라 새로운 객체를 생성할 수 있다. 다음과 같은 과정으로 이루어진다.\n\n* 빈 객체를 생성한다.\n* `[[Prot"
},
{
"path": "Notes/javascript/prototype.md",
"chars": 4177,
"preview": "# 프로토타입 (Prototype)\n\n자바스크립트에서 정말 헷갈리는 개념으로, 자바스크립트를 다루는데 있어서 굉장히 중요한 역할을 하기 때문에 반드시 이해하여야 한다.\n\n## 정의\n\n자바스크립트의 모든 객체는 자신의"
},
{
"path": "Notes/javascript/scope.md",
"chars": 1206,
"preview": "# 스코프\n\n> [실행 컨텍스트(Execution Context)](https://github.com/baeharam/Must-Know-About-Frontend/blob/master/Notes/javascript/"
},
{
"path": "Notes/javascript/stack-heap.md",
"chars": 1363,
"preview": "# 콜 스택(Call stack)과 힙(Heap)\n\n자바스크립트 엔진이 자바스크립트를 실행할 때 원시 타입 및 참조 타입을 저장하는 메모리 구조로 콜 스택과 힙을 가진다.\n\n* **콜 스택** : **원시타입 값**"
},
{
"path": "Notes/javascript/strict-mode.md",
"chars": 1097,
"preview": "# 엄격 모드 (Strict mode)\n\nECMAScript5 부터 도입된 기능으로 **기존에 무시되던 에러들로 하여금 에러를 발생시키게 한다.** 파일 전체에 적용시킬 수도 있고 함수 스코프에 적용시킬 수 있지만 "
},
{
"path": "Notes/javascript/this.md",
"chars": 1046,
"preview": "# this의 바인딩\n\nEC(Execution Context)가 생성될 때마다 this의 바인딩이 일어나며 우선순위 순으로 나열해보면 다음과 같다.\n\n1. `new` 를 사용했을 때 해당 객체로 바인딩된다.\n\n```"
},
{
"path": "Notes/javascript/var-let-const.md",
"chars": 2496,
"preview": "# var vs let vs const\n\n모두 변수를 선언하는 키워드라는 것은 동일하다. 하지만, let과 const는 ES2015(ES6)에서 등장했고 여러가지 다른 특성을 갖는다.\n\n## 스코프 규칙\n\n> 스코프"
},
{
"path": "Notes/network/cdn.md",
"chars": 1393,
"preview": "# CDN (Contents Delivery Network)\n\n어느 스타트업의 기술 면접을 보러갔을 때, 웹사이트를 구성하는 수많은 리소스들이 있을 경우 어떻게 최적화하는가에 대한 질문을 받은 적이 있다. 예를 들어"
},
{
"path": "Notes/network/cookie-session.md",
"chars": 1744,
"preview": "# Cookie vs Session\n\nHTTP는 상태가 없는(Stateless) 프로토콜이기 때문에 사용자가 웹 브라우저를 통해서 특정 웹 사이트에 접속하게 될 경우 어떤 사용자가 접속했는지에 대한 정보를 파악할 수"
},
{
"path": "Notes/network/http.md",
"chars": 3172,
"preview": "# HTTP\n\n클라이언트-서버 모델을 따르는 프로토콜로 TCP/IP 위에서 동작하며 well-known 포트인 80번 포트를 사용하여 통신한다. 첫번째 표준은 HTTP/1.1이며 이후로 HTTP/2 및 HTTP/3가"
},
{
"path": "Notes/network/http1.1-2.md",
"chars": 1651,
"preview": "# HTTP/1.1과 HTTP/2의 차이점\n\n이제까지 전통적인 웹 브라우저와 웹 서버와의 통신 프로토콜은 HTTP/1.1 기준으로 동작했는데, 많은 문제점들과 개선할 부분들이 있었기 때문에 2015년에 HTTP/2가"
},
{
"path": "Notes/network/https.md",
"chars": 1478,
"preview": "# HTTPS\n\n<img src=\"../../images/network/https.png\">\n\nHTTPS(HyperText Transfer Protocol over TLS/SSL)는 **기존의 HTTP를 암호화한 프"
},
{
"path": "Notes/network/rest-api.md",
"chars": 3435,
"preview": "# REST API\n\n학술적으로 엄밀한 내용을 보고 싶다면 REST를 만든 [로이필딩의 논문](https://www.ics.uci.edu/~taylor/documents/2002-REST-TOIT.pdf) 을 보는 "
},
{
"path": "Notes/network/tcp-udp.md",
"chars": 2469,
"preview": "# TCP와 UDP\n\nOSI 7계층에서 전송계층(Transport layer)에 속하는 데이터 전송 프로토콜이다. 여기선 중요한 것만 살펴보고 깊게는 들어가지 않는다.\n\n## TCP (Transmission Cont"
},
{
"path": "Notes/network/type-url-process.md",
"chars": 915,
"preview": "# URL을 입력하고 벌어지는 일\n\n* URL을 웹 브라우저의 주소창에 입력한다.\n* 웹 브라우저가 URL을 해석하고, 문법에 맞지 않으면 기본 검색엔진으로 검색한다.\n* 문법에 맞으면 URL의 호스트 부분을 인코딩"
},
{
"path": "Notes/network/uri.md",
"chars": 1368,
"preview": "# URL과 URN을 포함하는 URI\n\n## URI(Uniform Resource Identifier)\n\n통합 자원 식별자라는 의미로 **인터넷 상의 리소스** 를 고유하게 식별할 수 있는 식별자이다. URI에는 위"
},
{
"path": "Notes/security/sop.md",
"chars": 3703,
"preview": "# 동일 출처 정책 (Same-Origin Policy)\n\n어떠한 문서나 스크립트가 다른 **프로토콜 / 포트 / 호스트** 에 있는 리소스 사용하는 것을 제한하는 정책. 예를 들어, 다음과 같은 사이트에서 리소스를"
},
{
"path": "Notes/security/xss-csrf.md",
"chars": 2141,
"preview": "# XSS와 CSRF\n\n## XSS(Cross Site Scripting, 사이트간 스크립팅)\n\n**웹사이트 관리자가 아닌 사람이 웹사이트에 악성 스크립트를 삽입할 수 있는 취약점을 이용한 공격기법이다.** 사용자로"
},
{
"path": "README.md",
"chars": 7065,
"preview": "# 취준생이 반드시 알아야 할 프론트엔드 지식들\n\n## 목차\n\n* [소개](#tada-소개)\n* [프론트엔드 전반](#computer-프론트엔드-전반)\n* [HTML](#page_with_curl-html)\n* [C"
}
]
About this extraction
This page contains the full source code of the baeharam/Must-Know-About-Frontend GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 57 files (120.0 KB), approximately 50.7k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.