리액트 입문

튜토리얼

최신 흐름을 추구하는 리액트 강좌

  • 프론트 영역의 변화는 극심하지만 최신 흐름을 파악하는 것을 목표로 함.

  • 현재 상황에서는 클래스 컴포넌트의 도퇴되는 과정과, Hooks 와 Functional Component 의 부흥이 꼽혀진다 (2019년 기준)

리액트는 어쩌다가 만들어졌을까?

<h2 id="number">0</h2>
<div>
  <button id="increase">+1</button>
  <button id="decrease">-1</button>
</div>
const number = document.getElementById('number');
const increase = document.getElementById('increase');
const decrease = document.getElementById('decrease');

increase.onclick = () => {
  const current = parseInt(number.innerText, 10);
  number.innerText = current + 1;
};

decrease.onclick = () => {
  const current = parseInt(number.innerText, 10);
  number.innerText = current - 1;
};
  • 간단한 카운트를 행하는 소스다.

  • DOM 을 직접 다루거나 이벤트가 더 많아 지는 경우에는 관리하기 매우 까다로워 진다.

  • react는 대상이 되는 component를 특정한 규칙에 의해서 업데이트를 하는 것이 아닌, 새로 만드는 것에 대해서 사상을 가지고 있다.

  • 매번 복잡한 구조의 컴포넌트를 새로 만든다면 시간 낭비일 수 있으나, virtual DOM 이라는 것을 통해서 성능적인 이슈도 해결했다고 한다.

리액트의 DOM Rendering 과정
  • reactDOMRendering 하는 과정

    • RealDOM <--> VirtualDOM 비교 과정

    • 일치하지 않는 것을 patch 과정을 통해서 부분적인 업데이트를 진

    • 이로서 전체적인 것을 다시 그리는 행위를 취하지 않고 성능도 지켜나갈 수 있다.

    • 고로 어떻게 업데이트 하냐의 관점이 아닌 어떻게 보여줄 지에 집중이 필요하다고 한다.

작업환경 준비

  • Node.js 설치

  • yarn(더 빠른 설치) or npm 중 취향적인 선택

  • 본인인 intellij 에서 프로젝트를 함.

나의 첫번째 리액트 컴포넌트

  • 이미 클래스, 함수형 스타일의 컴포넌트를 실습했다.

JSX

  • JSX 에서 선언하는 태그는 반드시 닫혀야한다.

  • N개 이상의 태그는 하나로 감싸야하고 감싸는 용도로 보통 <div> 를 사용하는 편이나 이마저도 싫다면 편법으로는 fragment를 사용한다.

  • javascript 변수를 JSX 내에서 사용하고 자하는경우 {}를 사용하면 된다.

  • JSX 내에서 style 은 객체 형태로 지정해야한다. 그리고 camelCase 형식으로 지정해야한다.

  • JSX 내에서 css의 class 를 지하는 것은 className으로 사용해야 한다.

  • 주석을 작성하는 법은 제시해줬으나 사용하고 싶지 않다. {} 사용

props 를 통해 컴포넌트에게 값 전달하기

props의 개요

  • 부모에서 자식 컴포넌트로 값을 전달하는 용도로 사용한다.

번거로운 props 과정을 생략하는 비 구조화 할당

  • 매번 위와 같은 구조로 props. 과 같은 과정으로 호출하게되면 상당히 귀찮기 마련이다. 비 구조화 할당을 통해서 바로 사용하고자 하는 값을 곧바로 쓸 수도 있다.

  • 아래와 같은 구조로 사용하는 것이 비 구조화 할당이라 명명한다.

defaultProps로 기본값을 할당해보자

  • 다음과 같이 Hello 컴포넌트에 defaultProps 를 활용하는 법을 배웠다.

props.children 로 컴포넌트 태그사이의 값 조회하기

  • 컴포넌트를 래핑하기 위한 용도의 별도의 컴포넌트이다.

  • Wrapper 를 특정 컴포넌트에서 사용하려면 위와 같은 형태에서는 사용이 불가하기 때문에 Wrapper에서 props.children 을 활용해야한다.

  • 이전 항목에서 배운 비구조화 할당을 활용하면 위와 같이 간략하게 작성이 가능해졌다.

