11.1 useDebugValue란?11.2 React Developer Tools 설치방법 및 사용방법11.2.1 크롬 브라우저 확장 프로그램 설치11.2.2 독립 실행형 프로그램 설치 11.2.3 React Developer Tools 사용방법11.3 커스텀 훅 디버깅하기11.4 useDebugValue 주의사항 & 개선사항11.4.1 useDebugValue 의 사용시 주의사항11.4.2 useDebugValue를 더 효율적으로 사용하기
11.1 useDebugValue란?
useDebugValue는 React Developer Tools 내에서 커스텀 훅의 내부 논리에 대한 자세한 정보를 제공하는 빌트인 훅입니다. useDebugValue는 커스텀 훅을 디버깅할 때 훨씬 더 나은 디버깅 경험을 제공합니다.
디버그(debug)란?
디버그(debug) 혹은 디버깅(debugging)은 개발 단계 중에 발생하는 시스템의 논리적인 오류를 찾아내고, 그 원인을 밝히고 수정하는 작업 과정을 일컫습니다.
useDebugValue는 다음과 같은 형식으로 사용합니다.
useDebugValue(debugValue) // 또는 useDebugValue(debugValue, debugValue => debugValue.toString());
React Developer Tools 내에서 디버그 값을 표시할 때, 형식을 지정하는 것이 비용이 많이 드는 작업일 경우일 수 있습니다. 커스텀 훅이 검사되지 않는 한, 형식을 지정하는 작업이 불필요하기 때문에, useDebugValue의 두 번째 인자로 함수를 선택적으로 전달할 수 있습니다.
11.2 React Developer Tools 설치방법 및 사용방법
React에서는 주로 props와 state를 통해 실수의 원인을 추적합니다. props와 state를 추적하여 어떤 컴포넌트에서 문제가 발생하는지 확인할 수 있다면, 다른 문제 원인과 분리할 수 있습니다. 이렇게 다른 문제와 분리할 수 있다면, 문제 발생 원인을 더욱 쉽게 발견할 수 있다는 장점이 있습니다. 따라서, 문제가 발생했을 때 코드 베이스(Codebase)로 인한 실수의 원인을 추적할 수 있도록 환경을 만드는 것은 중요합니다.
개발 시 화면에서 렌더링 문제가 발생했을 경우, React Developer Tools를 사용하여 어떤 props 혹은 state에서 문제가 발생했는지를 확인할 수 있습니다. React Developer Tools를 사용하는 방법에 알아보기 위해, 먼저 React Developer Tools를 설치하는 방법에 대해 알아보도록 하겠습니다.
11.2.1 크롬 브라우저 확장 프로그램 설치
크롬 브라우저에서 React Developer Tools를 확장 프로그램으로 사용하려면 크롬 브라우저를 미리 설치해야 합니다. 크롬 브라우저에서 웹 스토어 페이지로 이동합니다. 그리고 웹 스토어 페이지에서 React Developer Tools를 검색한 뒤, 해당 프로그램을 ‘크롬에 추가’ 버튼을 눌러 크롬에 추가합니다.

해당 프로그램을 크롬에 추가했다면 React를 실행한 브라우저의 개발자 도구에서 Components 탭으로 이동하여 React Developer Tools를 사용할 수 있습니다.

11.2.2 독립 실행형 프로그램 설치
독립 실행형 프로그램을 설치하기 위해서 node.js 환경 구축이 선행되어야 합니다. node.js을 사용할 수 있는 환경을 만들었다면, 터미널에서 다음의 코드를 실행하여 React Developer Tools를 설치합니다. 다음의 코드는 대표적인 패키지 관리 도구인 yarn과 NPM에서 설치하는 방법입니다.
yarn add --dev react-devtools
npx react-devtools
위의 과정으로 설치한 후 터미널에 아래 코드를 실행한다면 그림 11-3과 같은 프로그램 창이 실행될 것입니다. 독립 실행형 프로그램에서는 React Native, React DOM 그리고 Profiler를 이용할 수 있으나, 이번 예제에서는 React DOM을 이용하여 실행되는 것을 확인해보겠습니다.
react-devtools

