7-11. 최적화하다
구성 요소 및 작업과 관련된 최적화
낭비되는 작업이 있는지 확인하는 방법
정적 분석
VSCode에서 코드 상태 보기 및 평가
동적 분석
프로젝트를 시작한 다음 도구의 힘을 사용하여 낭비되는 부분을 확인하는 방법
동적 분석을 수행합니다.
컴포넌트를 바로 리렌더링 했을 때 빛을 발하는 기능인 하이라이트 컴포넌트의 기능을 통해 파싱할 예정입니다.

찾아보니 날짜가 변경되면 필터와 “새 저널 쓰기” 버튼을 다시 렌더링할 필요가 없다는 것을 알았습니다.
코드의 이 부분을 보면 원인을 알 수 있습니다.
Home.js
const increaseMonth = () => {
setCurDate(
new Date(curDate.getFullYear(), curDate.getMonth() + 1, curDate.getDate())
);
};
const decreaseMonth = () => {
setCurDate(
new Date(curDate.getFullYear(), curDate.getMonth() - 1, curDate.getDate())
);
};
이 부분의 코드를 보면 상태 변경 기능이 실행되고 있는 것을 알 수 있는데, 상태가 변경되거나 부모 요소가 다시 렌더링될 때 다시 렌더링이 일어나기 때문에 DiaryList 컴포넌트는 Home에서 다시 렌더링되고, ControlMenu 컴포넌트는 DiaryList의 자식도 쓸모가 없습니다.재 렌더링이 없음을 알 수 있습니다.
불필요한 ControlMenu 재렌더링 제거
이제 우리는 이전에 배운 React.memo를 사용하여 이것을 조정할 것입니다.
const ControlMenu = React.memo(({ value, onChange, optionList }) => {
return (
<select
className="ControlMenu"
value={value}
onChange={(e) => onChange(e.target.value)}
>
{optionList.map((it, idx) => (
<option key={idx} value={it.value}>
{it.name}
</option>
))}
</select>
);
});
React.memo는 useState가 반환하는 상태 변경 함수가 아닌 처리 가능한 함수를 중간에 생성하고 해당 함수를 prop으로 전달하면 제대로 동작하지 않습니다.
구성 요소가 다시 렌더링되면 함수가 다시 생성됩니다. 따라서 React.meno에서 비교할 때 다른 prop과 비교가 이루어집니다. useState에서 상태 변경 기능은 동일한 ID를 보장하므로 useCallback 처리라고 생각하시면 됩니다.
중간에 핸들러 함수를 만들 필요가 없다면 useCallback 으로 어렵게 만들지 마시고 생태변화 기능을 낮추면 쉽게 최적화 할 수 있습니다.
목록 필터링을 변경할 때 diaryItem 구성 요소의 다시 렌더링을 제거합니다.
diaryList 구성 요소의 자식입니다.
dirayList 구성 요소에서 필터 값이 변경되면 상태가 변경됨에 따라 업데이트됩니다.
결과적으로 자식의 diaryItem 구성 요소도 계속해서 다시 렌더링됩니다.
export default React.memo(DiaryItem);
Reag.memo구성 요소를 감싸는 경우 암기하다된다
저널 항목 페이지에서 여러 EmotionItems 입력 창의 다시 그리기 제거
diaryEditor의 콘텐츠 상태가 변경됨에 따라 하위 구성 요소인 EmotionItem 구성 요소도 다시 렌더링됩니다.
EmotionItem.js
export default React.memo(EmotionItem);
먼저 React.memo에 EmotionIItem 컴포넌트를 래핑하되 상태 변경 함수가 아닌 onClick 함수도 useCallback으로 재사용해야 합니다.
DiaryEditor.js
onClick에 전달되는 함수인 handleClickEmote 함수도 useCallback을 사용하여 최적화됩니다.
const handleClickEmote = useCallback((emotion) => {
setEmotion(emotion);
}, ());
상태 변경 기능이 기능에 포함되어 있기 때문에 별도의 작업 없이 최적화가 가능합니다.
7-12 배포 준비
배포 전 프로젝트 유효성 검사
index.html의 제목 변경
<title>감정 일기장</title>
메타 설명 태그 변경
웹사이트에 대한 설명을 작성할 수 있는 곳
<meta name="description" content="나만의 감정일기장" />
HTML 언어 변경
<html lang="ko">
페이지별로 제목 페이지 편집
UseEffect는 문서의 title이라는 요소의 모든 제목을 가져와 배열로 반환하며 배열의 첫 번째 요소가 변경되면 페이지의 제목도 변경될 수 있습니다.
일기 페이지
useEffect(() => {
const titleElement = ducoment.getElementByTagName("title"(0));
titleElement.innerHTML = `감정 일기장 = ${id}번의 일기`;
}, ());
새 페이지
useEffect(() => {
const titleElement = ducoment.getElementByTagName("title"(0));
titleElement.innerHTML = `감정 일기장 - 새 일기`;
}, ());
페이지 편집
useEffect(() => {
const titleElement = ducoment.getElementByTagName("title"(0));
titleElement.innerHTML = `감정 일기장 = ${id}번의 일기 수정`;
}, ());
브라우저 탭의 아이콘 수정
강의에서 제공하거나 요청한 이미지를 다운받은 후 이름을 facicon.ico로 변경하여 프로젝트의 public 폴더에 넣어주세요.