조건부 렌더링

isSpecial 사용자 정의 props 설정 및 활용해보기

  • 간단한 삼항 연산자로 조건부 렌더링을 실습해보았다.

  • 다양하게 props 값을 설정할 수 있으나, 자바스크립트 값을 쓰기위해선 {}를 사용한다.

  • 또한 props 값을 생략하면 default value 는 true 이다.

조금더 축약된 표현을 활용해 본다면..

  • 우리가 단순히 보이고 안 보이고 수준의 표기용도이라면 && 연산자를 고려해보는 것도 나쁘지 않다.

useState 를 통해 컴포넌트에서 바뀌는 값 관리하기

사용자 인터렉션에 변화에 따른 구현 방법

  • 리액트 16.8 버전 이전에는 함수형 컴포넌트로 state를 관리할 수 없었다.

  • 이후 버전부터 Hooks의 등장으로 정식적인 기능은 아니였으나 많은 리액트 유저들이 이용한다.

  • 맛보기로 HooksuseState 를 활용하여 함수형 컴포넌트의 동적인 부분에 대응해본다.

  • 엘리먼트에 이벤트를 설정 시 xxxMethod()와 같은 형태 호출하여로 넣게되면 DOM이 렌더링 되기 전에 실행되버리므로 오류가 난다.

input 상태 관리하기

여러개의 input 상태 관리하기

  • 여러 개의 DOM을 다룰 경우 단순히 useState, onChange 를 여러개 만드는 방법이 쉬울 수 있으나 좋은 방법은 아니다. 해서 name을 설정하여 이벤트 발생시 이 값을 참조하여 관리하는 방법이다.

  • 리액트에서는 다음과 같은 연관배열이나 프로퍼티를 통해직접적인 수정을 하면 안된다.

    • inputs[name] = value

  • 대신에 새로운 객체를 생성하여 새 객체에 변화를 주고 이것을 상태로 사용해야 한다.

  • 위와 같이 기존 객체를 통해서 새로운 객체를 생성해 나가며 불변성을 지켜나가야만 리액트 컴포넌트에서 상태가 업데이트 됨을 감지하고 필요해 의하여 리렌더링이 진행된다.

  • 만약 직접 수정하는 경우 값이 바뀌어도 리렌더링이 되지 않는다.

코드에서 [name] : value, name:value 차이가 무엇인가요?

[name] , name 의 차이점
  • 궁금할때 직접 찍어보는 것도 하나의 답이 된다.

useRef 로 특정 DOM 선택하기

DOM을 선택해야하는 상황과 리액트에서 처리하는 방향

  • 리액트에서 직접적으로 DOM을 선택해야 하는 상황이 있다.

    • 엘리먼트의 크기, 위치, 포커스 설정

    • 외부 라이브러리

  • 위와 같은 상황일 경우 리액트에서는 ref 라는 것을 사용한다.

  • 함수형 컴포넌트의 경우 HookuseRef 함수를 사용.

  • 클래스형 컴포넌트의 경우 React.createRef 함수를 사용.

특정 DOM의 포커싱에 대해 처리해보자

  • useRef() 를 사용하여 Ref 객체 생성하여 선택하고자하는 DOM 요소에 ref 값으로 설정한 코

배열 렌더링하기

배열 데이터 처리 변천

  • 각 배열 요소를 사용하여 자식 컴포넌트를 구성하고 활용해보고, 앞으로 배열의 요소가 늘어날 경우를 대비한 동적인 구성에 대해서 배웠다.

key Props

key props 설정을 안한 경우
  • 리액트에서 배열을 랜더링시 key라는 props를 설정해야 한다.

  • 고유한 값을 다음과 같이 key props에 설정해본다. 왜 귀찮게 해야 하는가 생각이 들 수 있다.

