페이스북에서 관리하는 웹 페이지의 컴포넌트를 렌더링하고 빌드하는데 초점을 둔 가장 인기있는 자바스크립트 라이브러리
UI 라이브러리기 때문에 자체적으로 전역 상태 관리, 라우팅, 빌드 시스템을 지원하지 않고 Redux, Mox, React-router등을 추가하여 사용해야함
Vitual DOM을 사용해서 빠른 렌더링, 성능개선이 가능
-- 가상 돔의 장점 : 뷰에 변화가 있다면 그 변화는 실제 DOM에 적용되기 전에 가상 DOM에 먼저 적용 시키고 그 최종적인 결과를 실제 DOM에 전달하며 브라우저 내에서 발생하는 연산의 양을 줄이면서 성능이 개선됨
React는 View만 신경쓰기에 데이터 흐름이 단방향 데이터 흐름을 가짐
리액트는 UI를 여러 컴포넌트로 쪼개서 만듦
JSX라는 React문법이 HTMl과 비슷하여 예측 가능한 개발 가능
이벤트가 발생할 때 마다 가상돔을 만들고 다시 그릴 때 실제 돔과 비교하여 변경이 필요한 최소한의 변경사항만 실제 DOM에 반영해 웹의 효율성과 속도를 개선
리액트 내부적 비교 알고리즘으로 시간 복잡도 O(N)을 가진 휴리스틱 알고리즘을 활용하여 구현
리액트는 두 가지 가정을 기반으로 휴리스틱 알고리즘을 구현
서로 다른 타입의 두 엘리먼트는 서로 다른 트리를 만들어낸다.
개발자가 key prop을 통해, 여러 렌더링 사이에서 어떤 자식 엘리먼트가 변경되지 않아야 할지 표시해 줄 수 있다.
JSX란 JavaScript 문법에 XML을 추가한 확장 문법
브라우저에서 실행 전 Babel을 사용하여 일반 자바스크립트 형태의 코드로 변환
리액트를 개발할 때 활용되므로 공식적인 자바스크립트 문법은 아니지만 HTML 작성하듯이 하기 때문에 가독성이 높고 작성하기 쉬움
개발자가 JSX를 작성하면 리액트 엔진은 JSX를 기존 자바스크립트로 해석 이것을 선언형 화면 기술이라고 함
반드시 부모 요소 하나가 감싸 있어야 함 없으면 빈 태그인 프래그먼트라도 활용
JSX 안에서도 { } 를 활용해 자바스크립트 표현식을 작성할 수 있음
if문과 for문 대신 삼항 연산자나 && 연산자를 통한 조건부 렌더링
JSX에서 자바스크립트 문법을 활용하려면 { } 을 활용해야 하기 때문에 스타일을 넣어줄 때도 객체 형태로 넣어주어야야 하고 camelCalse 규칙 활용
SPA (Single Page Application) : 단 하나의 페이지로 자바스크립트를 이용해 동적으로 화면의 콘텐츠를 바꾸는 방식의 웹 애플리케이션
SPA는 웹 애플리케이션이 필요한 모든 정적 리소스를 최초 렌더링 시 한 번에 다운로드 하고 그 이후 새로운 페이지 요청이 있을 경우 페이지 갱신에 필요한 데이터 (JSON)만 서버로부터 전달받아 페이지를 갱신 (그래서 깜빡거리지 않음)
SPA에서 쓰이는 기법이 CSR이라 비슷하지만 SPA != CSR인 것을 명심
대표적인 SPA 관련 라이브러리는 리액트, 뷰, 앵귤러 등이 있음
SPA 장점 (CSR도 비슷)
-- 첫 로딩만 기다리면 동적으로 빠르게 렌더링 되기 때문에 사용자 경험이 좋음
-- 서버에서 요청하는 횟수가 MPA비해 적어서 서버의 부담이 덜함
SPA 단점 (CSR도 비슷)
-- 초기 렌더링 속도가 느리지만 코드 스플링틍 통해 리소스를 청크 단위로 묶어 요청할 때마다 리소스를 받게 하면 개선은 되지만 해결할 수는 없음
-- 검색엔진 검색봇이 크롤링을 못해 SEO 문제가 있음
전통적인 웹 애플리케이션 개발방식이며 여러 개 페이지로 구성된 애플리케이션
브라우저가 웹 서버로부터 페이지 요청을 할 때마다 해당 페이지에 관련된 HTML, CSS, JS의 데이터를 받아와서 렌더링 (깜빡거림)
기본적으로 MPA에서 쓰이는 기법이 SSR 방식인 것 여기도 MPA != SSR
MPA 장점 (SSR과 비슷)
-- 최초 렌더링 속도가 빨라 사용자가 컨텐츠를 빠르게 볼 수 있음
-- JS를 통한 렌더링이 아니기 때문에 SEO 가능
MPA 단점 (SSR과 비슷)
-- 매번 페이지를 요청할 때마다 깜빡거려 사용자 경험이 좋지 못함
-- 서버에 매번 요청을 하기 때문에 서버의 부하가 커짐
코드스플리팅을 하면 지금 당장 필요한 코드가 아니라면 따로 분리시켜서 나중에 필요할 때 불러와 사용할 수 있음 이를 통하여 페이지의 로딩 속도 개선 가능
특히 SPA (CSR)에서 자바스크립트로 애플리케이션을 개발하면 기본적으로는 하나의 파일에 모든 로직들이 들어가 자바스크립트 파일 용량이 프로젝트가 커질수록 커질 것이다 그러므로 인터넷이 느리면 로딩속도도 느림
리액트 자체적으로 React.lazy를 통해 코드 스플리팅을 지원하고 라이브러리로는 react-loadble이 있음
Mount
constructor : 생성자 메서드 컴포넌트가 만들어지면 가장 먼저 실행
getDerivedStateFromProps : props로 받아온 것을 활용할 때
render : 컴포넌트를 렌더링
componentDidMount : 첫 번째 렌더링이 마치면 호출되는 메서드 (우리가 만든 컴포넌트가 화면에 나타남)
Update
Unmount
리액트 훅은 React 16.8 버전에서 새롭게 도입된 기능 기존 클래스 컴포넌트에서는 상태관리나 라이프사이클의 기능이 있지만 함수형 컴포넌트에는 그런 기능이 존재 하지 않았음 하지만 이제 Hook을 통해 상태관리나 렌더링 후 작업을 설정할 수 있게 됨
리액트 훅이 도입되면서 클래스 기반 컴포넌트, 라이프 사이클 메서드, this의 필요성이 사라짐
useState
대표적인 훅으로서 함수형 컴포넌트에서 상태를 관리할 때 사용
useState()라는 함수는 배열을 리턴하므로 첫 번째는 getter인 state의 값 두 번쨰는 setter인 state변경 함수, 구조 분해 할당이 가능함
useEffect
라이플 사이클 메서드와 관련이 있고 useEffect( () => { return () => { }, [ ]} 을 활용하여 Unmount도 구현 가능 만약 두 번째 배열 인자 ([ ])를 입력하지 않으면 state가 바뀔 때마다 동작하기 때문에 비효율적
useLayout
useEffect는 컴포넌트 render 후에 paint 된 후에 실행되기 때문에 useEffect에서 DOM에 영향을 주는 코드가 있으면 깜빡이는 현상이 발생
useLayout은 render후에만 발생해서 깜빡임을 경험하지 않지만 사용자가 화면을 보는데 오래 걸릴 수도 있음
useRef
DOM 요소에 직접 접근해야할 때 (DOM요소에 focus를 줄 때)
useCallback
컴포넌트가 렌더링 될 때마다 함수를 새로 만들지 않고 재사용 재사용하고 두 번째 인자인 의존성 배열의 state값이 변경되었을 때만 새로 생성함
메모이제이션 훅이고 메모이제이션이란 결과 값을 자료 구조에 저장하고 이후 계산을 반복하는 것이 아닌 꺼내서 사용
useMemo
특정 결과값을 재사용할 때 사용되는 함수
useCallback과 마찬가지로 메모이제이션 훅이지만, 둘의 차이는 특정 결과값을 재사용 하느냐 함수는 재사용 하느냐의 차이
useContext
기존의 React에 존재하는 Context를 편하게 사용해줄 수 있는 Hook
useReducer
컴포넌트의 상태값을 리덕스의 리듀서처럼 관리할 수 있게 해주는 훅
useReducer를 사용하면 컴포넌트의 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있어 상태 업데이트 로직을 컴포넌트 바깥에 작성할 수도 있고 심지어 다른 파일도 가능
리액트에서는 state값을 변경할 때 불변성을 지켜야함
불변성이란, 원본값을 직접 변경하면 안 된다는 의미로 변경대신 복사를 통해 새로운 값을 만들어 내야함
예를 들어, ...연산자를 활용하거나 map, filter, slice를 통해 새로운 배열을 반환, splice, push, shift 등을 원본 데이터를 변경하기 때문에 사용을 지양
불변성을 지키면 사이드 이펙트 방지 및 프로그래밍 구조의 복잡도를 감소 시켜주고 변경이 일어난 객체의 프로퍼티만을 비교함으로 React에서 최적화가 가능
React.memo는 HOC (Higer-Orfer-Components) 즉, 고차 컴포넌트
-- 고차 컴포넌트란 컴포넌트를 인자로 받아 새로운 컴포넌트를 return 해주는 함수
React.memo는 컴포넌트의 프로퍼티(props)가 변경되었을 때만 리렌더링되도록 메모이제이션(Memoization)을 적용
컴포넌트가 같은 결과를 렌더링 하면 React.memo를 사용하여 불필요한 컴포넌트 렌더링을 방지할 수 있음 즉, 컴포넌트에서 같은 props가 들어온다면 리액트는 컴포넌트 렌더링 과정을 스킵하고 마지막에 렌더링된 결과를 재사용
React.memo는 오직 props가 변경됐는지 아닌지만 체크, 근데 만약 React.memo가 감싸진 컴포넌트가 useState나 useContext 같은 훅을 사용한다면 state나 context가 변경될 때마다 리렌더링
props로 들어온 Object는 얕은 비교로 비교, 즉, props로 들어온 number, string과 같은 원시 값을 실제 값이 동일한가를 비교하지만, 참조 타입의 경우 원시 값과 달리 같은 값을 참조 하고 있는지만을 비교