효뚜르팝의 Dev log
[React 공식문서로 공부하기] Describe the UI 본문
작년에 새롭게 개편된 React 공식문서를 읽으며 다시 리액트에 대한 기반을 다져보기로 했다.
그동안 회사에서건 사이드 프로젝트에서건 리액트를 줄곧 써왔지만 아직도 모르는 게 많다. 예를 들어 리액트에서 로딩이 느린 성능을 어떻게 개선할 지, 리액트가 어떤 동작원리에 기반하고 있는지, 리렌더링은 어떻게 동작하는 지 누군가 질문을 던진다면 바로 대답하기가 어렵다. 원초적인 동작원리부터 차근차근 다시 공부를 해야겠다는 생각이 들었다.
리액트 스터디는 지난 번 리팩토링 스터디를 함께 했던 근휘님, 민주님과 함께 하기로 하였다.
우선 공식문서부터 각자 공부해보고 공부한 것들에 대해 설명을 해주고, 공식문서 공부를 다하고나면 리액트 관력 책을 공부해볼 예정이다. (사실 리액트 말고도 하고 싶고 해야할 공부는 아주 많다. 아키텍처, 클린코드, 테스트 코드 등등... ^^ 아직도 잘 모르겠는 부분 투성이다. 기초가 탄탄한 개발자가 되고 싶다. 세상에 쓸모없는 공부는 없으니 하나씩 도장깨기 한다는 느낌으로다가 공부를 조금씩 하고 이 곳에 기록하고자 한다.)
개편된 React 공식 문서 : https://react-ko.dev/learn/describing-the-ui
UI 구성하기 – React
The library for web and native user interfaces
react-ko.dev
이 글에서는 UI 구성하기 챕터를 읽고 공부한 내용을 기록할 예정이다.
Describing the UI - UI 구성하기
React는 사용자 인터페이스(UI)를 렌더링하기 위한 JavaScript 라이브러리
1. Your First Component
React 컴포넌트는 마크업으로 뿌릴 수 있는 JavaScript 함수
컴포넌트를 빌드하는 방법
1. 컴포넌트 내보내기
export default // 표준 JavaScript 구문
2. 함수 정의하기
function Profile() { }
3. 마크업 추가하기
<div/> 는 HTML처럼 작성되었지만 실제로는 JavaScript이다. 이 구문을 JSX라고 하며, JavaScript 안에 마크업을 삽입할 수 있다.
return (
<div>
example
</div>
);
- <section>, <div> 등 은 소문자이므로 React는 HTML 태그를 가리킨다고 이해한다.
- <Profile /> 은 대문자 P 로 시작하므로 React는 Profile 이라는 컴포넌트를 사용하고자 한다고 이해한다.
2. Importing and Exporting Component
- Create React App에서는 앱 전체가 src/App.js에서 실행된다. 설정에 따라 root 컴포넌트가 다른 파일에 위치할 수도 있다.
- Next.js처럼 파일 기반으로 라우팅하는 프레임워크일 경우 페이지별로 root 컴포넌트가 다를 수 있다.
3. Writing Markup with JSX
- React에서 렌더링 로직과 마크업이 같은 위치의 컴포넌트에 함께 있는 이유?
- 웹이 더욱 인터렉티브해지면서 로직이 컨텐츠를 결정하는 경우가 많아졌다. 그래서 Javascript가 HTML을 담당하게 됨 - JSX와 React는 서로 다른 별개의 개념. 종종 함께 사용되기도 하지만 독립적으로 사용할 수도 있음. JSX는 구문 확장이고, React는 JavaScript 라이브러리.
- 여러 JSX 태그를 하나로 감싸줘야 하는 이유?
- JSX는 HTML처럼 보이지만 내부적으로는 JavaScript 객체로 변환된다. 하나의 배열로 감싸지 않은 하나의 함수에서는 두 개의 객j체를 반환할 수 없음. 따라서 또 다른 태그나 Fragment로 감싸지 않으면 두 개의 JSX태그를 반환할 수 없다.
(참고 : Fragment는 DOM에서 사라짐) - JSX에서 대부분 camelCase로 쓰는 이유? (ex. className)
- JSX는 JavaScript로 바뀌고 JSX로 작성된 어트리뷰트는 JavaScript 객체의 키가 된다. JavaScript에는 변수명에는 대시를 포함하거나 class처럼 예약어를 사용할 수 없다는 제약이 있기 때문.
4. Javascript in JSX with Curly Braces
- 중괄호를 사용하면 JavaScript 로직과 변수를 마크업으로 가져올 수 있다.
- `{{` 와 `}}` 는 특별한 구문이 아니라 JSX 중괄호 안에 들어 있는 JavaScript 객체이다.
5. Passing Props to a Component
- Props는 읽기 전용 스냅샷으로, 렌더링할 때마다 새로운 버전의 props를 받는다.
- Props는 변경할 수 없다. 상호작용이 필요한 경우 state를 설정해야 한다.
6. Conditional Rendering
다음의 두 조건부 렌더링이 동일할까?
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);
-> JSX 요소는 내부 state를 보유하지 않고 실제 DOM 노드가 아니기 때문에 “인스턴스”가 아니다. 청사진과 같은 개념으로 보면 된다. 이 두 예제는 완전히 동등하다.
7. Rendering Lists
- map() 호출 내부의 JSX 요소에는 항상 key가 필요
- key는 각 컴포넌트가 어떤 배열 항목에 해당하는지 React에 알려주어 나중에 매칭할 수 있도록 한다. 이는 배열 항목이 (정렬 등으로 인해) 이동하거나, 삽입되거나, 삭제될 수 있는 경우 중요해짐. 잘 만들어진 key는 React가 정확히 무슨 일이 일어났는지 추론하고 DOM 트리를 올바르게 업데이트하는 데 도움이 됨.
- 로컬에서 key 생성하려면 crypto.randomUUID()또는 uuid와 같은 패키지 등을 사용할 수 있다. - Key 규칙
- 형제 간에 고유 / 변경되지 않아야 함 (렌더링 중 생성하면 안됨)
8. Keeping Components Pure
일부 JavaScript 함수는 순수하다. 순수 함수는 계산만 수행하고 그 이상은 수행하지 않는다. 컴포넌트를 엄격하게 순수 함수로만 작성하면 코드베이스가 커짐에 따라 당황스러운 버그와 예측할 수 없는 동작을 피할 수 있다.
- 순수함수의 특징
- 자신의 일에만 신경쓴다. (호출되기 전에 존재했던 객체나 변수를 변경하지 않는다. )
- 동일 입력, 동일 출력 (동일한 입력이 주어지면 항상 동일한 결과를 반환해야 한다.
React는 모든 컴포넌트가 순수하다고 가정한다. 작성하는 React 컴포넌트는 동일한 입력이 주어졌을 때 항상 동일한 JSX를 반환해야 한다.
- StrictMode로 순수하지 않은 계산 감지하기
- React에서는 렌더링하는 동안 props, state, context를 읽을 수 있다. 무언가 변경하려면 state를 설정해야 함. 컴포넌트가 렌더링되는 동안에는 기존 변수나 객체를 절대 변경해서는 안 됨.
- React는 개발 환경에서 각 컴포넌트의 함수를 두 번 호출하는 “Strict Mode”를 제공. Strict Mode는 컴포넌트 함수를 두 번 호출함으로써 이러한 규칙을 위반하는 컴포넌트를 찾아내는 데 도움이 된다. (상용 환경에서는 아무런 영향을 미치지 않으므로 사용자의 앱 속도가 느려지지 않음)
- Side Effect
- 화면 업데이트, 애니메이션 시작, 데이터 변경과 같은 이러한 변경. 렌더링 중에 일어나는 것이 아니라 '부수적으로' 일어나는 것
- 사이드이펙트는 보통 이벤트 핸들러에서 일어남. 이벤트 핸들러는 렌더링 중에 일어나진 않기 때문에 순수할 필요가 없다.
- 다른 모든 옵션을 다 사용했는데도 사이드 이펙트에 적합한 이벤트 핸들러를 찾을 수 없다면, 컴포넌트에서 useEffect 호출을 통해 반환된 JSX에 이벤트 핸들러를 첨부할 수 있다. 이렇게 하면 나중에 렌더링 후 사이드 이펙트가 허용될 때 React가 이를 실행하도록 지시함. 하지만 이 방법은 최후의 수단으로 사용해야 함.
- React가 순수성을 중시하는 이유?
- 컴포넌트를 다른 환경(예: 서버)에서 실행할 수 있다 동일한 입력에 대해 동일한 결과를 반환하기 때문에 하나의 컴포넌트가 많은 사용자 요청을 처리할 수 있음.
- 입력이 변경되지 않은 컴포넌트는 렌더링 건너뛰기(memo)를 통해 성능을 향상시킬 수 있음. 순수 함수는 항상 동일한 결과를 반환하므로 캐싱해도 안전함.
- 깊은 컴포넌트 트리를 렌더링하는 도중에 일부 데이터가 변경되면 React는 오래된 렌더링을 완료하기 위해 시간을 낭비하지 않고 렌더링을 다시 시작할 수 있음. 언제든지 계산을 중단해도 안전함.
'TIL' 카테고리의 다른 글
| [React 공식문서로 공부하기3] Managing State (1) | 2024.02.25 |
|---|---|
| [React 공식문서로 공부하기2] Adding Interactivity 상호작용 추가하기 (1) | 2024.02.20 |
| PoC를 진행할 때 유의할 점에 대해서 (3) | 2024.02.04 |
| 디자인 시스템 구축을 위해 Shadcn UI와 Radix Theme PoC 진행해보기 (2) | 2024.01.21 |
| github workflow를 통해 ci cd 개발 환경 구축하기 (2) | 2024.01.02 |