key props 가 없는경우
  • 리렌더링 때, 해당 변화를 주고자하는 컴포넌트의 인덱스와 상관없이 모든 컴포넌트를 순차적으로 변경하는 과정을 취한다.

key props 가 있는 경우
  • 특정 인덱스의 컴포넌트에 변화를 주려면 고유 값을 알아야 원하는 곳만 변화를 줄 수 있다.

useRef 로 컴포넌트 안의 변수 만들기

useRef의 또다른 용도

  • 컴포넌트 내부에서 조회 및 수정이 가능한 변수를 관리하는 용도

  • 값이 변경이 되어도 컴포넌트 리렌더링에 관여하지 않는다.

  • 일반적인 컴포넌트는 상태를 바꾸는 함수를 호출 -> 랜더링 이후에 업데이트 된 상태를 조회하는 반면 useRef는 관리하고 있는 변수를 설정 이후 바로 조회가 가능하다.

위 용도를 통한 다양한 관리 사례

  • 비동기 이벤트를 통해 생성된 고유값 (ex: id값)

  • 외부 라이브러리를 통해 생성된 인스턴스

  • scroll 위치

직접 실습하여 보자

배열에 항목 추가하기

  • 부모컴포넌트 App에서 state 관리를 하며, input 엘리먼트에 필요한 함수들을 prop 를 넘겨서 실습.

  • CreateUser 에서 비구조화 할당을 통하여 props에서 필요한 변수, 함수를 전달받는다.

  • App 에서 자식 컴포넌트 CreateUser에서 사용할 props 를 관리한다.

배열에 대한 변화를 줄 시 주의점

  • 불변성을 지키기 위해 배열의 push, splice, sort 등의 함수를 사용할 경우 새로운 배열에 복사하여 사용한다. 간편하게 사용하고 싶을 때는 다음의 두가지 방법을 따른다.

    • spread 연산자

    • concat() : 기존 배열을 수정하지 않고 새로운 배열을 생성

배열에 항목 제거하기

배열에 항목 수정하기

간단한 색상 수정기능

구현 화면

구현 화면

useEffect를 사용하여 마운트/언마운트/업데이트시 할 작업 설정하기

useEffect를 통한 컴포넌트 마운트, 언마운트 관리

  • useEffect를 사용할 때에는 첫번째 파라미터에 함수, 두번째 파라미터에 의존값이 들어있는 배열(deps)를 넣는다.

  • 첫번째 함수에서 함수를 반환이 가능하며 이 함수를 cleanup함수라고 부른다. cleanup함수는 deps를 생략한 경우 컴포넌트가 사라질 때 사용된다.

mount시 주요 작업 예시

  • props로 받은 값을 컴포넌트의 로컬 state로 설정.

  • 외부 api 요청.

  • 라이브러리 사용.

  • setInterval(),setTimeout() 을 통한 작업.

unmount시 주요 작업 예시

  • setInterval(),setTimeout() 사용한 작업 clear. (clearInterval(), clearTimeout())

  • 라이브러리 인스턴스 제거

deps에 특정 값 넣기

  • deps에 특정 값을 넣게된다면 컴포넌트가 처음 마운트/언마운트 되거나 지정된 값이 바뀌거나 바뀌기 직전에도 호출이된다.

  • useEffect 안에서 사용하는 stateprops가 존재한다면 deps에 기입해야하 하는것이 규칙이다.

  • 만약 기입을 하지 않게될 경우 useEffect에 등록한 함수가 실행 될 때 최신 props/state를 가르키지 않게되며 다음과 같은 경고문을 보게된다.

deps 파라미터를 생략하는 경우

  • 이럴 경우 리렌더링 될때마다 호출이 된다.

리랜더링마다 호출
  • 리액트 컴포넌트는 부모가 리렌더링 되면 자식컴포넌트 또한 리렌더링이 수행된다.

  • 실제 DOM에 변화가 반영되는것은 바뀐 내용에 해당되는 컴포넌트만 되지만, Virtual DOM에서는 모든 DOM을 렌더링하므로 컴포넌트의 최적화하는 과정에서 이러한 불필요한 과정의 리소스를 절약하는 것이 가능하다.

