15.4 커스텀 훅 사용해보기

render() { return ( <React.Fragment> <ChildA /> <ChildB /> <ChildC /> </React.Fragment> ); }
React 공식문서

15.4.1 useTitle

Document Title

웹 사이트에 접속하면 브라우저의 상단 탭에서 현재 페이지의 제목을 볼 수 있으며 해당 페이지의 제목을 Document Title이라고 합니다. Document Title은 가장 대표적인 웹 페이지의 타이틀로, 각 페이지의 주제를 가장 잘 나타낼 수 있는 요소이자 해당 웹 페이지를 사용하는 유저에게 현재 자신이 보고 있는 웹 페이지가 어떤 페이지인지를 알려주는 중요한 요소입니다.
 
notion imagenotion image
 
하지만 React는 SPA이므로 CSS, JS 등의 번들이 포함된 하나의 index.html 파일만 가지기 때문에 을 각 페이지마다 Document Title을 변경하는데 한계점이 있습니다. 이를 위해 현재 페이지의 title을 바꿔주기 위한 useTitle 커스텀 훅을 활용한다면 페이지마다 Document Title을 변경할 수 있습니다.
 

useTitle

import { useEffect } from 'react'; const useTitle = (title) => { useEffect(() => { const prevTitle = document.title; document.title = title; return () => (document.title = prevTitle); }, [title]); }; export default useTitle;
 
useTitle은 unmount시까지 이전 Document Title이다 새 페이지로 mount될 때 그 페이지의 타이틀로 바꿀 수 있는 커스텀 훅입니다.
useTitle에서는 title을 매개변수로 전달 받아, useEffect를 통해 감시하고 있습니다. 새로운 컴포넌트가 mount 되고, 해당 컴포넌트에서 useTitle을 호출하는 동시에 변경하고자 하는 title을 전달하면, useTitle 내부의 useEffect에서는 title이 변경되었으므로 내부의 코드를 실행시킵니다. useEffect 내부에서는 Document Title을 입력 받은 title로 변경하고, 해당 컴포넌트가 사라질 때 동작할, Document Title을 원래대로 돌려놓기 위한 cleanup 함수를 반환합니다.

useTitle 적용

import useTitle from './useTitle'; function Login() { useTitle('Login - React'); return <div>Login 페이지</div> } export default Login;
 
notion imagenotion image
그리고 위 코드처럼 useTitle 커스텀 훅을 Login 컴포넌트에 적용하게 되면 다음과 같이 Document Title이 변경된 것을 확인할 수 있습니다. 그리고 사용자가 어느 사이트에 접속한 것인지는 인지하고 있으므로 Login 페이지처럼 서브 페이지 이름이 앞에 나오는 것이 사용자 피로도를 낮출 수 있습니다.
 
01_11 수정…? 추가했으면 좋겠다 싶은 것들, 기존 내용 바탕으로 추가.. 확인 부탁드립니다!!

Document Title

웹 사이트에 접속하면 브라우저의 상단 탭에서 현재 페이지의 제목을 볼 수 있으며 해당 페이지의 제목을 Document Title이라고 합니다. Document Title은 가장 대표적인 웹 페이지의 타이틀로, 각 페이지의 주제를 가장 잘 나타낼 수 있는 요소이자 해당 웹 페이지를 사용하는 유저에게 현재 자신이 보고 있는 웹 페이지가 어떤 페이지인지를 알려주는 중요한 요소입니다.
 
notion imagenotion image
 
하지만 React는 SPA이므로 CSS, JS 등의 번들이 포함된 하나의 index.html 파일만 가지기 때문에 을 각 페이지마다 Document Title을 변경하는데 한계점이 있습니다. 이를 위해 현재 페이지의 title을 바꿔주기 위한 useTitle 커스텀 훅을 활용한다면 페이지마다 Document Title을 변경할 수 있습니다.
 

useTitle

import { useEffect } from 'react'; const useTitle = (title) => { useEffect(() => { console.log('컴포넌트 생성'); const prevTitle = document.title; document.title = title; return function () { console.log('컴포넌트 삭제'); document.title = prevTitle } }, [title]); }; export default useTitle;
useTitle.jsx
 
render() { return ( <React.Fragment> <ChildA /> <ChildB /> <ChildC /> </React.Fragment> ); }
React 공식문서
render() { return ( <React.Fragment> <ChildA /> <ChildB /> <ChildC /> </React.Fragment> ); }
React 공식문서
useTitle은 mount 된 컴포넌트가 unmount되거나 새 페이지로 mount 될 때까지 상단의 Document Title을 입력 받은 내용으로 변경하고, 유지할 수 있게 해주는 커스텀 훅입니다.
 
useTitle에서는 title을 매개변수로 전달 받아, useEffect를 통해 감시하고 있습니다. 새로운 컴포넌트가 mount 되고, 해당 컴포넌트에서 useTitle을 호출하는 동시에 변경하고자 하는 title을 전달하면, useTitle 내부의 useEffect에서는 title이 변경되었으므로 내부의 코드를 실행시킵니다. useEffect 내부에서는 Document Title을 입력 받은 title로 변경하고, 해당 컴포넌트가 사라질 때 동작할, Document Title을 원래대로 돌려놓기 위한 cleanup 함수를 반환합니다.
 

useTitle 적용

import useTitle from './useTitle'; function Modal() { useTitle('Modal - React'); return <div>모달</div> } export default Modal;
Modal.jsx
 
import { useState } from "react"; import Modal from "./Modal"; function App() { const [display, setDisplay] = useState(false); const showModal = () => { setDisplay(!display); } return ( <div> <button onClick={showModal}>모달 띄우기</button> {display && <Modal />} </div> ); } export default App;
App.jsx
 
notion imagenotion image
 
위의 페이지에서는 화면에 버튼 하나가 존재하고, 해당 버튼을 통해 간단한 모달 창 하나를 띄울 수 있는 페이지입니다.
 
notion imagenotion image
 
화면의 버튼을 눌러 모달창을 띄울 경우, 모달창이 화면에 나타날 때, useTitle을 호출하는 동시에 변경하고자 하는 title을 전달해주었기 때문에 useTitle 내부의 useEffect가 실행되고, 콘솔에 ‘컴포넌트 생성’이라는 로그가 출력되며 Document Title이 변경되는 모습을 확인할 수 있습니다.
 
notion imagenotion image
 
다시 버튼을 눌러 모당 창을 없앨 경우, 모달 컴포넌트가 unmount 되는 과정에서 useTitle 내부의 useEffect에서 반환한 cleanup 함수가 호출되고, 콘솔에 ‘컴포넌트 삭제’ 로그가 뜨는 동시에 Document Title이 원래대로 변경되는 것을 확인할 수 있습니다.
 
(cleanup까지 구현하셨는데 해당 부분이 묻히는 것 같아서 좀 바꿔보았는데 어떠신가요..?)
 
 
useTitle을 통해 페이지가 변경될 때마다 관련 내용을 Document Title에 반영할 수 있다면 현재 페이지를 사용하고 있는 사용자가 어떤 내용을 가진 사이트에 접근하고 있는지를 보다 명확이 인지할 수 있게 되고, 이는 곧 사용자의 피로도를 낮추며 쾌적한 사용자 경험으로 이어질 수 있습니다.