프로젝트 크기 줄이기
증가하는 코드 들여쓰기는 공간을 차지합니다.
압축 파일로 보내는 것과 마찬가지로 필요한 파일과 코드를 압축하여 서버에 업로드하고 제공할 수 있는 방식으로 빌드하면 됩니다.
터미널에 npm run build 입력
완료 후 프로젝트 구조를 보면 새로운 빌드 폴더가 보입니다.

npm build 를 실행하고 터미널을 보면 그것은 이렇게 될 것입니다

serve -s build 로 배포할 수 있다고 합니다.
그러나 serve 가 설치되어 있지 않기 때문에 위의 install 명령도 같이 나옵니다.
설치가 완료되면 배포할 준비가 된 것입니다.
터미널에 serve -s build 를 입력하면 배포 시작
제 경우 zsh: command not found: serve 가 나와서 안타깝게 검색해봤습니다.
npx 서브 빌드할 내용을 찾아보니 잘 되는 것을 확인했습니다.
이렇게 터미널이 나오면 잘 먹힌 것입니다.

단, 이렇게 해도 오류가 발생할 수 있는 부분이 있습니다.
App.js에 저널 데이터가 없어도 빈 배열이 true이므로 해당 부분을 실행하여 발생한 오류입니다.
다이어리 데이터가 없을 때 다이어리 리스트 아이디로 접근하지 못하도록 if 문을 추가했습니다.
useEffect(() => {
const localData = localStorage.getItem("diary");
if (localData) {
const diaryList = JSON.parse(localData).sort(
(a, b) => parseInt(b.id) - parseInt(a.id)
);
if (diaryList.length >= 1) {
dataid.current = parseInt(diaryList(0).id + 1);
dispatch({ type: "INIT", data: diaryList });
}
}
}, ());
코드를 변경하고 다시 빌드하고 배포하면 이전 오류가 사라진 것을 확인할 수 있습니다.
다시 실행해보니 이번에는 탭 이름이 바뀌지 않는다는 오류가 떴다.
const titleElement = document.getElementsByTagName("title")(0);
코드의 해당 부분에 오타가 있는 터무니없는 버그 중 하나였습니다.
const titleElement = document.getElementsByTagName("title"(0));
이렇게 배포하기 전에 오류를 잡으려고 했습니다.
7-13 배포
하나. 서버 구축
서버 유지 보수, 방화벽 등
2. 중포 기지
Google에서 제공하는 서비스
Firebase로 이동하여 새 프로젝트를 만듭니다.
프로젝트 생성이 완료되면 Build 탭 -> Hosting
시작하기
npm 설치 -g firebase-tools
터미널에서 명령으로 Firebase의 기능을 사용할 수 있도록 도와주는 도구
설치가 완료되면 프로젝트가 있는 디렉토리로 변경하고
Firebase 로그인
입력 프로세스가 있지만 zsh의 창에서 작업이 계속되지 않습니다: Command not found: Firebase.
단말기에 자동 설치 스크립트를 추가하면 문제가 해결된다고 해서 바로 입력했더니 해결되었습니다.
자동 설치 스크립트: curl -sL https://firebase.tools | 세게 때리다
설치가 완료되면 명령을 입력하면 Google 로그인 화면이 나타납니다.
로그인이 완료되면 프로젝트를 작업한 폴더에서
Firebase 초기화 명령을 입력합니다.
이 명령을 입력하면
현금화할 준비가 되셨습니까? y를 눌러 시작하면 선택 창이 다시 나타납니다.

사용할 서비스를 선택하는 화면입니다. 공간으로 호스팅을 선택하고 Enter 키를 눌러 다음 화면으로 이동합니다.
옵션을 선택하십시오 탭에서 기존 프로젝트 사용을 선택하십시오.
이 디렉터리의 기본 Firebase 프로젝트 선택에서 이전에 만든 프로젝트의 이름을 입력합니다.
VSCode에서 생성된 firebase.json 및 .firebaserc 파일 수정
firebaserc
{
"projects": {
"default": "jeo-react-project"
}
}
firebase.json
{
"hosting": {
"site": "jeo-react-project",
"public": "build",
"ignore": ("firebase.json", "**/.*", "**/node_modules/**"),
"rewrites": (
{
"source": "**",
"destination": "/index.html"
}
)
}
}
재구축 및 배포
3) 배포 전 최종 빌드
npm 실행 빌드
4) Firebase에 배포
모든 것이 준비되면 생성된 정적 파일을 배포합니다.
Firebase 배포
7-14.차트 열기
썸네일 만들기
메타태그 추가
index.html
<메타 재산=”위: 그림” 내용물=”%PUBLIC_URL%/thumbnail.png” />
<메타 재산=”og:site_name” 내용물=”감정 일기” />
<메타 재산=”og: 설명” 내용물=”나의 작은 감성 일기” />
위: 그림 링크에서 가져온 사진
%PUBLIC_URL%사용 공공의 디렉토리가 사용됩니다
og:사이트_이름: 링크의 제목
위:설명: 링크에 대한 설명
단, 즉시 적용되지는 않습니다. 해결책은 카카오 디벨로퍼 (도구) > (초기화 도구) > 유형(OG(오픈 그래프) 캐시).링크의 OpenGraph를 초기화할 수 있습니다.
이렇게 하면 카카오톡으로 링크를 보낼 때 썸네일, 이름, 설명이 잘 표시되는 것을 볼 수 있습니다.

강의를 처음부터 끝까지 들었는데 중간에 할 일이 있어서 한번에 다 들을 수는 없었지만 꾸준하게 해내서 다행입니다.