useMemo 를 사용하여 연산한 값 재사용하기

  • 활성 사용자 수를 세는건, users 에 변화가 있을때만 세야되는건데, input 값이 바뀔 때에도 컴포넌트가 리렌더링 되므로 이렇게 불필요할때에도 호출하여서 자원이 낭비된다.

  • 이러한 상황에는 useMemo 라는 Hook 함수를 사용하면 성능을 최적화 한다. 이전에 계산 한 값을 재사용하는 방법이다.

  • useMemo 의 첫번째 파라미터에는 어떻게 연산할지 정의하는 함수를 넣어주면 되고 두번째 파라미터에는 deps 배열을 넣어주면 되는데, 이 배열 안에 넣은 내용이 바뀌면, 우리가 등록한 함수를 호출해서 값을 연산해주고, 만약에 내용이 바뀌지 않았다면 이전에 연산한 값을 재사용한다.

useCallback 를 사용하여 함수 재사용하기

  • useMemo와 비슷한 형태의 Hook함수이나 확실히 다른점

    • useMemo() : 특정한 결과값을 재사용할 때 사용.

    • useCallback() : 특정 함수를 재사용할 때 사용.

  • 함수 선언자체의 리소스는 큰 부하의 작업이 아니나, 재사용이 가능할 경우 활용하는 것이 중요하다.

    • 컴포넌트에서 props가 바뀌지 않았다면 Virtual DOM에 새로 랜더링하지 않고 컴포넌트의 결과물을 재사용하는 최적화 작업을 하기 위해서 필수적이다.

  • 함수 안에서 사용하는 state,props가 있다면 꼭 deps에 포함시켜야 최신 값을 참조할 수 있다.

  • props 를 통해 받아온 함수가 있다면, 이또한 deps에 포함해야한다.

사실은 useCallBackuseMemo기반으로 만들어졌다.

  • 다만 이런식으로 적기에는 효율적이지 않아 더욱 편하게 사용하기 위해 등장했다.

React DevTool

hightlight update
  • v4 버전으로 업그레이드 되면서 hightlight update 기능이 보이지 않았다.

  • https://blog.woolta.com/categories/1/posts/159 에서 그에 대한 대처법을 블로그했다.

  • 하지만 4.2버전부터는 원활하게 잘된다.

React.memo 를 사용한 컴포넌트 리렌더링 방지

  • React.memo 의 활용안은 기존 컴포넌트를 담을 수 있게 변수로 할당하고(할필요는 없지만 가독성을 위해서) 해당 변수를 React.memo에 인자값으로 설정해준다.

  • 다른 컴포넌트도 동일하게 적용을 해나갈 수도 있지만 User의 경우에 한개만 건드려도 모든 User, CreateUser까지 리렌더링 되는 현상이 있다.

  • 몇 가지 점검을 해야 올바르게 작동한다.

    • App에서 users배열을 변경시 의존하는 함수들의 deps에 대해서 useState로 관리하는 users의 정보를 함수형으로 업데이트를 하는 구조로 변경이 필요하다.

    • 이러한 이유는 users가 변경시 함수가 재 선언되며, 이를 활용하는 컴포넌트들은 리렌더링 과정을 수행하기 때문이다.

    • 방법은 deps에 위치한 users 를 지우고, setUsers에 등록하는 콜백함수의 파라미터에 최신 users를 참조하게 변경하면 depsusers가 존재하지 않더라도 된다.

  • onChange의 경우엔 함수형 업데이트를 해도 영향이 가지 않는다고 한다.

완벽하지 않은 React DevTool V4.2

  • hightlight update 기능이 아직 완벽하게 픽스 된것 같지는 않다. (2019.11.08 기준)

  • 개발툴에 의존해서 확인하는 것 보다 각 컴포넌트에서 직접 확인해서 체크하는 것도 하나의 방법이다.

