이나의 공부 블로그
[TIL] D+56 리액트 입문 완강~! 본문
1️⃣ 리액트 입문 2주차
state의 불변성부터
📌 불변성
리액트 State를 이해하기 위해 꼭 필요한 개념인 불변성.
불변성이란 메모리에 있는 값을 변경할 수 없는 것을 뜻한다.
쉽게 풀어서 말하면 state를 직접 변경하지 않고 기존 것을 복사해서 새로운 값을 만들어 바꾸는 것이다.
<불변성을 지켜야하는 이유>
리액트는 화면을 업데이트 할 때 이전 값과 새 값이 다르다는 것을 빠르게 인식해야한다.
만약 state를 직접 바꿔버리면 리액트는 값이 바뀐 것을 인식하지 못해서
화면을 업데이트하지 못하거나 오류가 발생할 수 있다.
❌ 잘못된 방법(불변성을 지키지 않은 경우)
function App() {
const [numbers, setNumbers] = useState([1, 2, 3]);
const addNumber = () => {
numbers.push(4); // 기존 배열을 직접 수정 (안돼요!)
setNumbers(numbers); // 이렇게 하면 리액트가 업데이트를 못 알아차림
};
return (
<div>
<button onClick={addNumber}>숫자 추가</button>
<p>{numbers.join(', ')}</p>
</div>
);
}
push()
를 사용하여 기존 배열을 바꿨다.
이런 경우 리액트는 "배열 자체는 여전히 같은 객체"라고 생각해서 화면 업데이트를 건너뛸 수 있다.
⭕️ 올바른 방법(불변성을 지킨 경우)
function App() {
const [numbers, setNumbers] = useState([1, 2, 3]);
const addNumber = () => {
const newNumbers = [...numbers, 4]; // 새 배열 생성 (불변성 유지)
setNumbers(newNumbers); // 새 배열로 state 업데이트
};
return (
<div>
<button onClick={addNumber}>숫자 추가</button>
<p>{numbers.join(', ')}</p>
</div>
);
}
[...numbers,4]
로 기존 배열을 복사하고 새로운 숫자를 추가했다.
이렇게 하면 리액트가 "새로운 값이 생겼다"는 것을 알아차리고 화면을 제대로 업데이트 한다.
📌 컴포넌트
1) 컴포넌트는 리액트의 핵심
리액트에서 개발할 모든 애플리케이션은 컴포넌트라는 조각으로 구성된다.
컴포넌트는 UI 구축 작업을 훨씬 쉽게 만들어준다.
컴포넌트는 리액트의 핵심 빌딩 블록 중 하나로
UI 요소를 표현하는 최소한의 단위이며 화면의 특정 부분이 어떻게 생길지 정하는 선언체이다.
2) 명령형 프로그래밍 VS 선언형 프로그래밍
2-1) DOM (명령형 프로그래밍)
명령형으로 작성된 코드는 Hello,World!를 출력하기 위해
컴퓨터가 수행해야하는 절차를 일일히 코드로 작성해주어야한다.
// Hello, World! 화면에 출력하기
// 순수 javaScript 명령형 코드
const root = document.getElementById('root');
const header = document.createElement('h1');
const headerContent = document.createTextNode(
'Hello, World!'
);
header.appendChild(headerContent);
root.appendChild(header);
2-2) 리액트 (선언형 프로그래밍)
리액트 코드의 경우, 내가 UI를 선언하고 render 함수를 호출하면
리액트가 알아서 절차를 수행해 화면에 출력해준다.
화면에 어떻게 그려야할지는 리액트 내부에 잘 숨겨져 추상화 되어있다.
// React 코드 (선언적인)
const header = <h1>Hello World</h1>; // jsx
ReactDOM.render(header, document.getElementById('root'));
명령형 프로그래밍 코드가 나쁜 것은 아니지만
더 복잡한 UI 시스템에서는 관리가 기하급수적으로 어려워진다.
📌 렌더링
리액트에서 렌더링이란, 컴포넌트가 현재 props와 state의 상태에 기초하여
UI를 어떻게 구성할지 컴포넌트에게 요청하는 작업을 의미한다.
UI가 음식 / 컴포넌트가 주방장 / 리액트가 웨이터라고 치면
- 렌더링을 일으키는 것은 triggering - UI를 주문하고 주방으로 전달하는 것
- 렌더링 하는 것은 rendering - 주방에서 컴포넌트가 UI를 만들고 준비하는 것
- 렌더링 결과를 실제 DOM에 커밋하는 것은 commit - 리액트가 준비된 UI를 손님 테이블에 올려놓는 것
1️⃣ 렌더링 트리거
렌더링이 발생하는 경우는 크게 두 가지, 세세하게는 네 가지로 볼 수 있다.
1. 첫 리액트 앱을 실행했을 때
2. 현재 리액트 내부에 어떤 상태(state)가 변경되었을 때.
- 컴포넌트 내부 state가 변경되었을 때
- 컴포넌트에 새로운 props가 들어올 때
- 상위 부모 컴포넌트에서 위 두가지 이유로 렌더링이 발생했을 때
리액트 앱이 실행되고 첫 렌더링이 일어나면 리액트는 컴포넌트의 루트에서부터 시작하여
아래 방향으로 훑으며 컴포넌트가 반환하는 JSX 결과물을 DOM 요소에 반영한다.
2️⃣ 리렌더링
첫 렌더링은 자동, 리액트 앱이 실행되면 리액트는 전체 컴포넌트를 렌더링하고
결과물을 DOM에 반영해 브라우저상에 보여준다.
첫 렌더링이 끝난 후 추가로 렌더링을 트리거 하려면 상태를 변경해주면 된다.
컴포넌트 상태에 변화가 생기면 리렌더링이 발생한다.
이 때 여러 상태가 변경되면 리액트는 이를 큐 자료 구조에 넣어 순서를 관리한다.
3️⃣ 브라우저 렌더링
브라우저의 렌더링과 리액트의 렌더링은 다른 독립적인 프로세스다.
렌더링이 완료되고 React가 DOM을 업데이트한 후 브라우저는 화면을 그린다.
이 프로세스를 "브라우저 렌더링" 또는 "페인팅"이라고 한다.
추후에 DOM과 virtualDOM을 배우며 자세히 살펴볼 예정
📌 DOM과 Virtual DOM
리액트나 뷰는 가상돔(Virtual DOM)을 사용해서 원하는 화면을 브라우저에 그려준다.
효율적인 자체 알고리즘을 사용해서 그리기 때문에 속도가 굉장히 빠른 편이다.
수 많은 컴포넌트로 구성된 웹페이지가 있다.
그 페이지를 문서(Document)라고 부르고,
페이지를 이루는 컴포넌트를 엘리먼트(Element)라고 부른다.
DOM은 이 엘리먼트를 트리 형태(DOM Tree)로 표현한 것이다.
트리의 요소 하나하나를 노드라고 부르고,
각각의 노드는 해당 노드에 접근과 제어(DOM 조작)를 할 수 있는 API를 제공한다.
*API : HTML 요소에 접근해서 수정할 수 있는 함수 정도로 이해하자
// id가 demo인 녀석을 찾아, 'Hello World!'를 대입해줘.
document.getElementById("demo").innerHTML = "Hello World!";
// p 태그들을 모두 가져와서 element 변수에 저장해줘
const element = document.getElementsByTagName("p");
// 클래스 이름이 intro인 모든 요소를 가져와서 x 변수에 저장해줘
const x = document.getElementsByClassName("intro");
⬆️대표적인 DOM API의 사용 예시
가상 DOM이란?
리액트는 가상 DOM을 이용해서 실제 DOM을 변경하는 작업을 효율적으로 수행한다.
웹페이지에서 어떤 요소를 수정하거나 추가할 때, 실제 DOM을 조작하는 것은 생각보다 느릴 수 있다.
DOM 조작은 브라우저가 다시 계산하고 화면을 그려야해서 시간이 많이 걸리기 때문이다.
1단계. 가상 DOM은 실제 DOM과 구조가 완벽히 동일한 복사본 형태를 만들어서(갱신 전/갱신 후 가상 DOM 두가지 버전)
2단계. 가상 DOM과 실제 DOM을 비교하여 바뀐 부분만 찾는다. (diffing)
3단계. 그리고 바뀐 부분만 모두 모아 실제 DOM에 적용한다. (reconciliation,Bath Update)
가상DOM은 실제 DOM은 아니지만,
객체 형태로 메모리에 저장되기 때문에 실제 DOM을 조작하는 것 보다 훨씬 더 빠르게 조작을 수행할 수 있다.
📌 브라우저 렌더링(페인팅)
위 내용에서 배운 주요 3가지 리액트 렌더링 순서
1. 가상 DOM 생성 : 리액트는 컴포넌트의 렌더 함수를 실행하여 가상 DOM을 새로 생성
2. 차이 비교(Diffing) : 새로운 가상 DOM과 이전 가상 DOM을 비교하여 실제 DOM에서 업데이트 해야할 부분을 찾는다.
3. 배치 업데이트(Reconciliation) : 변경된 부분만을 효율적으로 실제 DOM에 반영한다.
리액트가 실제 DOM을 업데이트하면, 이 변경 사항은 브라우저의 렌더링 엔진에 의해 화면에 반영된다.
브라우저 렌더링 과정은 다음과 같다.
1. 스타일 계산 : HTML과 CSS를 분석하여 각 요소의 스타일을 계산한다.
2. 레이아웃 : 각 요소의 위치와 크기를 계산한다.
3. 페인팅 : 레이아웃 단계에서 계산된 정보를 바탕으로 요소를 화면에 그린다.
브라우저 렌더링과 리액트의 렌더링은 엄연히 다른 독립적인 프로세스 !!
📌 카운터 앱 실습
허ㅏ거거거거거걱거거걱
다음 강의는 카운터 앱 실습이었는데 강의 멈춰두고 혼자 해봤다가 바로 성공해버려서 감격...
물론 완전히 혼자한 건 아니고 이전에 useState+onClick 내용 교안에 있던 거 보면서
살짝 고친 거긴 하지만...ㅎㅎ 이해는 했으니 이제 외우기만 하면 되쟈나?~!?!?
너무 신나서 오늘 공부 그만하고 싶다(안됨...)
📌 스타일링 및 refactoring 실습
진짜 너무 어려워서 토할 뻔 했다
컴포넌트 기본 스타일링과 반복적인 코드 줄이기,
너무 길거나 재사용 가능한 컴포넌트는 분리하는 방법을 배웠다
그 외에도 객체가 담긴 배열을 map을 활용해서 구현하기
정적 배열 데이터로 관리했던 유저 리스트를 useState를 활용하여 '상태값'으로 변경하기
onChange 활용해서 객체 추가/삭제하는 버튼 만들기
props.children 활용해서 버튼 색상 변경하기 << 제일 이해안감
등등...
너무 어려웠지만 여태까지 배운 내용들을 모두 복습할 수 있는 실습이라고 하니
여러번 살펴보고 수정도 도전해보자...
우와 ~ 리액트 입문 강의 다 들었다 ~ 👏
'스파르타 내일배움캠프 > 프로덕트 디자이너 트랙' 카테고리의 다른 글
[TIL] D+59 최종 프로젝트 시작!! (0) | 2025.01.13 |
---|---|
[TIL] D+57 리액트 숙련 시작...? (0) | 2025.01.09 |
[TIL] D+55 역대급으로 진도 못나간 날 (0) | 2025.01.07 |
[TIL] D+54 리액트 잘하는 사람 나였으면... (0) | 2025.01.06 |
[TIL] D+53 리액트 실습 이틀차... 금요일!!!!! (2) | 2025.01.03 |