React DOM에서 제공하는 두 링크 중 하나를 클릭하여 클립보드에 저장합니다. 저장된 script 태그를 개발 중인 index.html 파일의 head 태그 바로 아래에 다음 코드를 붙여줍니다.
<!DOCTYPE html> <html lang="ko"> <head> <script src="http://localhost:8097"></script>
위의 과정대로 진행하여 개발 중인 페이지를 실행했을 때, 정상적으로 React Developer Tools에 연결될 것입니다. 주의해야 할 점으로 사용자가 React Developer Tools에 접근하지 못하도록 배포 전에 위에서 작성한 script 태그를 삭제해야 합니다.
11.2.3 React Developer Tools 사용방법
React Developer Tools를 활용하면 Component Inspector 내부에 있는 데이터의 state나 props를 시각화할 수 있습니다. Component Inspector가 전달하는 디버그 정보에서는 useState나 useEffect와 같은 내장된 React Hook들에 대한 정보만 표시하는 것으로 제한합니다. 또한 Hook 레이블이 존재하지 않아, 해당 정보를 이해하는데 어려움이 있을 수 있습니다. 하지만, useDebugValue를 사용한다면 Hook 레이블을 통해 더 많은 정보를 전달할 수 있게 도와줍니다.
실제로 useDebugValue를 어떻게 사용할 수 있는지 간단한 예제를 통해 살펴보겠습니다. 어떠한 애플리케이션의 상태가 ‘시작’, ‘실행 중’, ‘종료’의 상태로 한정되고, 버튼의 클릭 이벤트로 세 개의 상태를 순차적으로 변경하는 프로그램을 작성한다고 가정합시다. 아래의 코드를 작성하여 React Developer Tools에서 어떻게 표현하는지 확인해보겠습니다.
import React from "react"; import useChangeAppState, { STATE_START, STATE_RUNNING, } from "./hooks/useChangeAppState"; function App() { const [state, next] = useChangeAppState(); const msg = state===STATE_START ? "앱 시작" : state===STATE_RUNNING ? "앱 실행 중" : "앱 종료"; return ( <div> <p>{msg}</p> <button onClick={next}>next</button> </div> ); } export default App;
import { useState, useDebugValue } from "react"; export const STATE_START = 0; export const STATE_RUNNING = 1; export const STATE_STOP = 2; export default function useChangeAppState() { const [state, setState] = useState(STATE_START); const next = () => setState(state === STATE_STOP ? STATE_START : state + 1); useDebugValue( state === STATE_START ? "앱 시작" : state === STATE_RUNNING ? "앱 실행 중" : "앱 종료" ); return [state, next]; }
위의 코드는 next 버튼을 누를 때마다 애플리케이션 실행 상태가 달라지는 코드입니다. React Developer Tools에서 애플리케이션 실행 상태에 따라 다른 텍스트(’앱 시작’, ‘앱 실행 중’, ‘앱 종료’)가 표시되는 것을 확인할 수 있습니다.

11.3 커스텀 훅 디버깅하기
프로그래밍 중 문제가 생겨 값을 확인해야 한다면 console.log를 통하여 값을 검증하는 게 일반적일 것입니다. console.log를 사용하는 방법은 React에서도 충분히 좋은 방법임은 틀림없으나 커스텀 훅이 여러 번 사용될 때 사용된 컴포넌트에서 Hook이 가지고 있는 현재 상태를 확인하기 어려워집니다.
아래 예제는 여러 번 사용되는 커스텀 훅으로 문제가 생겼을 시 console.log로 값을 출력할 때 생기는 문제입니다.
import { useState, useDebugValue } from 'react'; export const STATE_START = 0; export const STATE_RUNNING = 1; export const STATE_STOP = 2; export default function useChangeAppState() { const [state, setState] = useState(STATE_START); const next = () => setState(state === STATE_STOP ? STATE_START : state + 1); console.log( state === STATE_START ? "앱 시작" : state === STATE_RUNNING ? "앱 실행 중" : "앱 종료" ); return [state, next]; }
import React from "react"; import useChangeAppState, { STATE_START, STATE_RUNNING, } from "./hooks/useChangeAppState"; import ItemComponent from "./ItemComponent"; function App() { const [state, next] = useChangeAppState(); const msg = state === STATE_START ? "앱 시작" : state === STATE_RUNNING ? "앱 실행 중" : "앱 종료"; return ( <div> <p>{msg}</p> <button onClick={next}>next</button> <ItemComponent /> <ItemComponent /> {... 중략} <ItemComponent /> </div> ); } export default App;