useMemo의 구성

  • 사실 이해하기엔 아직 아는게 없지만, 이런 식으로 구성을 한번 살펴보는거도 공부가 될 것이라고 생각한다.

useReducer 를 사용하여 상태 업데이트 로직 분리하기

useReducer는 무엇인가?

  • 이전까지 상태를 업데이트시 useState를 활용했지만 또다른 방법이다.

  • 상태관리 + 상태 업데이트 로직 분리가 가능하다.

useReducer를 활용한 Counter 컴포넌트 구현

  • "함수만 분리했는데 무엇이 따로 관리하는 것인가" 라는 의문이 들수도 있다.

  • 중요한 포인트는 useReducerreducer를 다른 파일에 작성해도 무방하다.

  • 상태관련 업데이트를 따로 분리가 가능하다는 점이다.

useReducer를 활용한 App 컴포넌트 재구성

  • 조금 더 많은 기능이 존재하는 AppuseState ->useReducer변환 코드.

  • 개인적으론 상태관리를 신경쓰는 관심사가 분리되어 더욱 가독성이 좋아진 것 같다.

  • switch~case 분기를 위해 작성한 값은 typeScript를 도입해서 enum으로 대체하고 싶다.

그래서 useState, useReducer는 언제 구분해서 활용하는가?

  • 정답은 없다고 한다.

  • 상태관리를 함에 있어서 두가지 관점으로 보자면 다음과 같다.

    1. 내가 관리하는 상태 값이 한개 인가?

    2. 내가 관리하는 상태 값이 1~n 개 인가?

    3. 혹은 현재는 단일 상태 값만 관리하지만 유동적일 가능성이 있는가?

  • 1번 이라면 useState를 권장한다.

  • 2,3번 이라면 useReducer를 권장한다.

그래서 본인은 useState or useReducer?

  • 상태값이 몇개 인지에서 생각하는 관점이 아니라, 기능 상으로 동일하다면 해당 로직에 더욱 집중을 하도록 애초부터 분리를 하여 집중할 수 있도록 분리하는 useReducer를 택할 것이다.

  • 그런데 상태 관리에 관한 여러 기술들 Context API, Redux, MobX등이 있다곤 한다.

커스텀 Hooks 만들기

공통되는 로직을 관리해보자.

  • 컴포넌트를 생성하다보면, 공통적인 로직이 발생하기 마련이다.

  • custom Hooks 를 생성하여 재사용하는 방법에 대해서 실습했다.

custom hooks : useState -> useReducer 전환 연습하기

본인은 어떤 식으로 전환했나요?

  • 기존의 App Component에서 작성한 reducer 함수를 토대로 동일하게 작성을 시도했다.

  • 하지만 case 'FORM_RESET' 에서 input 의 상태값을 초기화 함에 있어서 비슷한 구조의 코드가 반복되면 줄여나가야 한다고 파악하여 for..in 구문을 통해서 문제를 풀어나갔다.

벨로퍼트는 어떻게 전환했는가?

  • Object.keys()를 통해 statekey 값을 추출

  • reduce()를 통해서 최초 초기값으로 객체 리터럴{} 에 초기화된 상태값을 연관배열을 통해 초기화하고 집계했다.

그래서 본인과 벨로퍼트의 전환 방식에 대해서 느낀 점은?

  • 취향 차이라고 볼수도 있으나 본인도 메서드 체이닝, 함수형 프로그래밍으로 풀어나가는 것을 더 선호하기에 reduce()에 대해서 더 공부하기로 마음먹었다.

