-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[5,6주차/현] 워크북 제출합니다.
- Loading branch information
Showing
148 changed files
with
22,213 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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를 만들어 줌 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }, | ||
], | ||
}, | ||
}, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
Oops, something went wrong.