Skip to content

Commit

Permalink
[5,6주차/현] 워크북 제출합니다.
Browse files Browse the repository at this point in the history
[5,6주차/현] 워크북 제출합니다.
  • Loading branch information
hyuke81 authored Nov 14, 2024
2 parents 17bf2bf + d4a359f commit 8a66c3f
Show file tree
Hide file tree
Showing 148 changed files with 22,213 additions and 0 deletions.
47 changes: 47 additions & 0 deletions keyword/chapter05/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
- useRef 🍠

렌더링에 필요하지 않은 값을 참조할 수 있는 React hook

```jsx
const ref = useRef(initialValue)
```

- 컴포넌트가 특정 정보를 ‘기억’하도록 하고 싶지만 해당 정보가 새 렌더링을 촉발하지 않도록 하려는 경우 ref를 사용할 수 있음
- **`useRef(initialValue)`**
- 컴포넌트의 최상위 레벨에서 `useRef`를 호출하여 `ref`를 선언

```jsx
import { useRef } from 'react';
function MyComponent() {
const intervalRef = useRef(0);
const inputRef = useRef(null);
// ...
```

- returns
- 단일 프로퍼티를 가진 객체를 반환함

```jsx
const intervalRef = useRef(0)
console.log(intervalRef)
// { current: 0 } 출력
```


- ref 특징
- 일반 변수는 리렌더링 될 때마다 재할당 but, ref 객체는 동일한 객체를 반환
- 리렌더링 사이에 정보를 저장
- state 변수는 변경될 때마다 리렌더링을 촉발
- 정보가 공유되는 외부 변수와 달리 각각의 컴포넌트에 로컬로 저장

⇒ 화면에 표시되는 정보를 저장하는 데는 ref보다는 state를 사용하는 게 좋음

### react-hook-form & yup 🍠

ex. 회원가입

react-hook-form은 회원가입에 필요한 각각의 항목들을 state로 관리해주고 변화를 실시간으로 반영

yup를 통해 회원가입에 필요한 input 값을 관리할 schema를 만들어 줌
181 changes: 181 additions & 0 deletions keyword/chapter06/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
- Debounce & Throttling 🍠
- Debounce는 무엇일까요?
- 특정 기간 동안 함수의 실행을 모두 취소하고, 마지막 실행만 수행함
- 함수를 마지막으로 호출한 후 일정 시간이 경과한 후에만 함수가 실행되도록 함
- 가장 마지막 이벤트만을 실행해 성능성 유리함
- Trailing
- 임계시간 안에 연속적으로 이벤트를 계속해서 발생하게 되면 이벤트가 끝날 때까지, 계속해서 함수의 실행은 뒤로 밀리게 됨
- 이후, 이벤트 끝나고 임계조건이 끝나야만 실제 함수의 실제 함수의 실행이 수행됨
- Leading
- 맨 처음의 이벤트에 대해서만 함수를 딱 한 번만 실행하고, 나머지는 모두 무시함
- Debounce는 주로 어디에 사용하나요?
- 사용자가 입력이나 스크롤과 같은 이벤트 트리거를 중단할 때까지 함수 실행을 지연시키고자 하는 시나리오에서 사용됨
- JavaScript의 디바운싱은 브라우저 성능을 향상시키는 데 사용되는 방식
- Throttling은 무엇일까요?
- 함수 실행 후 특정 기간 동안 추가적인 함수의 재실행을 모두 취소함
- 연속해서 발생하는 이벤트에 대해 특정 시간을 주기로 끊어내는 개념
- 지정된 시간 간격(time interval)안에 최대 한 번의 이벤트만 리스닝하겠다는 개념
- Throttling은 주로 어디에 사용하나요?
- 함수를 주기적으로 호출하되 너무 자주 호출하지 않으려느 시나리오에 유용
- Debounce와 Throttling의 차이점은 무엇일까요?
- Throttle은 입력 주기를 방해하지 않고 일정 시간 동안의 입력을 모아서 한 번에 출력을 제한하는 것이고 Debounce 는 입력 주기가 끝나면 출력하게함
- throttling은 적어도 x 밀리 초마다 정기적으로 기능 실행을 보장함
- debounce는 아무리 많은 이벤트가 발생해도 모두 무시하고 특정 시간사이에 어떤 이벤트도 발생하지 않았을 때 딱 한번만 마지막 이벤트를 발생시킴
- 어떤 기능을 구현할 때 Debounce를 적용하고, Throttling을 적용하는 것이 좋을까요?
- Debounce
- 키워드 검색 혹은 자동완성 기능에서 api 함수 호출 횟수를 최대한 줄이고 싶을때
- 사용자가 창크기 조정을 멈출때까지 기다렸다가 resizing Event 를 반영하고 싶을때
- Throttling
- 스크롤에 많이 사용