Array.prototype.reduce를 잠깐 짚고 넘어가자

  • reduce() 메서드는 배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환한다.

  • 크게 callback, initialValue로 나뉜다.

  • callback

    • 컬렉션의 각 요소에 대해 실행할 함수. 4개의 인수를 가지고 있다.

      • 필수요소

        • accumulator : 콜백의 반환값을 누적한다.. 콜백의 이전 반환값 또는, 콜백의 첫 번째 호출과정에서 initialValue를 제공한 경우에는 initialValue의 초기값 이다.

        • currentValue : 처리할 현재 요소.

      • 옵션

        • currentIndex : Optional처리할 현재 요소의 인덱스. initialValue를 제공한 경우 0, 아니면 1부터 시작합니다.

        • array : Optionalreduce()를 호출한 배열.

  • initialValue

    • Optionalcallback의 최초 호출에서 첫 번째 인수에 제공하는 값.

    • 초기값을 제공하지 않으면 배열의 첫 번째 요소를 사용한다.

    • 빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생한다.

Context API 를 사용한 전역 값 관리

부모에게서 자식으로 "값"을 전달할 경우 고찰..

  • 현재까지 실습을 한 컴포넌트의 구성을 살펴본다면 해당 컴포넌트에서 사용하지 않는데도 불구하고 다음 세대의 자식 컴포넌트에 전달하기위한 중간다리 역할을 하기위해 "값"을 전달하는 형태로 구현했다.

  • one-depth 의 구조의 컴포넌트면 신경을 안 쓸수도 있으나 우리가 앞으로 실무에서 구현해야 하는 컴포넌트는 그렇게 만만하지 않다.

  • 이전부터 누누히 언급했었던 상태관리에 대한 기술 중 하나읜 Context API를 해당 챕터에서 실습했다.

Context API

  • state 뿐만 아니라 외부라이브러리 인스턴스, DOM이 될 수있다.

  • 전역적으로 프로젝트의 상태를 관리하는 용도로 사용된다.

기본 코드

  • Context의 기본값을 설정할 수 있다.

  • 내부 컴포넌트로 Provider 라는 컴포넌트가 구성되어있고 Context의 값을 지정할 수 있다.

    • attributevalue를 설정이 가능하다. 본 챕터에서는 fragment 대신 교체가 되고 useReducer에서 추출한 dispatchvalue로 설정했다.

실습코드

  • App

    • onToggle, onRemove의 삭제.

    • Context API 사용.

    • fragment -> Context 로 교체.

  • UserList

    • App 에서 삭제된 onToggle, onRemove 구현.

    • App 에서 선언한 Context 활용.

    • 기존 User에 전달하기 위한 onToggle, onRemove props 제거.

벨로퍼트의 숙제 완료 코드(숙제 그만 좀..)

  • 요구사항

  • 실습분

  • Context API 를 통해서 각 컴포넌트의 "값"의 변화는 필요한 컴포넌트에서 관리하게 되는 이점을 얻게 되었다.

Immer를 사용한 더 쉬운 불변성 관리

불변성의 중요성

  • 리액트로 함수형 스타일로 구현해 나가면서 데이터의 불변성을 지켜주는 것은 더욱 중요해졌다.

  • 불변성을 지키기 해서는 기존 데이터에서 변형이 필요할 때 수정이 아닌 새로 생성해 나가면 된다.

그러나 불변성을 쉽게 지켜나가게 도와주는 Immer

  • 비교적 직관적으로 코드가 보인다.

Immer 설치

  • 둘 중 하나를 고르면 된다.

produce()

  • 심플하게 해하고 넘어간다.

기존 예제의 Reducer에서 활용해보기

Immer와 함수형 업데이트

  • useState를 활용한 곳에서 우리 직접 업데이트하는 코드를 작성함으로 depstodo를 추가하지 않아도 었다. produce에서 한개의 인자값을 활용하면 반환 값은 새로운 상태가 아닌 상태를 업데이트 해주는 함수가 된다.

편하긴 하나 주의해야할 점

  • 성능

    • 인간이 시각적으로 인지하는 기준은 13ms

      • Immer가 5만개의 원소중 5천개를 업데이트하는 속도는 약 31ms

      • Native Reducer가 업데이트하는 속도는 약 6ms

    • 성능적으로 Navtive Reducer 보다 좋지 않다.

    • 그러므로 데이터의 양이 적거나, 구조가 복잡할 때 복잡도를 방지하는 차원의 용도로 권장한다.

    • Immer 는 JavaScript 엔진의 Proxy 라는 기능을 사용

      • 구형 브라우저 및 react-native 같은 환경에서는 미지원

        • 위 환경에서 ES5 fallback 을 사용하게 되고 191ms 정도로, 꽤나 느려지게 다.

      • Proxy 처럼 작동하지만 Proxy는 아니다.

