프론트엔드 기본개념 복습/React 12

[React] classnames로 리액트에서 클래스 관리하기

React의 className 리액트는 JSX문법에 따라 class가 아닌 className을 통해 element의 클래스를 지정해준다. 그런데 클래스명을 지정해주다 보면 불필요하게 코드가 길어지거나 일관성이 떨어지는 등의 문제가 발생하기도 한다. 첫 번째 예시를 보자. 여러 클래스명이 존재할 때 클래스명은 서로 공백을 통해 구분된다. 만약 경우에 따라 클래스명이 추가될 수도 추가되지 않을 수도 있을 때 이것은 매우 귀찮은 문제를 만든다. 클래스명이 추가될지 여부도 모르는 채 공백을 추가해줘야 하며 어떠한 방식으로 표현해도 관련 코드가 보기 안 좋아진다. (공백 처리 관련하여 join을 활용한 classNameGenerator 함수를 만들어줘도 되지만 그 역시 효율적이라고 볼 수는 없다.) 두 번째 예시..

[React] react-query에서 에러 처리하기

react-query는 onError 옵션을 통해 에러 처리 메소드를 지정할 수 있도록 해준다. 그런데 매 쿼리마다 onError 메소드를 지정해주는 것은 비효율적이다. 예를 들어서 서버 점검으로 인해 503번 HTTP 상태 코드가 반환되었을 때 우리는 공통적으로 서버 점검 관련 안내 메시지 혹은 화면을 보여줄 것이다. 그런데 매 쿼리가 생성될 때마다 503번 코드를 받았을 때 해당 작업을 수행하는 메소드를 지정해주는 것은 비효율적이다. 다행히 react-query는 QueryClient를 생성할 때 default option들을 지정하게 해 준다. 그 중 onError 옵션에 에러 처리 함수를 지정해주면 해당 QueryClient 내부에서 사용하는 모든 useQuery와 useMutation hook에..

[React] React Hook Form으로 간단하게 리액트에서 폼 사용하기