- 쿠키 🍠
- 쿠키란 무엇이고, 어떤 특징을 가지고 있을까요?
- 사용자의 디스크나 웹 브라우저 메모리에 저장
- 클라이언트 측에 `key``value`형태의 **text 타입**으로 데이터가 저장되며 데이터의 크기에 제한이 있음
- 쿠키를 어떻게 사용할 수 있을까요?

**프로세스**

1. 브라우저에서 웹 페이지 접속
2. 웹 서버에서 쿠키를 생성
3. 생성한 쿠키에 데이터를 담아 요청에 응답할 때 클라이언트에게 함께 전송
4. 클라이언트가 보관하다가 서버에 재요청할 때 쿠키를 함께 전송
5. 클라이언트와 서버가 로그인 정보가 유지되어있는 것처럼 사용
- 토큰 🍠
- 토큰이 왜 필요할까요?
- 메모리 공간을 많이 차지하는 세션 방식의 대안은 로그인한 사용자에게 세션 아이디 대신 토큰을 발급
- 세션 방식은 안전하고 효과적이지만 서버에 부하가 걸리는 단점이 있음
- CORS 에러가 무엇이고, 이 에러를 어떻게 해결할 수 있을까요?

CORS(Cross-Origin Resource Sharing)

- 출처(Origin)가 다른 자원들을 공유한다.

해결방법

- 서버의 허용이 필요함
- **`서버측`에서 허용할 출처를** 헤더의 **`Access-Control-Allow-Origin`**에 기재해서 응답하면 해결
- 크롬 확장 프로그램 이용
- Proxy 활용
- 클라이언트와 서버 사의의 중간 역할
-
- JWT 토큰 기반 인증 방법이란 무엇일까요?
- JWT는 인증에 필요한 정보들을 암호화시킨 JSON토큰
- JWT 기반 인증은 JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식
- 토큰은 세션과 달리 서버가 아닌 클라이언트에 저장되기 때문에 서버의 부담을 줄일 수 있음
- JWT 기반 로그인 동작 과정에 대해 알아보세요.
1. 클라이언트 사용자가 아이디, 패스워드를 통해 웹서비스 인증
2. 서버에서 서명된(signed) JWT를 생성하여 클라이언트에 응답으로 돌려주기
3. 클라이언트가 서버에 데이터를 추가적으로 요구할 때 JWT HTTP Header에 첨부
4. 서버에서 클라이언트로부터 온 JWT를 검증
- AccessToken / RefreshToken의 차이에 대해 설명해주세요.
- 웹 스토리지 🍠
- 웹 스토리지의 메소드와 프로퍼티는 어떤게 있을까요?
- 공통 메소드/프로퍼티


| **메소드** | **설명** |
| --- | --- |
| **setItem(key, value)** | 키-값 쌍을 보관 |
| **getItem(key)** | 키에 해당하는 값을 받아옴 |
| **removeItem(key)** | 키와 해당 값을 삭제 |
| **clear()** | 모든 것을 삭제 |
| **key(index)** | 인덱스(index)에 해당하는 키를 받아옴 |
| **length** | 저장된 항목의 개수를 가져옴 |
- 세션 스토리지에 대해 정리해 주세요!
- 데이터가 오리진 뿐만 아니라 브라우저 탭에도 종속되기 때문에 윈도우나 브라우저 탭을 닫을 경우 제거
- 같은 브라우저라도 탭이 다르면 공유 불가
- 페이지를 새로 고침할 때 `sessionStorage`에 저장된 데이터는 사라지지 않음
- 탭 닫고 새로 열 때는 제거
- 일시적으로 필요한 데이터 저장
- 일회성 로그인 정보, 입력창 저장
- 오리진뿐만 아니라 브라우저 탭에도 종속되어 있어 잘 사용하지 않음
- 로컬 스토리지에 대해 정리해 주세요!
- 브라우저 내에서 영구적으로 데이터를 저장
- 도메인만 같으면 전역적으로 공유 가능
- 저장한 데이터는 브라우저를 종료하거나 컴퓨터를 재 시작해도 유지
- 사용자가 웹 어플리케이션을 떠났다가 나중에 돌아올 때 유용한 데이터 저장할 때 유용
- window.lacalStorage에 위치
- key, value 저장소이기 때문에 key, value를 순서대로 저장
- 값으로는 문자열, 불린, 숫자, null, undefined 등을 저장할 수 있지만, 모두 문자열로 변환
- key도 문자열로 반환
- 로컬 스토리지에서 JWT 토큰을 저장하고, 사용하고, 삭제하는 메소드에 대해 찾아보세요!