클래스형 컴포넌트

함수형 컴포넌트가 하지 못하는 작업을 처리하자

  • 클래스형 컴포넌트의 유지보수, 함수형 컴포넌트에서 아직까지 하지 못하는 2가지 작업에 대해서 클래스형 컴포넌트로 풀어나가는 과정을 학습한다.

  • 오래된 라이브러리일 경우 Hooks의 지원이 안된다.

  • react-native 관련 라우터 라이브러리 react-native-navigation도 클래스형 컴포넌트를 써야한다.

  • 클래스형 컴포넌트에서는 render() 메서드가 꼭 있어야 하고 렌더링하고 싶은 JSX 를 반환하시면 됩니다. 그리고, props 를 조회 해야 할 때에는 this.props 를 조회한다.

  • defaultProps 를 설정하는 것은 이전 함수형 컴포넌트에서 했을 때와 동일하나 클래스 내부에 static 키워드와 함께 선언하는 방법도 존재한다.

클래스형 컴포넌트의 다양한 상황 해결방법

  • 클래스 컴포넌트에서 이벤트를 등록하는 과정에서 각 메서드와 컴포넌트 인스턴스의 관계가 바인딩이 되지 않는 상황이 존재한다.

  • 해결법은 생성자 바인, Arrow Function, 직접 함수를 전달하는 방식이 존재한다.

  • CRA(Create-React-App)으로 생성한 프로젝트에서 클래스 컴포넌트 내부에 Arrow Function 선언을 가능하게 해주는 class-properties 라는 문법을 사용이 가능하나 정식 자바스크립트 문법이 아니니 주의해야한다.

  • 직접 전달하는 법은 랜더링 때마다 함수도 새로 생성되기 때문에 컴포넌트 최적화를 위해선 배제해야한다.

상태 선언, 업데이트 하기

  • 클래스형 컴포넌트의 state는 객체형태여야 한다.

  • 특별히 관리하지 않는 프로퍼티도 값은 유지된다. 하지만, 클래스형 컴포넌트의 state 에서 객체 형태의 상태를 관리해야 한다면, 불변성을 관리해줘가면서 업데이트를 해야한다.

setState의 함수형 업데이

  • setState 를 한다고 해서 상태가 바로 바뀌지 않는다.

  • setState 는 단순히 상태를 바꾸는 함수가 아니라 상태로 바꿔달라고 요청해주는 함수이기 때문이다.(참고)

  • 성능적인 이유 때문에 리액트에서는 상태가 바로 업데이트 되지 않고 비동기적으로 업데이트가 된다고 한다.

  • 만약에, 상태가 업데이트 되고 나서 어떤 작업을 하고 싶다면 다음과 같이 setState 의 두번째 파라미터에 콜백함수를 넣어 활용한다.

LifeCycle Method

무엇을 공부하든 중요한 생명주기

  • 컴포넌트가 브라우저 상에서 흐르는 생명주기에 관련된 메서드는 매우 중요하다.

  • 클래스형 컴포넌트에서만 사용이 가능하다.

  • 깊게 공부하는 시간은 따로 개인적으로 준비를 한다.

생명주기 호출 과정

생명주기 메서드 흐름

마운트

  • constructor : 컴포넌트의 생성자 역활

  • getDerivedStateFromProps

    • props 로 받아온 값을 state에서 관리하고자 할 때 사용

    • 다른 생명주기와 달리 static 키워드가 필요하며, 내부에서 this를 조회하는 것은 불가능하다.

    • 이 생명주기에서 별도의 특정 객체를 반환하면 해당 객체의 프로퍼티가 state에 설정이 된다.

    • 반면 null 일 경우 아무런 변화가 없다.

  • render : 컴포넌트 렌더링을 당하는 메서드.

  • componentDidMount : 컴포넌트의 첫 렌더링 후 호출되는 메서드

    • 외부 라이브러리, 컴포넌트에 필요한 데이터 요청, 직접적인 DOM의 속성을 파악 및 변경하는 용도로 사용된다.

