-
Notifications
You must be signed in to change notification settings - Fork 5
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
[2주차] 김세현 학습 PR 제출합니다. #14
base: main
Are you sure you want to change the base?
Changes from all commits
aac9c9c
41986bf
2769bc0
274d844
b12f0e1
663d974
90e0dd1
9268024
29c69c3
b597ba0
f0c4497
5a0a489
0b34680
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
## JSX란? (JavaScript eXtension) | ||
|
||
JSX는 JavaScript를 확장한 문법이며, JavaScript의 모든 기능이 포함되어 있다. | ||
|
||
React에서 JSX 사용이 필수가 아니지만, 대부분 JavaScript 코드 안에서 UI 관련 작업을 할 때 시작적으로 더 도움이 된다고 생각한다. 또한 React가 더욱 도움이 되는 에러 및 경고 메시지를 표시할 수 있게 해준다. | ||
|
||
## JSX도 표현식이다. | ||
|
||
``` | ||
const name = 'Josh Perez'; | ||
|
||
const element = <h1>Hello, {name}</h1>; | ||
``` | ||
|
||
name이라는 변수를 선언한 후 중괄호로 감싸 JSX에 사용하였는데, JSX의 중괄호 ({}) 안에는 유효한 모든 JavaScript 표현식을 넣을 수 있다. | ||
|
||
컴파일이 끝나면, JSX 표현식이 정규 JavaScript 함수 호출이 되고 JavaScript 객체로 인식된다. | ||
|
||
## JSX 속성 정의 | ||
|
||
어트리뷰트에 따옴표를 사용해 문자열 리터럴을 정의할 수 있으며, 중괄호를 사용해 JavaScript 표현식을 삽입할 수 있다. | ||
|
||
``` | ||
const element = <a href="https://www.reactjs.org">link</a>; | ||
const element = <img src={user.avatarUrl} />; | ||
``` | ||
|
||
JSX에서는 HTML 어트리뷰트 이름 대신 camelCase 프로퍼티 명명 규칙을 사용한다. 예를 들어, `class`는 `className`으로 사용된다. | ||
|
||
## JSX로 자식 정의 | ||
|
||
``` | ||
const element = ( | ||
<div> | ||
<h1>Hello!</h1> | ||
<h2>Good to see you here.</h2> | ||
</div> | ||
); | ||
``` | ||
|
||
JSX 태그는 자식을 포함할 수 있으며, 태그가 비어있다면 XML 처럼 />로 닫아야 한다. | ||
|
||
## JSX는 주입 공격을 방지한다. | ||
|
||
JSX에 사용자 입력을 삽입하는 것은 안전하다. React DOM은 JSX에 삽입된 모든 값을 렌더링하기 전에 이스케이프하여 XSS 공격을 방지한다. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. XSS공격은 어떤 공격일까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. XSS(교차 사이트 스크립팅) 공격은 악의적인 사용자가 웹 페이지에 스크립트 코드를 삽입하여 다른 사용자의 브라우저에서 실행시키는 공격입니다. 이 공격을 통해 공격자는 사용자의 세션 정보를 탈취하거나, 웹 페이지의 내용을 변조하거나, 악성 소프트웨어를 배포할 수 있습니다! |
||
|
||
``` | ||
const title = response.potentiallyMaliciousInput; | ||
const element = <h1>{title}</h1>; // 안전함 | ||
``` | ||
|
||
--- | ||
|
||
## React에서 객체 업데이트 방법 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 리액트에서 컴포넌트가 재렌더링 되는 때는 어떤 경우일까요 ?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 먼저 컴포넌트의 Props나 State가 변경되면, React는 해당 컴포넌트를 리렌더링합니다. 이 때, 부모 컴포넌트의 리렌더링도 자식 컴포넌트의 리렌더링을 유발할 수 있다고 합니다! |
||
|
||
상태를 **읽기 전용**으로 다루어야 하며, 기존 객체를 변경하는 대신 새로운 객체를 생성해야 한다. | ||
|
||
React는 state 설정 함수 (setState 같이)가 없으면 객체가 변경되었는지 알 수 없다. 따라서 React는 아무것도 하지 않는다. | ||
|
||
그렇기에 렌더링 시에 접근하려는 state 값은 **읽기 전용**처럼 다루어야 한다. | ||
|
||
## 불변성이란? | ||
|
||
불변성은 객체의 상태를 직접 변경하지 않고, 새로운 객체를 생성하여 업데이트 하는 원칙이다. | ||
|
||
React에서 배열 상태 업데이트 할 때, 불변성을 지키지 않은 경우이다. | ||
|
||
``` | ||
const [items, setItems] = useState([1, 2, 3]); | ||
|
||
// 배열을 직접 수정 | ||
items.push(4); // 권장하지 않음 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 왜 권장하지 않는지 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 배열을 직접 수정하면 React가 상태 변경 수정을 감지하지 못하게 되어 UI 업데이트가 발생하지 않아 버그를 초래할 수 있거나 변경을 감지하지 못해 불필요한 렌더링이 발생할 수 있다고 합니다! const Counter = () => {
}; export default Counter;` 위의 예시 코드에서 increment 함수에서 현재 count의 값을 클로저로 캡처하여 사용할 수 있습니다. Closure에 대해 알 수 있어 좋은 공부가 되었습니다! 감사합니다! |
||
setItems(items); // React는 변경을 감지하지 못함 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 왜 React에서는 해당 부분 변경을 감지하지 못할까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 말씀해주신 참조 비교를 찾아본 내용입니다! |
||
``` | ||
|
||
React에서 배열 상태를 업데이트 할 때, 불변성을 지킨 경우이다. | ||
|
||
``` | ||
const [items, setItems] = useState([1, 2, 3]); | ||
|
||
// 새로운 배열을 생성 | ||
const newItems = [...items, 4]; | ||
setItems(newItems); // React는 변경을 감지하고 리렌더링 | ||
|
||
``` | ||
|
||
이렇게 새로운 배열인 newItems를 생성하여 setItems로 상태를 업데이트를 했다. | ||
|
||
불변성을 유지하는 것은 코드의 안정성, 예측 가능성, 디버깅 용이성을 높이는 데 중요한 역할을 하므로 반드시 불변성을 염두에 두고 코드를 작성하는 것이 좋다. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 불변성을 유지하는 방법으로는 어떤 것이 있을까요 ?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 찾아본 바로는 |
||
|
||
## 객체 전개 구문 | ||
|
||
객체의 전개 구문을 사용하면 기존 객체의 프로퍼티를 쉽게 복사할 수 있다. | ||
|
||
``` | ||
setPerson({ | ||
|
||
...person, // 이전 필드를 복사 | ||
|
||
firstName: e.target.value // 새로운 부분은 덮어쓰기 | ||
|
||
}); | ||
``` | ||
|
||
위의 코드를 통해 단 한 개의 필드만 수정하고, 나머지 모든 필드는 이전 값을 유지하고 싶을 때 유용한 방법이다. | ||
|
||
* 주의: ...전개 문법은 얕다. 빠르지만, 중첩된 프로퍼티를 업데이트하고 싶다면 한 번 이상 사용해야 한다. | ||
|
||
## Immer 사용 | ||
|
||
Immer를 사용하면 상태 업데이트를 간결하게 관리할 수 있다. Immer는 내부적으로 변경 사항을 기록하여 새로운 객체를 생성한다. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Immer라는 라이브러리를 언급하셨는데 해당 부분에서 라이브러리 언급을 하셨다면 간단하게 사용하는 이유에 대해서도 설명하면 좋을 것 같아요. 가령 Immer 사용이 필요없는 상황도 있을텐데 어떤 경우에 해당 라이브러리를 사용하는지, 이 라이브러리를 사용하면 기존에 비해 어떻게 좋아지는지 등을 파악해야한다고 생각합니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Immer는 상태 업데이트를 간결하게 관리할 수 있도록 도와주는 라이브러리인데요, 주로 불변성 유지 (상태를 직접 수정하지 않고, 변경 사항을 기록하여 새로운 객체를 생성하여), 가독성 향상 (스프레드 연산자 사용 같은 기존의 불변성 유지 방법보다 코드를 더 간결하게 작성할 수 있다), 복잡한 상태 관리 (중첩된 객체나 배열을 다룰 때 더 쉽게 처리 가능) 같은 이유로 사용된다고 합니다. |
||
|
||
--- | ||
|
||
## 1. Props 전달하기 | ||
|
||
부모 컴포넌트는 JSX 태그에 props를 추가하여 자식 컴포넌트에 정보를 전달한다. | ||
|
||
예를 들어 | ||
|
||
``` | ||
... | ||
<Avatar person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} size={100} /> | ||
``` | ||
|
||
처럼 person(객체)와 size (숫자)를 전달할 수 있다. | ||
|
||
## 2. props 읽기 | ||
|
||
자식 컴포넌트에서 구조 분해 할당을 통해 전달된 props를 읽는다. | ||
|
||
``` | ||
function Avatar({ person, size }) { | ||
|
||
// person과 size는 이곳에서 사용가능합니다. | ||
|
||
} | ||
``` | ||
|
||
function Avatar 바로 뒤의 person, size 등을 쉼표로 구분하여 읽을 수 있다. | ||
|
||
이렇게 하면 Avatar 코드 내에서 변수를 사용하는 것처럼 사용할 수 있다. | ||
|
||
## 3. 기본값 지정하기 | ||
|
||
props에 기본값을 설정할 수 있다. 예를 들어, `size = 100`과 같이 하면 size가 전달되지 않았을 때 기본값으로 100이 사용된다. | ||
|
||
## 4.JSX로 자식 전달하기 | ||
|
||
JSX 태그 내에 자식 요소를 중첩하면, 부모 컴포넌트는 이 자식을 `children` prop으로 받을 수 있다. | ||
|
||
``` | ||
<Card> | ||
|
||
<Avatar /> | ||
|
||
</Card> | ||
``` | ||
|
||
## 5. 시간에 따른 props 변하는 방식 | ||
|
||
props는 컴포넌트가 렌더링될 때마다 새로운 값을 받을 수 있으며, 이는 변경할 수 없는 불변성을 가진다. 상태가 필요한 경우 state를 사용해야 한다. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Props를 사용하는 이유와 장단점, 자식 컴포넌트가 많아졌을때 props에 대한 처리방법에 대해 생각해보면 좋을 것 같아요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Props는 데이터 전달 (부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달), 재사용성 (컴포넌트를 재사용 할 수 있으며, 다양한 데이터를 받아 동일한 컴포넌트를 여러 번 사용할 수 있다), 불변성 유지 (props는 불변성을 가지므로, 자식컴포넌트 내에서 변경되지 않고 안정적인 데이터 전달을 보장)의 이유로 사용합니다!
단점으로는
자식 컴포넌트가 많아졌을 때,
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# 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? |
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 |
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 }, | ||
], | ||
}, | ||
}, | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class대신 className으로 사용해야하는 이유는 무엇인가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
어라 위의 방금 내용 Resolve conversation을 잘못 눌러버렸네요 ㅠㅠ
아무튼 JSX에서 class 대신 className을 사용하는 이유는 예약어 충돌 때문입니다!
class는 ES6(ECMAScript 2015)에서 도입된 자바 스크립트의 예약어로, 클래스 정의에 사용하는데, JSX는 자바스크립트의 문법을 기반으로 하기 때문에, class를 속성 이름으로 사용할 경우 문법적으로 문제가 발생할 수 있기에 className으로 사용합니다!