위 예제에서 next 버튼을 누른다면 상태가 “앱 실행 중”으로 변경되고 상태가 변경되면서 모든 컴포넌트가 재 렌더링 될 것입니다. 만약 위와 같이 해당 커스텀 훅을 사용하는 많은 컴포넌트가 있다면 재 렌더링 될 때마다 각각의 console.log가 실행되어 원하는 커스텀 훅의 현재 상태를 찾기 어려워집니다.
이때, useDebugValue를 사용한다면 커스텀 훅을 사용하는 컴포넌트가 늘어나도 특정 컴포넌트에서 사용된 커스텀 훅의 현재 상태를 바로 확인할 수 있습니다.
import { useState, useDebugValue } from 'react'; export const STATE_START = 0; export const STATE_RUNNING = 1; export const STATE_STOP = 2; export default function useChangeAppState() { const [state, setState] = useState(STATE_START); const next = () => setState(state === STATE_STOP ? STATE_START : state + 1); useDebugValue( state === STATE_START ? "앱 시작" : state === STATE_RUNNING ? "앱 실행 중" : "앱 종료", ); return [state, next]; }

커스텀 훅의 구조가 복잡하지 않고 단순 값만 알고 싶다면 console.log만 사용해도 될 것입니다. 하지만 보다 복잡하고 많은 양의 커스텀 훅을 사용하게 되었을 때, useDebugValue 훅은 우리의 훅이 어떤 컴포넌트에서 어떤 상태인지 조금 더 보기 쉽게 알려줄 것입니다.
11.4 useDebugValue 주의사항 & 개선사항
11.4.1 useDebugValue 의 사용시 주의사항
useDebugValue 또한 Hook의 규칙을 따르기 때문에, 반복문과 조건문, 중첩된 함수 안에서는 사용하지 못합니다.
또한, 각 컴포넌트의 top level에서 작성하면 아무런 동작을 하지 않습니다. Hook의 내부(최상단)에서 작성해야 동작하게 됩니다.
function App() { {/* ------------------ */} useDebugValue("test"); {/* ------------------ */} } export default App;
function App() { {/* ------------------ */} const useColorState = () => { useDebugValue("test"); }; useColorState(); {/* ------------------ */} } export default App;
11.4.2 useDebugValue를 더 효율적으로 사용하기
useDebugValue를 더 개선하여서 useState 값에 라벨과 간단한 설명을 붙여서 보여줄 수 있습니다.
아래 예제를 통해 좀 더 향상된 디버깅을 하는 방법을 알아보겠습니다.
아래 그림처럼 세 개의 버튼을 통해, 박스의 색상을 변경할 수 있으며 커스텀된 디버깅 메시지를 출력하는 애플리케이션을 만들어보겠습니다.


import { useState, useDebugValue } from "react"; const useBoxColorState = (initialValue, message) => { const [value, setValue] = useState(initialValue); useDebugValue(`${message}: ${value}`); return [value, setValue]; }; export default useBoxColorState ;
하나의 커스텀 훅을 만들고, 훅 내부에서 받아온 인자 값을 초기 값으로 하여 state값을 만들어줍니다.
useDebugValue를 훅 안에서 선언해주고, 상태 값과 상태관리 값을 반환하여 줍니다.
위처럼 커스텀 훅 안에 useDebugValue를 선언해주면 해당 훅을 호출할 때, 디버깅 시에 use를 제외한
BoxColorState
라는 이름으로 디버깅메시지를 출력해주게 됩니다.import { useDebugValue, useEffect } from "react"; import { useState } from "react"; import useBoxColorState from "./useBoxColorState.jsx"; import "./style.css"; function App() { const [isColor, setIsColor] = useBoxColorState("", "현재 박스색상"); const [isTomato, setIsTomdato] = useState(false); const [isPink, setIsPink] = useState(false); const [isSky, setIsSky] = useState(false); useEffect(() => { if (isPink) { setIsColor("pink"); } if (isSky) { setIsColor("sky"); } if (isTomato) { setIsColor("tomato"); } }, [isTomato, isPink, isSky]); return ( <> <button onClick={() => { setIsTomdato(true); setIsPink(false); setIsSky(false); }} > Tomato </button> <button onClick={() => { setIsTomdato(false); setIsPink(true); setIsSky(false); }} > Pink </button> <button onClick={() => { setIsTomdato(false); setIsPink(false); setIsSky(true); }} > Sky </button> <div className={isColor}></div> </> ); } export default App;
위에서 만든 useBoxColorState Hook을 호출하여
isColor
, setIsColor
에 저장합니다. useState를 대신하여 사용한다고 보면 됩니다. 첫 번째 파라미터로는 초기 값을 넣고, 두 번째 파라미터로는 출력할 디버깅 메시지를 넣어줍니다.
이후, 각 버튼의 클릭으로
isColor
값이 변경될 때마다 디버깅 메시지가 수정되어 출력되게 됩니다..pink { width: 100px; height: 100px; background-color: pink; } .sky { width: 100px; height: 100px; background-color: skyblue; } .tomato { width: 100px; height: 100px; background-color: tomato; }
위의 예제에서 사용된 CSS 파일입니다.