Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[권오연] 1장: 리액트 개발을 위해 꼭 알아야 할 자바스크립트 #5

Merged
merged 1 commit into from
Dec 5, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
284 changes: 284 additions & 0 deletions 1장/권오연.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
## 1.1 자바스크립트의 동등 비교

### 1.1.1 자바스크립트의 데이터 타입

- 원시 타입
- boolean
- null
- undefined
- number
- string
- symbol
- 중복되지 않는 어떤 고유한 값을 나타내기 위해 만들어진 타입. `Symbol()` 을 사용해서 제작 가능.
- ex. `const key = Symbol('key')`
- bigint
- number가 다룰 수 있는 숫자 크기의 제한을 극복하기 위해 ES2020에서 새롭게 나온 타입. 2^53 - 1 보다 더 큰 숫자를 저장 가능
- 객체 타입
- object

### 1.1.2 값을 저장하는 방식의 차이

- 원시 타입은 불변 형태의 값으로 저장
- 객체 타입은 변경 가능한 형태로 저장, 값을 복사할 때도 값이 아닌 참조를 전달

### 1.1.3 자바스크립트의 또 다른 비교 공식, Object.is

- 비교할 수 있는 방법: 1. == 2. === 3. [Object.is](http://Object.is)
- == 는 강제로 타입 변환을 시켜 느슨한 비교 연산자로서 작동
- === 는 타입이 다른 경우에는 false를 리턴해 엄격한 비교 연산자로서 작동
- [Object.is](http://Object.is) 는 위 비교 연산자들보다 좀 더 개발자가 기대하는 방식으로 정확하게 비교

```jsx
-0 === +0; // true
Object.is(-0, +0); // false

Number.NaN === NaN; // false
Object.is(Number.NaN, NaN); // true

NaN === 0 / 0; // false
Object.is(NaN, 0 / 0); // true
```

### 1.1.4 리액트에서의 동등 비교

- 리액트에서는 이 Object.is를 기반으로 동등 비교를 하는 shallowEqual 함수를 만들어 사용
- shallowEqual
- [Object.is](http://Object.is) 로 먼저 비교를 수행한 다음에 객체 간 얕은 비교(첫 번째 깊이에 존재하는 값만 비교)를 한 번 더 수행
- 그 이유는 props 가 객체이고 이 props 만 일차적으로 비교하면 되기 때문

## 1.2 함수

### 1.2.1 함수란 무엇인가?

- 함수란 작업을 수행하거나 값을 계산하는 등의 과정을 표현하고, 이를 하나의 블록으로 감싸서 실행 단위로 만들어 놓은 것

### 1.2.2 함수를 정의하는 4가지 방법

- 함수 선언문
- 가장 일반적인 방식
- 호이스팅이 가능 → 코드의 순서에 상관없이 함수를 호출할 수 있다.
- 함수 표현식
- 함수는 ‘일급 객체’
- 함수는 다른 함수의 매개변수가 될 수도 있고, 반환값이 될 수도 있으며, 할당도 가능
- 함수를 변수에 할당하는 것은 당연히 가능
- 호이스팅은 가능하지만 런타임 시점에 함수가 할당되어 작동
- Function 생성자
- 잘 사용하지 않는 방법
- 화살표 함수
- ES6에서 새로 추가된 방식이며 가독성과 코드 글자 수가 줄어들어 많이 이용하는 방식
- 기존 함수와 차이점
- constructor 사용 불가
- arguments 없음
- this 바인딩 차이: 화살표 함수는 함수 자체의 바인딩을 갖지 않는다.

### 1.2.3 다양한 함수 살펴보기

- 즉시 실행 함수 (IIFE: Immediately Invoked Function Expression)
- 함수를 정의하고 그 순간 즉시 실행되는 함수, 단 한 번만 호출되고 다시금 호출할 수 없다.
- 고차 함수
- 함수를 인수로 받거나 결과로 새로운 함수를 반환하는 함수
- 이 특징을 활용해 고차 컴포넌트(Higher Order Component) 를 만들 수 있다.

### 1.2.4 함수를 만들 때 주의해야 할 사항

- 함수의 부수 효과(side effect)를 최대한 억제하라
- 가능한 함수를 작게 만들어라
- 누구나 이해할 수 있는 이름을 붙여라
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

즐겨 사용하시는 네이밍 컨벤션이 있으신가요?!

- useEffect나 useCallback을 사용할 때 넘겨주는 콜백 함수에 네이밍을 붙여주면 가독성에 도움이 된다.
```jsx
useEffect(function apiRequest() {
// do something
}, []);
```

## 1.3 클래스

### 1.3.1 클래스란 무엇인가?

- 특정한 형태의 객체를 반복적으로 만들기 위해 사용되는 것
- constructor
- 객체를 생성하는데 사용하는 특수한 메서드, 단 하나만 존재할 수 있으며 여러 개를 사용한다면 에러가 발생
- 생성자에서 별 다르게 수행할 작업이 없다면 생략도 가능
- 프로퍼티
- 클래스로 인스턴스를 생성할 때 내부에 정의할 수 있는 속성값
- getter와 setter
- getter: 클래스에서 무언가 값을 가져올 때 사용
- setter: 클래스 필드에 값을 할당할 때 사용
- 인스턴드 메서드
- 클래스 내부에 선언한 메서드
- a.k.a. prototype 메서드
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😎

- 정적 메서드
- 클래스의 인스턴스가 아닌 이름으로 호출할 수 있는 메서드 `static`
- this는 사용할 수 없다.
- 전역 유틸 함수를 정적 메서드로 많이 활용
- 상속
- `extends` 키워드를 활용하면 기본 클래스를 기반으로 다양하게 파생된 클래스를 만들 수 있다.

### 1.3.2 클래스와 함수의 관계

- 클래스 작동을 생성자 함수로 유사하게 재현 가능

## 1.4 클로저

### 1.4.1 클로저의 정의

- 클로저는 함수와 함수가 선언된 어휘적 환경의 조합

### 1.4.2 변수의 유효 범위, 스코프

- 전역 스코프
- 전역 레벨에 선언한 스코프
- 변수를 선언하면 어디서든 호출할 수 있음.
- 함수 스코프
- 자바스크립트는 기본적으로 함수 레벨 스코프

### 1.4.3 클로저의 활용

- 전역 스코프의 활용을 막고, 개발자가 원하는 정보만 개발자가 원하는 방향으로 노출시킬 수 있다.
- 리액트에서의 클로저
- `useState` 함수의 호출이 종료되어도 setState는 useState 내부의 최신 값을 계속해서 확인이 가능

### 1.4.4 주의할 점

- 꼭 필요한 작업만 남겨 놓고 기억할 수 있도록 구성해야 함
- 그렇지 않으면 메모리를 불필요하게 잡아먹고 성능에 악영향을 미칠 수 있다.

## 1.5 이벤트 루프와 비동기 통신의 이해

- 자바스크립트는 싱글 스레드에서 작동하기 때문에 한 번에 하나의 작업만 동기 방식으로 처리할 수 있는 것이 기본이다.
- 그렇지만 이벤트 루프 등의 개념을 활용해 비동기 요청을 처리할 수 있다.

### 1.5.1 싱글 스레드 자바스크립트

- 프로세스
- 프로그램을 구동해 프로그램의 상태가 메모리상에서 실행되는 작업 단위, 즉 하나의 프로그램 실행은 하나의 프로세스를 가지고 그 프로세스 내부에서 모든 작업이 처리되는 것

→ 동시에 여러 개의 복잡한 작업을 수행하기 위해서 스레드라는 더 작은 실행 단위가 등장

- 스레드
- 하나의 프로세스에서 여러 개의 스레드를 만들 수 있고 스레드 끼리는 메모리를 공유할 수 있어 여러 가지 작업을 동시에 수행할 수 있다.

→ 결국 프로세스 내부에서 여러 개의 스레드를 활용하면서 동시 다발적인 작업 처리가 가능해 짐.

- 싱글 스레드 자바스크립트라는 것은 자바스크립트 코드의 실행이 하나의 스레드에서 순차적으로 이루어진다는 의미

### 1.5.2 이벤트 루프란?

- 이벤트 루프란 자바스크립트 런타임 외부에서 자바스크립트 비동기 실행을 돕기 위해 만들어진 장치
- 호출 스택과 이벤트 루프
- 호출 스택은 자바스크립트에서 수행해야 할 코드나 함수를 순차적으로 담아두는 스택
- 호출 스택에 실행 중인 코드가 있는지, 그리고 태스크 큐에 대기 중인 함수가 있는지 반복해서 확인하는 역할
- 호출 스택이 비었다면 태스크 큐에 대기 중인 작업이 있는지 확인하고 이 작업을 실행 가능한 오래된 것부터 순차적으로 꺼내와서 실행한다.

### 1.5.3 태스크 큐와 마이크로 태스크 큐

- 마이크로 태스크
- Promise
- 마이크로 태스크 큐는 기존 태스크 큐보다 우선권을 갖는다. 즉, `setTimeout` 과 `setInterval` 은 Promise 보다 늦게 실행
- 마이크로 태스크 큐 작업이 끝날 때 마다 렌더링이 실행된다.

## 1.6 리액트에서 자주 사용하는 자바스크립트 문법

### 1.6.1 구조 분해 할당

- 배열 또는 객체의 값을 분해해 개별 변수에 즉시 할당
- 배열은 이름을 변경할 수 있고, 객체는 객체 내부 이름으로 사용 가능
- `useState` 는 배열 구조 분해 할당을 활용한 예시

### 1.6.2 전개 구문

- spread syntax
- 객체, 문자열과 같이 순회할 수 있는 값에 대해 전개해서 간결하게 사용할 수 있는 구문
- 배열과 객체의 전개 구문을 활용하면 `push()` , `concat()` , `splice()` 등의 메서드를 사용하지 않고도 합성이 가능하다.
- 단, 객체 전개 구문에 있어서는 순서가 중요하다.

### 1.6.3 객체 초기자

- 객체를 선언할 때 객체에 넣고자 하는 키와 값을 가지고 있는 변수가 이미 존재한다면 해당 값을 간결하게 넣어줄 수 있는 방식

### 1.6.4 Array 프로토타입의 메서드: map, filter, reduce, forEach

- map: 인수로 전달받은 배열과 똑같은 길이의 새로운 배열을 반환하는 메서드
- filter: 콜백 함수를 인수로 받고, 콜백 함수에서 truthy 조건을 만족하는 경우에만 해당 원소를 반환
- reduce: 콜백 함수와 함께 초깃값을 추가로 인수를 받는데 이 초깃값에 따라 배열이나 객체, 또는 그 외의 다른 무언가를 반환할 수 있는 메서드
- forEach: 콜백 함수를 받아 배열을 순회하면서 단순히 그 콜백 함수를 실행하기만 하는 메서드

### 1.6.5 삼항 조건 연산자

- 자바스크립트에서 유일하게 3개의 피연산자를 취할 수 있는 문법

```html
조건문 ? 참일 때 값 : 거짓일 때 값
```

- 삼항 조건 연산자는 가급적이면 가독성을 위해서 중첩하지 않는 편이 좋다.

## 1.7 선택이 아닌 필수, 타입스크립트

### 1.7.1 타입스크립트란?

- TypeScript is JavaScript with syntax for types
- 자바스크립트는 기본적으로 동적 타입의 언어이기 때문에 대부분의 에러를 코드를 실행했을 때만 확인할 수 있다는 문제점이 있다.
- 자바스크립트의 한계를 벗어나 타입 체크를 정적으로 런타임이 아닌 빌드 타임에 수행할 수 있게 해 준다.

### 1.7.2 리액트 코드를 효과적으로 작성하기 위한 타입스크립트 활용법

- any 대신 unknown을 사용하자
- any는 타입스크립트를 사용하는 의미가 없어지게 만들기 때문에 정말 예외적인 경우에만 사용하는 것이 좋다.
- 대신 아직 타입을 단정할 수 없는 경우에는 unknown 을 사용하는 것이 좋다.
```html
function doSomething(callback: unknown) { if (typeof callback ===
'function') { callback() } throw new Error('callback은 함수여야 합니다.') }
```
이렇게 typeof를 사용해서 unknown에 직접 접근하는 대신 해당 unknown 값이 우리가 원하는 타입일 때만 의도대로 작동하도록 코드를 작성
- unknown: top type VS never: bottom type
- never은 어떤 타입도 들어올 수 없음을 의미, 코드상으로 존재가 불가능한 타입
- 타입 가드를 적극 활용하자
- 타입을 사용할 때는 타입을 좁히는 것이 좋다. 타입을 좁히는데 도움을 주는 것이 타입 가드
- instanceof
- 클래스로 타입을 만들어서 타입 체크를 할 때 해당 클래스의 인스턴스인지 체크
- typeof
- 특정 요소에 대한 자료형을 확인
- in
- 어떤 객체에 키가 존재하는지 확인하는 용도
- 제네릭
- 함수나 클래스 내부에서 단일 타입이 아닌 다양한 타입에 대응할 수 있도록 도와주는 도구 `<>`
```html
const [state, setState] = useState<string>('')</string>
```
- 인덱스 시그니처
- 객체의 키를 정의하는 방식, 키에 원하는 타입을 부여할 수 있다.
```html
type Hello = { [key: string]: string }
```
여기서 `[key: string]` 이 부분이 인덱스 시그니처
- 인덱스 시그니처를 사용할 경우 key의 범위가 string, number 등 커지기 때문에 키의 타입을 좁히는 방법이 필요하다.
- `Record<Key, Value>` 혹은 `type` 을 활용해 타입을 좁힐 수 있다.
- `Object.keys` 를 활용해서 객체의 키들을 뽑아낼 경우 타입 에러가 발생할 수 있다.
- 이럴 때는 `as` 를 활용해 타입 단언을 해 줄 수 있다.

### 1.7.3 타입스크립트 전환 가이드

- tsconfig.json 먼저 작성하기
- 주요 옵션 목록
- `outDir` : .ts 나 .js 가 만들어진 결과를 넣어두는 폴더
- `allowJs` : .js 파일을 허용할 것인지
- `target` : 결과물이 될 자바스크립트 버전 지정
- `include` : 트랜스파일 할 자바스크립트와 타입스크립트 파일 지정
- JSDoc과 @ts-check를 활용해 점진적으로 전환하기
- 자바스크립트 파일 최상단에 //@ts-check를 선언하고 JSDoc을 활용해 변수나 함수에 타입을 제공하면 타입 체크 가능
- 타입 기반 라이브러리 사용을 위해 @types 모듈 설치하기
- 자바스크립트 기반으로 작성된 라이브러리를 타입스크립트에서 사용하기 위해서는 @types 모듈을 설치
- ex. `@types/react`
- 파일 단위로 조금씩 전환하기

## 알게 된 부분

- 클로저라는 개념이 추상적으로만 느껴졌었는데 useState가 클로저를 활용한 개념이라는 것을 알고나니 훨씬 개념 잡기 명확해진 느낌!
- 태스크 큐와 마이크로 태스크 큐가 나눠진다는 것도 처음 알게 되었다. Promise가 setTimeout, setInterval 보다 더욱 우선적으로 실행!
- 타입스크립트 꿀팁들이 유용했다. as 로 타입 단언하는 것을 지양한다고 알고 있었는데 Object.keys 로 인해 타입이 넓게 설정될 경우 as가 필요하다는 것을 알게 됨!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧐

- 그래서 타입 단언을 사용하는 경우를 조금 더 찾아보았다.
- HTML 요소에 접근하게 될 경우
- `document.getElementById("root")` 를 변수에 할당하게 되면 해당 요소는 정확하게 `HTMLDivElement` 밖에 없다는 것을 알기 때문에 단언 사용을 해도 무방!
- stringify 된 JSON 값을 parsing 해서 사용하는 경우
- JSON.parse를 거치고 난 값은 any 타입으로 나오기 때문에 파싱한 후 타입을 갖게 하기 위해서 as를 활용해 단언 사용이 가능!
Comment on lines +275 to +284
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍 👍 👍 👍 👍