1장
왜 리액트인가?
한때 자바스크립트는 단순한 스크립트 언어에 불과했지만 현재는 현재는 웹 애플리케이션의 핵심적인 역할을 한디. 프론트엔드 사이드에서 돌아가는 대규모 애플리케이션 구조를 관리할 때 순수하게 JS만으로 관리하기엔 힘들기 때문에 이를 해결하기 위해 Angular, Vue, Derby, pureMVC 등의 프레임워크들이 등장했다.
이러한 프레임 워크들은 주로 MVC, MVVM, MVW 아키택쳐로 애플리케이션을 구조화 한다.
→ 이러한 아키텍쳐들은 모두 모델 뷰가 있다. Model: DataBase(DB) 데이터가 저장되는 곳으로 애플리케이션에서 사용하는 데이터를 관리하는 영역
View: 사용자에게 보이는 영역으
Controller: 사용자에게 어떤 작업을 받으면 모델 데이터를 조회하거나 수정하고, 변경 사항을 뷰에 반영하는 영역
리액트는 MVC, MVW 등의 프레임워크와 달리, View만 신경 쓰는 라이브러리이다.
변경사항을 반영하는 과정에서 보통 '뷰를 변형'한다. 이때 애플리케이션 규모가 커질수록 복잡해지고 성능도 떨어질 수 있다. 따라서 페이스북 개발팀은 데이터가 변할 때마다 어떤 변화를 주는 것이 아니라 기존의 뷰를 날려 버리고 처음부터 새로 랜더링하는 방식을 고안해냈다. 이를 통해 어떻게 변화를 줄지 신경쓰지 않고, 뷰가 어떻게 생길지를 선언하고, 데이터의 변화가 있으면 기존의 것은 버리고 새로 랜더링만 하면 되게 된다. → 구조 간단, 작성해야 할 코드 양 줄어든다.
템플릿:
- 데이터셋이 주어지면 HTML 태그 형식을 문자열로 반환한다.
- 다른 프레임워크에서 사용자 인터페이스를 다룰 때 사용.
컴포넌트:
- 리엑트에서 특정 부분이 어떻게 생길지 전하는 선언체.
- 템플릿보다 더 복합적인 개념으로 재사용 가능한 API로 수많은 기능을 내장하며, 컴포넌트 하나에 생김새와 작동 방식 정의.
렌더링: 사용자 화면에 뷰를 보여주는 것.
리액트는 어떻게 성능을 아끼고 최적화 하는가?
앞서 용어 정리
초기렌더링: 리액트 컴포넌트가 최초로 실행한 것. 리렌더링: 컴포넌트의 데이터 변경으로 다시 실행되는 것
초기 렌더링
맨 처음 어떻게 보일지를 정하는 초기 랜더링이 필요 → 이를 다루는것이?
render함수 : 맨 처음 어떻게 보일지를 정하는 초기 랜더링을 다루는 함수
render() { ... }
- 컴포넌트가 어떻게 생겼는지 정의
- 뷰가 어떻게 생겼고 어떻게 작동하는지의 정보를 가진 객체를 반환
- 랜더함수 실행시 내부 컴포는트들 재귀적으로 랜더링
- 최상위 컴포넌트의 랜더링 작업 끝 → 이를 통해 HTML 마크업 만들기 → 실제 페이지의 DOM요소 안에 주입
조화 과정
그렇다면 리엑트에서 업데이트는 어떻게 하는가?
reder함수가 컴포넌트에서 데이터에 변화에 따라 새로운 요소로 갈아 끼운다.
리액트에서 뷰를 업데이트를 할 때 "조화 과정(reconciliation)"을 거친다.
render 함수는 뷰가 어떻게 생겼고 어떻게 작동하는지에 대한 정보를 지닌 객체를 반환
컴포넌트는 데이터를 업데이트했을 때 단지 값을 수정하는 것이 아니라 새로운 데이터를 가지고 render함수를 또 다시 호출 → 업데이트된 데이터를 지닌 새로운 뷰 생성
이전에 render함수가 만들었던 뷰 정보와 현대 render 함수가 만든 뷰 정보를 비교 후 DOM에 반영
리엑트에는 컴포넌트들이 가상의 돔트리 형태로 메모리상에 존재한다.
리엑트의 모든 구조들이 돔트리에 업데이트 되는것이 아니라 이전의 가상 돔트리와 비교해서 변경사항이 있는 부분만 계산을 하여 돔트리에 업데이트를 한다.
리액트의 특징
DOM이란?
Document Object Model
객체로 문서 구조를 표현하는 방법 (html로 작성) 웹 브라우저는 트리 구조의 DOM을 활용하여 객체에 JS와 CSS를 적용한다.
트리형태 → 특정 노드를 찾고, 수정, 제거, 삽입이 가능
문제점
동적 UI에 최적화되어 있지 않다 (html은 정적이며 자바스크립트를 사용해 이를 동적으로 만든다)
대규모 웹 애플리케이션에서 DOM에 직접 접근하여 변화를 주다 보면 성능 이슈 발생 (slow)
DOM 자체는 빠르나 브라우저에서 DOM에 변화가 있을때 브라우저가 CSS연산, 레이아웃 구성, 페이지 리페인트 과정에서 시간이 허비됨.
해결
HTML 마크업을 시각적인 형태로 변환하는 것은 웹 브라우저의 주역할이므로 컴퓨터 자원을 사용하는 것은 어쩔 수 없다.
→ DOM을 조최소한으로 조작하도록 하여 성능 개선, 리액트는 Virtual DOM 방식으로 DOM업데이트를 추상화하여 DOM처리 횟수를 최소화
Virtual DOM
Virtual DOM 사용 시 실제 DOM에 접근하여 조작하는 대신, 이를 추상화한 JS객체를 구성하여 사용. Like 실제 DOM의 사본
- 데이터를 업데이트하면 전체 UI를 Virtaul DOM에 리렌더링한다.
- 이전 Virtaul Dom에 있던 내용과 현재 내용을 비교한다.
- 바뀐 부분만 실제 DOM에 적용한다.
Virtaul DOM을 사용한다고 해서 무조건 빠른 것은 아니다. 적절한 곳에 사용해야 한다.
결국 리액트와 Virtual DOM이 제공하는 것은 업데이트 처리 간결성인 것이다. UI를 업데이트하는 과정에서 생기는 복잡함을 해소
기타 특징
리액트는 오직 뷰만 담당하는 라이브러리이다.
다른 프레임워크나 라이브러리와 혼용할 수 있으므로
리액트 라우터, axios, fetch, redux 등의 라이브러리로 빈자리를 채우면 된다.
2장
import logo from '~~';
다음과 같은 import 구문은 특정 파일을 불러오는 것을 의미한다.
리액트로 만든 프로젝트의 파일에서는 import를 사용해 다른 파일들을 불러올 수 있다.
이렇게 모듈을 불러와 사용하는것은 원래 브라우저에 없는 기능이나 브라우저가 아닌 환경에서 자바스크립트를 실행할 수 잇게 해주는 환경인 node.js 에서 지원하는 기능이다.
이러한 기능을 브라우저에서도 사용하기 위해 번들러를 사용한다. (파일을 묶듯이 연결)
번들러를 사용하면 import 로 모듈을 불러왔을 때 불러온 모듈을 모두 합쳐 하나의 파일을 생성 and 최적화 과정에서 여러 개의 파일로 분리될 수도 있음
대표적 번들러: 웹펙(편의성, 확장성이 뛰어나 리액트에서 주로 사용), parcel 등의 도구
웹팩 사용 시 SVG, CSS파일도 불러와 사용 가능
이렇게 파일들을 불러오는 것은 웹팩의 로더라는 기능이 담당
로더의 예:
- css-loader - css파일 불러옴
- file-loader - 웹 폰트, 미디어 파일 불러옴,
- babel-loader - 자바스크립트 파일들 불러오고 최신 js문법으로 작성된 코드 또는 jsx를 ES5 문법으로 변환 (구버전 웹 브라우저와 호환을 위해, jsx를 js로 바꾸기 위해)
JSX
JSX 자바스크립트의 확장 문법이며 XML과 매우 비슷하다. 이런 형식으로 작성한 코드는 브라우저에서 실행되기 전에 코드가 번들링 되는 과정에서 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환된다.
function App() {
return (
<div>
Hello 《b〉react</b〉
</div>
);
}
위와같이 작성된 코드는 다음과 같이 변환
function App() {
return React.createElement("div", null, "Hello ". React.createElement("b", null, "react"));
{
JSX의 장점
- 보기 쉽고 익숙하다
- 가독성이 작성하기도 쉽다.(html코드와 비슷)
- 더욱 높은 활용도
- html 태그 뿐만 아니라 컴포넌트도 JSX안에서 작성 할 수 있다.
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
ReactDoM.render: 컴포넌트를 페이지에 렌더링하는 역할. 첫 번째 파라미터에 JSX 형태로 페이지에 렌더링할 내용을 작성하고, 두 번째 파라미터 에 해당 JSX를 렌더링할 document 내부 요소를 설정 React.StrictMode: 리액트 프로젝트에서 리액트의 레거시 기능을 사용하지 못하게 하는 기능. 나중에 완전히 사라지게 될 기능을 사용했을 때 경고를 출력
JSX의 문법
- 감싸인 요소
- 컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 한다.
- why?: Virtual DOM에서 컴포넌트의 변화를 감지해 낼 때 효율적으로 비교할 수 있도록 컴포넌트 내부는 하나의 DOM트리 구조로 이루어져야 한다는 규칙이 존재
- 자바스크립트 표현
- JSX 안에서 { }로 감싸서 자바스크립트 표현식을 작성할 수 있음.
ES6의 const와 let
- ES6문법에서는 var를 사용할 일은 없음. 기본적으로 const를 사용하고, 값을 바꿔야 할 때만 let 사용.
- scope : 해당 값을 사용 할 수 있는 코드 영역
- const : 한 번 지정하면 변경이 불가능한 상수 선언 시 사용. scope가 블록단위. 블록 내 중복선언X, 재설정X, 한 번 설정 후 갑이 변할 일이 없는 값에 사용.
- let : 동적인 값을 담을 수 있는 변수를 선언 할 때 사용. scope가 블록단위. 블록 내 중복선언X, 한 번 선언 후 값이 변할 수 있는 경우에만 사용.
- var : scope가 함수 단위
if문 대신 조건부 연산자
- JSX 내부의 JS표현식에서 if문 사용 불가
- {} 안에 삼항 연산자를 사용
<div> { name === ' 리액트' ? ( 〈h1>리액트입니다.</h1> ) : ( 〈h2>리액트가 아닙니다.</h2> )} </div>
- JSX 밖에서 if 문으로 사전에 값을 설정하여 사용
- 자바스크립트 표현
- JSX 안에서 {자바스크립트 표현식}으로 사용할 수 있음
AND 연산자를 사용한 조건부 랜더링
특정 조건을 만족할때 노출, 아닐때 아무것도 랜더링하지 않아야 할 때
&& 연산자로 간단하게 조건부 랜더링 가능
→ 리액트에서 false를 랜더링할 때 null과 마찬가지로 아무것도 나타나지 않음
function App() {
const name = '뤼왝트';
return <div>{name === '리액트' && <h1>리액트입니다.</h1>}</div>;
}
export default App;
undefined를 랜더링 하지 않기
- 리액트에서는 함수에서 undefined만 반환해 랜더링 시
→ 값이 undefined일 수도 있다면, OR 연산자를 사용하면 undefined일때 사용할 값 지정하여 간단하게 오류 방지 가능
function App() {
const name = undefined;
return 〈div〉{name II '리액트'}/div〉;
}
export default App;
인라인 스타일링
- DOM요소에 스타일을 적용 할 때는 객체 형태로 넣어주어야 한다. 스타일명에 하이픈이 들어간 경우 카멜케이스로 변경해 넣는다.
<div
style={{
// background-color는 backgroundColor와 같이 -가 사라지고 카멜 표기법으로 작성됩니다.
backgroundColor: 'black' color: 'aqua'
fontsize: 48px', 1/ font-size -> fontsize
fontWeight: 'bold', /l font-weight - fontWeight
padding: 16// 단위를 생략하면 px로 지정됩니다.
}}
>
{name}
</div>
이렇게 또는 객체를 미리 선언하고 지정해줘도 됨.
class 대신 className
꼭 닫아야 하는 태그
꼭 닫아줘야 한다
태그 사이 별도의 내용이 들어가지 않는다면 self-closing 태그 이용 (선언 동시에 닫기)
주석
{/_ … _/}