728x90
이 글은 Udemy의 【한글자막】 React 완벽 가이드 2025 with React Router & Redux 를 수강하고 정리한 내용입니다.
🎈Componet
- 재사용이 가능한 구성요소이다.
- HTML, CSS, 자바스크립트 로직 등을 포함하고 있다.
- 사용하는 이유
- 컴포넌트가 없다면 html 코드가 방대하고 복잡해져 유지보수가 어려워질 수 있다.
- 오류 가능성이 줄어든다.
- 코드를 재활용 하는 방식이기 때문에 한 부분에서 일괄적으로 수정이 가능하다.
- 공통된 기능을 제공하는 유사한 코드가 묶여 작성되어 개발 과정이 단순해진다.
- 각 컴포넌트들 마다 각 기능별로 관심사가 분리되어 작업된다.
- 컴포넌트 저장 및 좋은 프로젝트 구조
- src - assets - components - Header - Header.jsx - Header.css - App.jsx
🎈JSX
- JavaScript Syntax Extention, JavaScript 의 확장된 문법
- 함수를 추가하여 컴포넌트 생성이 가능하다.
- JSX 문법은 브라우저에서는 사용이 불가능하지만 리액트 개발을 위해 작성하는 코드로 브라우저에 도달하기 전에 개발 서버에서 브라우저에서 사용 가능 하도록 변환된다.\
- 컴포넌트로 인식되기 위한 규칙
- 함수의 제목이 대문자로 시작
- 함수의 반환 값이 렌더링이 가능한 값(즉, 화면에 보여져야 하는 내용)
// App.jsx
// Header 컴포넌트 생성
function Header() {
return ( // 반호나 값이 여러줄인 경우 괄호로 묶기
<header>
<img src="src/assets/react-core-concepts.png" alt="Stylized atom" />
<h1>React Essentials</h1>
<p>
Fundamental React concepts you will need for almost any app you are going to build!
</p>
</header>
);
}
// Header 컴포넌트 사용
<Header></Header>
// or
<Header/>
🎈Element Rendering
- Element 는 React 의 가장 작은 단위를 의미한다. (Element는 Componet의 “구성요소”) const element = <h1>Hello, world</h1>;
- 리액트로 구현된 어플리케이션은 일반적으로 하나의 루트 DOM 노드가 존재한다. <div id="root"></div>
- 이 루트 DOM 노드에 들어가는 모든 엘리먼트들을 React DOM에서 관리한다.
- 리액트 엘리먼트를 렌더링 하기 위해서는 DOM 엘리먼트를 ReactDOM.createRoot()에 전달한 다음, React 엘리먼트를 root.render()에 전달해야 한다.
const root = ReactDOM.createRoot( document.getElementById('root') ); const element = <h1>Hello, world</h1>; root.render(element);
- import ReactDOM from "react-dom/client"; import App from "./App"; import "./index.css"; const entryPoint = document.getElementById("root"); ReactDOM.createRoot(entryPoint).render(<App />);
- 컴포넌트 계층구조를 의미하는 컴포넌트 트리는 리액트를 통해 화면으로 렌더링 될 뿐, 커스텀 컴포넌트는 실제로 렌더링된 DOM에 나타나지 않는다.
🎈동적 값 출력 및 활용
- jsx 또는 리액트에 중괄호{}를 사용하여 동적인 값을 출력 가능
- 요소 태그 사이에 넣을 수도 있고, 속성 값으로서도 사용할 수 있다.
- 단, 동적인 값을 표현할때 따옴표를 작성하지 않는다.
<p>{동적인 값의 변수}</p>
<img src={동적인 값의 변수}/>
const reactDescriptions = ["Fundamental", "Crucial", "Core"];
function genRandomInt(max) {
return Math.floor(Math.random() * (max + 1));
}
function Header() {
return (
<header>
<img src="src/assets/react-core-concepts.png" alt="Stylized atom" />
<h1>React Essentials</h1>
<p>
{reactDescriptions[genRandomInt(2)]} React concepts you will need for
almost any app you are going to build!
</p>
</header>
);
}
- 이미지를 가져오는 최적의 방법 - import
- 이미지를 이런 식으로 불러올 경우 배포 시 이미지 파일이 무시되거나 유실 될 수 있다.
- 여러 추가적인 최적화 단계를 사용할 수 없다.
import reactImg from './src/assets/react-core-concepts.png'; ... <img src={reactImg} alt="Stylized atom" />
- <img src="src/assets/react-core-concepts.png" alt="Stylized atom" />
🎈Prop(속성)
- Prop는 부모 → 자식 컴포넌트로 데이터를 전달하는 방법 (부모 → 자식 방향으로만 데이터 전달 가능)
- 읽기 전용이므로 자식 컴포넌트에서 prop 값을 변경 불가능하다.
- 일반적으로 props 라고 불리는 하나의 매개변수(변수명수정가능)만 사용해서 데이터를 전달할 때는 커스텀 특성은 key로 속성의 값은 value 형태로 객체화 되어 저장된다.
// 부모
function App() {
return (
...
<CoreComcept title="Components" description="blablabla" image ={Img} />
// or
<CoreComcept {...CORE_CONCEPT[0]} /> // 스프레드 연산자 사용
...
);
// 자식
function CoreComcept (props) {
return (
<img src={props.image} />
<h3> {props.title}</h3>
<p>{props.descriptsion>/<p>
);
}
// 구조분해 한 방식
function CoreComcept ({image, title, description}) { //
return (
<img src={image} />
<h3> {title}</h3>
<p>{description}>/<p>
);
}
🎈Children Prop
- 컴포넌트 태그 사이의 텍스트를 저장하는 prop
- prop의 명이 무조건 children이어야 함.
<TapButton>buttonName</TapButton>
------------------------------
export default function TapButton(props) {
return <button>{props.childeren}</button>; // props.childeren === buttonName
// or
export default function TapButton({childeren}) { // 객체 구조분해
return <button>{childeren}</button>; // props.childeren === buttonName
🎈 Event 처리
- button 태그의 on ~ 으로 시작하는 prop 추가 (ex)onClick)
- 커스텀 컴포넌트인 TabButton의 propd으로 생성한 onSelect는 개발자 임의로 명칭을 변경가능하다.
- on ~ 으로 시작하는 이벤트 prop(여기서는 onClick)의 값은 함수. (onSelect 속성 값을 onClick으로 넘겨줌으로 여기서는 onSelect 를 예시로 든다.)
- onSelect=handleSelect() 와 같이 소괄호를 붙이지 않는다. 이 경우 handleSelect()의 반환 값이 속성의 값으로 전달되어 렌더링 될 때 바로 실행되기 때문
- onSelect=hadleSelect 와 onSelect={() => handleSelect('component')} 두 방식은 함수의 참조값을 전달하며 두 방식의 차이는 매개변수를 넘길 수 있다, 없다 의 차이를 가진다.
- TapButton을 실행하면 handleSelect 함수가 실행
// App.jsx
function App() {
function handleSelect(selectedButton) {
// selectedButton => component, jsx, props, state
}
return (
<TapButton onSelect={() => handleSelect('component')}>component</TapButton>
<TapButton onSelect={() => handleSelect('jsx')}>jsx</TapButton>
<TapButton onSelect={() => handleSelect('props')}>props</TapButton>
);
}
------------------------------
export default function TapButton({childeren , onSelect}) {
return <button onClick={onSelect}>{childeren}</button>;
}
🎈UI가 업데이트 되지 않는 이유 - State를 사용하는 이유
// App.jsx
function App() {
let tabContent = "hello";
function handleSelect(selectedButton) {
tabContent = selectedButton;
console.log(tabConent)
}
return (
<TapButton onSelect={() => handleSelect('component')}>component</TapButton>
{tabContent}
);
}
------------------------------
export default function TapButton({childeren , onSelect}) {
return <button onClick={onSelect}>{childeren}</button>;
}
- App.jsx의 component 버튼을 누르면 handleSelect 함수를 통해 tabContent의 값이 “component”로 변경 될 것이다. 그리고 {tabContent}의 내용의 hello 에서 component로 변경될 것이라 예상하지만 아무리 버튼을 눌러도 콘솔에 찍히는 로그만 component로 변경되어 찍힐 뿐, 화면의 텍스트는 바뀌지 않는 것을 확인할 수 있다.
- 그 이유는 handleSelect 함수가 실행되었어도 변수만 변경될 뿐, App 컴포넌트 함수가 실행되지 않아 UI가 업데이트 되지 않는 것이다.
- 그러므로 App 컴포넌트 함수가 재실행 되어야 한다는 것을 리액트에게 알려줄 필요가 있다.
- 이는 State 를 이용하여 구현 가능하다.
🎈State(상태) & Hook(훅)
- use ~ 로 시작하는 모든 함수는 리액트 Hook 이다.
- Hook은 컴포넌트 함수 또는 다른 리액트 Hook에서만 호출 될 수 있다.
- Hook은 컴포넌트 함수 최상위에서 호출해야하며 내부 함수나 if문 또는 loop문 안에 중첩되어선 안된다.
- 리액트 라이브러리의 useState 라는 함수의 도움을 받아 리액트에게 데이터가 변한 것을 알려주면 리액트가 UI를 업데이트 하도록 한다.
- useState Hook은 일부 컴포넌트에 연결된 상태를 관리하는데, 일부 데이터가 변경되면 이 Hook이 자신이 속한 컴포넌트 함수를 활성화 하여 리액트에 의해 재검토하게 된다.
- useState의 반환 값은 배열로, 첫번째 요소는 컴포넌트 실행 주기의 현재 데이터 값이며, 두번째 요소는 이 상태를 업데이트 하기 위해 실행되는 함수이다. 두번째 요소인 함수가 호출되면 리액트에 컴포넌트 함수가 다시 실행되어야 함을 알려준다.
import {useState} from 'react';
function App() {
const [selectedTopic, setSeletedTopic] = useState("hello");
function handleSelect(selectedButton) {
setSeletedTopic(selectedButton);
console.log(selectedTopic)
}
return (
<TapButton onSelect={() => handleSelect('component')}>component</TapButton>
{selectedTopic}
);
}
🎈조건적 콘텐츠 렌더링
import {useState} from 'react';
function App() {
const [selectedTopic, setSeletedTopic] = useState("hello");
function handleSelect(selectedButton) {
setSeletedTopic(selectedButton);
console.log(selectedTopic)
}
return (
...
{!selectedTopic ? <p>hello</p> : <p>{EXAMPLES[selectedTopic].title}</p>}
// or
{!selectedTopic && <p>hello</p>}
{selectedTopic && <p>{EXAMPLES[selectedTopic].title}</p>}
);
}
🎈Css 스타일링 및 동적 스타일링
- jsx 에서는 버튼에 클래스를 추가하기 위해서는 className을 사용한다.
// App.jsx
function App() {
const [selectedTopic, setSeletedTopic] = useState("hello");
function handleSelect(selectedButton) {
setSeletedTopic(selectedButton);
console.log(selectedTopic)
}
...
return (
<TapButton isSelected={isSelected==='component'}
onSelect={() => handleSelect('component')}>component</TapButton>
);
}
------------------------------
export default function TapButton({childeren , onSelect, isSelected}) {
return <button className={isSelected ? 'active' :undefined} onClick={onSelect}>{childeren}</button>;
}
🎈List 데이터 동적 츨력
- .map 함수를 이용하여 list 의 수만큼 자동으로 컴포넌트가 출력할 수 있도록 수정
- .map 함수를 이용하여 list 데이터를 출력 할때 각 항목을 식별할 수 있는 key를 부여하면 리액트가 변경을 효율적으로 감지하며 key 값을 기준으로 어떤 요소가 변경, 추가, 삭제 되었는지 판단하기 때문에 불필요한 리렌더링을 방지하고, 렌더링 성능을 최적화 할 수 있다.
- key 속성이 없다면 매번 전체 리스트를 다시 렌더링하여 불필요한 렌더링이 발생하고, 리스트 중간에 요소가 추가, 삭제 되는 경우 모든 항목을 다시 그릴 수 있어 성능 저하에 발생한다.
// 부모
function App() {
return (
...
<CoreComcept title="Components" description="blablabla" image ={Img} />
// or
<CoreComcept {...CORE_CONCEPT[0]} /> // 스프레드 연산자 사용
...
// or
{CORE_CONCEPT.map((conceptItem) => <CoreComcept key={conceptItem.title} {...CORE_CONCEPT[conceptItem]} /> ) // map 함수로 list 동적 출력
);
반응형
'Programming > React' 카테고리의 다른 글
[React] React 완벽 가이드 - 섹션 5: React로 투자 계산기 만들기 | 개발 회고 (0) | 2025.03.18 |
---|---|
[React]스프레드 연산자를 통한 속성 전달 방식- id 전달 (0) | 2025.03.12 |
[React] 함수형 컴포넌트의 반환 return 값 조건 & Fragment(프래그먼트) <>...</> (0) | 2025.03.11 |
[React] Element와 Componet의 차이 (0) | 2025.03.11 |
[React] React 완벽 가이드 - 섹션 1: 시작하기 (0) | 2025.02.15 |