
이 글은 모던 리액트 Deep Dive를 기반으로 작성되었습니다.
리액트 팀에서 제공하고 있는 react-dev-tools를 알아보자. 리액트로 만들어진 다양한 사이트를 디버깅하기 위해 만들어졌으며, 리액트뿐만 아니라 네이비티브 등 다양한 플랫폼에서 사용할 수 있다.
크롬과 파이어폭스 엣지 브라우저에서 제공하지만, 대부분의 사용자가 크롬을 사용하기때문에 크롬을 기준으로 설명하겠다.
개발 도구를 설치해야하는데 어렵지 않다. 크롬의 경우 확장 프로그램을 설치하면 된다. 설치를 완료하면 우측 상단에서 확인할 수 있다!
일반적인 로고 모양 : 현재 페이지가 리액트로 배포되어있다.
빨간 로고 모양 : 리액트가 개발자 모드로 실행되고있다.
Compontents 탭에서는 리액트 어플리케이션의 컴포넌트 트리를 확인할 수 있다. 단순히 구조만 확인하는게 아니라, props나 내부 hooks 등 다양한 정보를 확인할 수 있다!
정상정인 함수 선언식과 함수 표현식을 통해 생성된 컴포넌트는 모두 정상적으로 함수명을 표시하지만, 그렇지 않은 컴포넌트는 Anonymous나 _default로 보인다.
//App.tsx
import DefaultComponent from './DefaultComponent'
export default function App() {
return (
<DefaultComponent />
)
}
// DefaultComponent.tsx
export default () => {
return <>DefaultComponent</>
}
위의 코드는 컴포넌트 트리를 보면 DefaultComponent의 함수명을 확인할 수 없어 함수명을 제대로 확인할 수 없다. 그 외에도 memo 또는 고차 컴포넌트 예시가 있는데 이런 부분은 모두 함수명을 제대로 정의 하지 않는 경우와 동일하다.
만약 함수로 기명함수로 변경하기 어렵다면 displayName을 사용하면 좋다. 다만, 빌드 시에 사용하지 않는 코드로 인식할 가능성도 있기에 개발 모드에서만 제한적으로 참고하는 것이 좋다.
const MemoizedComponent = memo(function () {
return <>MemoizedComponent</>
})
MemoizedComponent.displayName = "메모 컴포넌트입니다.'

우측 패널에 props정보와 hooks과 같은 정보가 나온다. 훅도 마찬가지로, 익명함수냐 기명함수냐에 따라 보여지는 이름이 다르다.
// 익명함수
useEffect(() => {
console.log('useEffect')
})
// 기명함수
useEffect(function effectOnlyMount() {
console.log('useEffect')
})
컴포넌트와 다르게 프로파일러는 렌더링하는 과정에서 발생하는 상황을 확인하기 위한 도구이다. 프로파일러는 렌더링 과정에 개입하여 기록하기에 프로덕션 빌드로 실행된 리액트 애플리케이션에는 사용이 불가능하다.
프로파일러를 통해 input에 텍스트를 입력하는 렌더링 과정을 살펴보면 매번 입력할 때 마다 전체 input이 아닌 DailyWrite 전체가 렌더링된다.
이유는, input의 value값을 저장하는 데이터가 DailyWrite에 선언되어있기때문에 state가 변경되면 전체가 렌더링 된다.
이 input 컴포넌트를 따로 분리하여 사용한다면, input의 상태 값이 변경할 때마다 DailyWrite가 변경되는 것이 아닌, input컴포넌트만 리렌더링되어 성능에 최적화가 가능하다.
function InputText(PH) {
const [text, setText] = useState('')
const handleTextChange = (e) => setText(e.target.value);
return (
<>
<input onChange={handleTextChange} placeholder={PH} />
</>
)
}
export default function App() {
return (
<InputText PH="placeholder" />
)
}
사실 실제 졸업작품 코드를 리팩토링 해보고싶었는데 ㅎㅎ.. 꽤나 답이없다..
역시 미리미리 생각하고 코딩해야한다..
아래 이미지척럼 Title 컴포넌트에는 text라는 props이 고정되어있다.
// Title Components
import React from "react";
import styled from "styled-components";
const TitleText = styled.p`
font-size: 32px;
font-weight:600;
color:white;
`
function Title(props) {
const { text } = props;
return (
<TitleText>{text}</TitleText>
)
}
export default Title;
그러나 동일하게 input 컴포넌트에 입력하는 과정을 렌더링해보면 dispalyName으로 등록해둔 "이 멍충이들아"가 계속해서 리렌더링 되고있다.
만약 아래와 같이 memo를 통해 코드를 수정한다면, 이전 값을 저장하기때문에 고정된 props이라면 다시 렌더링 될 이유가 없다. 실제로 확인해보면 더 이상 렌더링 되지 않는걸 볼 수 있다.
// After
import { memo } from "react";
import styled from "styled-components";
const TitleText = styled.p`
font-size: 32px;
font-weight:600;
color:white;
`
const Title = memo(function Title(props) {
const { text } = props;
return (
<TitleText>{text}</TitleText>
)
})
export default Title;
처음에 메모이제이션이나, 컴포넌트 관리 등에 대해서 학습했을땐 막연하게 이론적인 부분으로만 습득을 했었지 실제로 적용해볼 기회가 없었고, 딥다이브 자체가 예제코드를 어느정도의 "리액트"가 아닌 "코딩"에 대한 지식을 많이 요구하기에 내가 이해하기는 어려웠던 한계점이 있었다.
그러나, 리액트 개발도구를 통해서 실제 내 졸업작품의 렌더링 과정들을 살펴보니 조금 더 수월하게 이해가 갔다.
또한, 어느정도 서비스의 규모가 커지고 복잡해지니 문제를 발견하고 수습하기에는 너무 많이 손봐야했다. 따라서 틈틈이 원하는 방향으로 렌더링이 되고 있는지, 메모이제이션을 통한 최적화를 잘 하고 있는지 확인해 볼 필요가 있을 것 같다.
"디버깅과 최적화는 틈틈이!"
우기명 함수