```jsx
//로그인 후 로켈 스토리지에 토큰 저장
localStorage.setitem('token', token);

//로그아웃 시 로컬 스토리지에서 토큰 제거
localStorage.removeitem('token');
```

- 스토리지가 변경되었을 때 처리하는 방법을 조사해 주세요.

```jsx
window.addEventListener("storage", () => {
const showSidebar = localStorage.getItem('show-sidebar') === 'true';
// showSidebar 값 적용하기
});
```

- Bearer Token이 무엇인지 찾아보고, 이를 통해 백엔드 서버와 어떠한 방식으로 통신하는지 조사해 보세요!
- OAuth와 같은 인증 서버를 사용하여 엑세스 토큰을 이용해 인증하는 방식
- 보안성이 높아 중요한 데이터나 기능을 보호하는 데 적합
- Bearer Token을 사용하려면 우선 인증 서버에서 엑세스 토큰을 발급
- 클라이언트는 이 토큰을 HTTP 요청 헤더에 포함하여 서버로 전송

```jsx
Authorization: Bearer {access_token}
```

- 토큰 기반 인증 방식이므로 요청할 때마다 아이디와 비밀번호를 전송할 필요가 없음
- OAuth 프레임워크
- 리소스 소유자: 사용자
- 클라이언트: 사용자의 정보를 접근하는 제 3자의 서비스
- 인증 서버: 클라이언트의 접근을 관리하는 서버
- 리소스 서버: 리소스 소유자의 데이터를 관리하는 서버

![image.png](https://prod-files-secure.s3.us-west-2.amazonaws.com/f1912130-0409-4e90-a90f-6091ae253e73/6ff14404-825b-461f-ac12-060b10c1a6a5/image.png)

- 리소스 소유자의 동의가 확인되면 인증 서버는 클라이언트에게 액세스 토큰을 발급
- 클라이언트는 액세스 토큰을 사용해서 리소스 서버에 보호된 데이터를 불러 옴
- Bearer 토큰은 클라이언트가 해석할 수 없는 형태여야 하고, 사용자의 정보를 전달 x
- 서버에서 클라이언트의 권한을 확인할 수 있는 메타데이터가 토큰에 인코딩되어 있어야 함
- Context-API 🍠
- 전역 상태 관리는 왜 해야할까요?
- 리액트 데이터는 부모로부터 자식으로 props를 통해 탑-다운으로 전달됨. 이 단계가 너무 많아진다거나 전달을 여러곳에 해줘야하는 경우, 전역 스토어에 데이터를 저장하고 이를 데이터가 필요한 컴포넌트에 따로 공유할 수 있음

⇒ 몇 단계만 전달하면 되거나 굳이 전역으로 관리할 필요가 없는 데이터를 전역으로 넣는 것은 코드의 관리 측면에서 좋지 않음

- Context API란 무엇일까요?
- props를 사용하지 않아도 특정 값이 필요한 컴포넌트끼리 쉽게 값을 공유할 수 있게 함
- Provider 하위의 모든 consumer들이 Provider 속성이 변경될 때마다 다시 렌더링
- 만약 Provider의 값이 배열이나 객체인 경우, 구조가 조금이라도 변경된다면 그 Context를 구독하고 있는 하위의 모든 것들이 다시 렌더링
- `createContext` 함수를 불러와서 context를 생성

```jsx
import {createContext} from 'react';
const MyContext = creatreContext();
```

- 공유하고자 하는 state가 있는 컴포넌트를 `context` 내부 `Provider`를 꺼내 감싸주고, 공유하고자 하는 state를 `value`에 넣고 공유

```jsx
function App() {
return (
<MyContext.Provider value="Hello World">
<Children />
</MyContext.Provider>
);
}
```

- `value`에서 공유된 state를 활용하고 싶은 컴포넌트 안에서 `useContext`를 선언하여 state를 꺼내 씀

```jsx
import {useContext} from 'react';
function Message() {
const value = useContext(MyContext);
return <div>Received: {value}</div>;
}
```
26 changes: 26 additions & 0 deletions mission/chapter05/mission/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

.env
8 changes: 8 additions & 0 deletions mission/chapter05/mission/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# React + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
38 changes: 38 additions & 0 deletions mission/chapter05/mission/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import js from '@eslint/js'
import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'

export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
12 changes: 12 additions & 0 deletions mission/chapter05/mission/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./src/main.jsx"></script>
</body>
</html>
Loading

0 comments on commit 8a66c3f

Please sign in to comment.