React Hook Form 리액트에서 폼을 관리하는 것은 생각보다 귀찮은 작업이다. Input Validation, Form Submit 등의 작업을 수행하다보면 별 거 아닌 기능에도 코드가 매우 길어지는 것을 볼 수 있을 것이다. 다행히 React-Hook-Form이라는 라이브러리를 사용하면 ReactJS와 React Native 애플리케이션을 구현할 때 매우 적은 양의 코드로도 손쉽게 폼을 관리할 수 있다. 장점 (사실 React Hook Form은 공식 사이트에서 워낙 장점을 잘 표현해놔서 직접 확인하는 것을 추천한다. 공식 사이트 링크는 위에 있다.) (1) 코드를 적게 작성해도 된다. (2) 렌더링 관점에서 효율적이다. (폼 내에서 리렌더링이 발생할 때 최소한의 리렌더링만을 수행한다. 예를 들..

[React] useLayoutEffect vs useEffect

useLayoutEffect와 useEffect는 모두 의존값의 변화에 따라 side effect 함수를 실행시킨다는 점에서 유사한 성질을 가진다. 그러나 실제 그것이 동작하는 방식에 있어서 실제로 그것을 활용하는 방향성에 있어서 차이점을 지닌다. useEffect useLayoutEffect 실행 순서 컴포넌트 렌더링 → 화면 갱신 → side effect 컴포넌트 렌더링 → side effect → 화면 갱신 side effect 함수 실행 방식 비동기 동기 useEffect문을 사용해서 DOM element의 style을 지정하는 등 mutation을 일으키는 경우 이미 화면이 갱신된 이후에 또 다시 화면이 갱신되면서 '깜빡거림'(flickering)이 발생한다. 이는 SPA의 장점을 망치는 현상 ..

[React Native] React Native의 작동 원리

React Native 앱의 구성 요소 React Native 앱은 크게 세 가지 요소로 이루어져 있다. Native 영역과 JS 영역이 존재하며 그 둘을 Native Bridge가 이어준다. 1. Native side (Main Thread = UI Thread) 네이티브 영역인 메인 스레드는 어플리케이션이 실행되자마자 시작된다. 메인 스레드는 우선적으로 앱을 로드하고 JS 스레드를 실행시킨다. 메인 스레드는 앱의 UI적인 부분을 담당한다. (그렇기 때문에 UI 스레드라고 부르기도 한다.) 메인 스레드는 JS의 이벤트 루프가 끝날 때마다 네이티브 브릿지를 통해 받은 메시지를 기준으로 UI를 화면에 보여준다. 반대로 사용자가 기기에 UI 이벤트를 일으키면(press, touch 등) 네이티브 브릿지를 통..

[React] 리액트 최적화하기 (Optimization in React)

1. React.memo( ), useMemo( ), useCallback( ) 각각 함수 컴포넌트, 함수 컴포넌트 내 변수, 함수 컴포넌트 내 함수를 메모이제이션하기위해 사용한다. 위 세가지 메소드들을 활용하면 불필요한 리렌더링을 방지할 수 있다. 이미 관련 내용들에 대한 포스팅을 한 기억이 있으니 간략하게 넘어가겠다. (마지막으로 useCallback( )의 중요성을 한 번만 더 강조하고 싶다. 함수를 props로 넘겨줄 때 익명 arrow function을 경우가 종종 있는데 이는 해당 익명 함수를 전달해주는 컴포넌트가 리렌더링될 때마다 새로운 함수 인스턴스를 만들어줘야 한다. 그렇기 때문에 동일한 함수 내용이더라도 다른 인스턴스이기 때문에 해당 함수를 전달받은 자식 컴포넌트는 부모 컴포넌트가 리렌..

[React] state 갱신하기

리액트에서 컴포넌트의 state를 제대로 갱신하기 위해서 주의해야 할 점을 간략히 정리해보겠다. 1. state 직접 수정하지 않기 컴포넌트의 state를 변경하고 싶으면 setState( ) 메소드를 활용해야 한다. 그냥 state에 값을 대입하는 경우 값의 갱신은 이루어질 수 있더라도 컴포넌트가 리렌더링되어야 한다는 사실을 알지 못하기 때문이다. (state에 직접 값을 대입하는 경우는 클래스 컴포넌트의 constructor( ) 메소드 내부 말고는 없다.) 2. state의 갱신은 원하는대로 이루어지지 않을 수 있다. 컴포넌트의 state 혹은 props는 비동기적으로 업데이트될 수 있다. 그렇기 때문에 state나 props에 의존하여 새로운 state를 지정해줄 때에는 주의가 필요하다. 이럴 때..

[React] 에러 경계 (Error Boundaries)

리액트를 개발해본 사람이라면 누구나 한 번쯤 접했을 화면이다. 리액트는 컴포넌트 내부에서 에러가 발생하면 위와 같이 에러를 화면으로 보여준다. 그러나 저 화면은 개발을 하는 우리들만이 볼 수 있는 화면이다. Production 모드로 들어가면 에러는 보여지지 않고 렌더링에 실패한 컴포넌트가 남긴 쓸쓸한 텅 빈 화면만이 남아있을 것이다. 그에 따라 React16에서는 UI 일부분에 해당하는 자바스크립트 에러가 전체 어플리케이션을 셧다운시키는 것을 막기 위해서 에러 경계라는 새로운 개념을 가져왔다. (React 공식 문서에 적힌 표현) 에러 경계(Error Boundary)는 하위 컴포넌트 트리 안에서 발생하는 에러를 찾아내고 깨진 컴포넌트 트리 대신 fallback UI를 제공해준다. 복잡할 것 없이 에러..

[React] 코드 분할 (Code Splitting)

번들링은 여러 파일을 하나로 묶는 것을 말한다. 그냥 파일을 그대로 가져오면 편리함에도 번들링을 실행하는 이유는 단발성으로 리소스를 요청하는 HTTP 통신의 특성상 여러 번 파일을 요청하는 것보다 여러 파일을 한 번에 가져오는 것이 훨씬 효율적이기 때문이다. 이러한 측면에서 번들링은 최대한 빨리 리소스를 가져와서 사용자에게 화면을 제공해야 하는 프론트엔드 직무에서 매우 중요한 개념 중 하나이다. 리액트 어플리케이션들은 Webpack, Rollup, Browserify 등의 번들링 툴을 활용하여 하나의 파일로 통합할 수 있다. 심지어 리액트 어플리케이션을 만들기 위해 많이 사용하는 Create React App 혹은 최근 서버 사이드 렌더링과 함께 주목받고 있는 Next.js 등의 툴을 활용한다면 어플리케..

[React] React.memo, useCallback

React.memo( ) React.memo( )는 리액트에서 제공하는 고차함수(HOC)이다. React.memo( )로 컴포넌트를 감싸주면 그 결과물을 메모리에 기억하여 재사용한다. 그를 통해 불필요한 리렌더링을 방지할 수 있기 때문에 성능적인 부분을 개선시킬 수 있다. 그러나 무분별한 React.memo( )의 남발은 렌더링 비용보다 메모이제이션 비용이 비싸져서 오히려 프로그램의 성능을 저하시킬 수도 있다. 따라서 적절한 순간에만 React.memo( )를 적용하는 것이 중요하다. 1. React.memo( )의 비교 방법 React.memo( )는 기본적으로 얕은 비교를 통해 Props 객체를 비교한다. 만약 Props를 비교하는 Custom 메소드를 지정해주고 싶다면 다음과 같이 React.mem..