업데이트

  • getDerivedStateFromProps

  • shouldComponentUpdate

    • 컴포넌트의 리렌더링 여부를 결정하는 메서

    • 최적화 용도로 사용되며 React.memo와 그 기능이 유사하다.

  • render

  • getSnapshotBeforeUpdate

    • getSnapshotBeforeUpdate 는 컴포넌트에 변화 직전의 DOM 상태를 가져와서 특정 값을 반환하여 그 다음 발생하게 되는 componentDidUpdate 에서 받아와서 활용을 할 수 있습니다.

  • componentDidUpdate

    • componentDidUpdate 는 리렌더링 이후, 변화가 모두 반영되고 난 뒤 호출되는 메서드입니다.

    • 3번째 파라미터로 getSnapshotBeforeUpdate 에서 반환한 값을 조회가 가능하.

getSnapshotBeforeUpdate의 활용 예 (스크롤바 유지하기)

언마운트

  • componentWillAmount

    • DOM 요소가 완전히 제거되기 직전에 발생되는 메서드로 언마운트 단계에서는 단 하나만 존재한다.

    • 주로 해당 DOM 요소에 활용하였던 비동기 메서드 및 외부 라이브러리를 이곳에서 해제한다.

componentDidCatch 로 에러 잡아내기

Sentry 연동

  • 본인은 GitHub 계정을 통해서 Sentry.io 에 방문하여 다음 동영상과 같이 시작 절차를 진행했다.

센트리 따라해보기
  • npm 을 통한 sentry 설치 진행

  • Sentry에 SDK 연결을 수행해야 한다. Sentry에서 프로젝트 설정을 완료하면 Sentry는 DSN 또는 Data Source Name 이라는 값을 제공합니다 . 표준 URL과 비슷하지만 Sentry SDK에 필요한 구성을 나타내며 프로토콜, 공개 키, 서버 주소 및 프로젝트 식별자를 포함하여 몇 가지로 구성된다. 해당 스크린샷을 참조하여 index.js 를 수정하여 최종적인 센트리 등록을 마치자.

  • 위 과정까지 마쳤다면 다음과 같이 시작하기 페이지가 변동이 되있다.

  • 그 이후 다음과 같은 Sentry UI를 확인 할 수 있다.

그래서 실제로 프로덕션 환경에서 어떻게 활용하는가.

  • 먼저 ErrorBoundary 클래스 컴포넌트를 만들어보자

  • 주요적으로 보야하는 메서드는 componentDidCatch 이며 파라미터는 각각 에러의 내용과 위치 정보를 제공한다.

  • velopert 는 yarn 을 활용하여 production 환경에 대한 빌드를 진행했다. 그러나 필자는 npm 을 활용하여 설치를 진행했다.

  • 위 명령어를 통해 모든 과정을 마치면, localhost:5000/ 에서도 정상적으로 센트리와 연동이 완료된다.

리액트 개발 할 때 사용하면 편리한 도구들

  • 본인만의 스타일로 코드의 형태를 정할 수 있는 code formatter 이다.

  • vscode 를 통해서는 velopert의 강좌를 따라서 진행하면된다.

  • intellij 설치 과정은 다음 탭의 과정을 순서대로 진행하면 된다.

  • 변경 전과 후를 비교해본다.

ESLint

  • create-react-app 으로 개발 시에는 미리 경험을 해본 관계로 생략한다.

Snippet

  • 코드관련 템플릿에 관한 것이며, vscode 기준이기도 하며 다양한 플러그인을 intellij에서도 지원하니 취향거 선택하여 사한다.

Last updated

Was this helpful?