[React] Virtual Scroll(가상 스크롤)로 렌더링 최적화하기 (react-window)
·
Library & Runtime/React
리스트가 길어질수록 모든 항목을 한 번에 렌더링하면 성능 문제가 발생한다.특히 1,000개 이상의 데이터를 렌더링할 때 브라우저가 느려지고 사용자 경험이 저하된다.이를 해결하는 기술이 Virtual Scroll(가상 스크롤)이다. 🔎 가상 스크롤(Virtual Scroll)이란?가상 스크롤(Virtual Scroll)은 긴 리스트나 테이블에서 화면에 보이는 항목만 렌더링하고 나머지 항목은 렌더링하지 않는 기법이다.사용자가 스크롤할 때마다 보여줄 항목만 동적으로 추가한다.렌더링 비용과 메모리 사용량을 크게 줄일 수 있다.항목 수가 많아도 초기 렌더링 속도를 빠르게 유지하고 스크롤 성능을 높이는 것이다.💡 예: 카카오톡, 인스타그램, 유튜브 피드 → 수천~수만 개 항목이 있지만 느려지지 않는다. 🧩 ..
[React] 계산/렌더링 최적화: useMemo + React.memo 실험
·
Library & Runtime/React
부모와 자식 컴포넌트 간의 렌더링 최적화와 계산 최적화가 어떻게 작동하는지 실험해보려고 한다.부모 컴포넌트가 리렌더링될 때 자식 컴포넌트가 리렌더링 되는지 확인하고 useMemo와 React.memo가 각각 최적화에 어떻게 작동하는지 알아보자. 🧩 예제 코드ParentWithMemoinput과 count 상태를 관리input 값으로 무거운 계산 실행계산 결과(calculatedValue)를 자식 컴포넌트에 넘긴다import { useMemo, useState } from 'react';import MemoizedChild from './MemoizedChild';const heavyCalculation = (num: number) => { console.log('💥 무거운 계산 실행'); let ..
[React] 무거운 연산 최적화 : 일반 계산 vs useMemo
·
Library & Runtime/React
React를 사용하다 보면 컴포넌트가 리렌더링될 때마다 불필요하게 무거운 계산이 반복 실행되어 앱 성능이 저하되는 경우가 많다.이 문제를 해결하기 위한 최적화 기법 중 하나가 useMemo이다.useMemo와 일반 계산을 비교하는 예제를 통해 언제 useMemo가 필요한지 알아보자. 🧩 예제 코드import { useMemo, useState } from 'react';const heavyCalculation = (num: number) => { console.log('💥 무거운 계산 실행'); let result = 0; for (let i = 0; i { const [count, setCount] = useState(0); const [input, setInput] = useState..
[React] 자식 컴포넌트 렌더링 : 일반 함수 vs useCallback
·
Library & Runtime/React
컴포넌트에서 자식에게 함수를 props로 넘길 때, 그 함수가 일반 함수인지 useCallback으로 감싼 함수인지에 따라 자식 컴포넌트의 렌더링 여부가 달라진다. 🎯 실험 목표 부모 컴포넌트에서 자식에게 함수를 전달할 때, 일반 함수를 전달했을 때와 useCallback으로 메모이제이션한 함수를 전달했을 때를 비교하고자 예제 코드를 준비했다.어떤 경우에 자식 컴포넌트가 불필요하게 렌더링되는지 확인해 보자. 🧩 예제 코드ChildRaw: 일반 함수를 props로 받는 자식ChildMemo: useCallback 함수를 props로 받는 자식 👉 두 자식 모두 React.memo로 감싸져 있음import { memo, useCallback, useState } from 'react';const Chi..
[React] 컴포넌트 생명주기 : useEffect, 마운트, 언마운트
·
Library & Runtime/React
🔨 마운트 (mount)컴포넌트가 처음 화면에 나타나는 시점JSX로 만든 컴포넌트가 실제 DOM에 "붙는" 순간초기화 작업(데이터 불러오기, 이벤트 리스너 등록 등)을 주로 이 시점에 처리useEffect(() => { ... }, [])의 본문이 실행되는 타이밍 🧩 예시{isVisible && }isVisible가 true가 되는 순간 → MyComponent가 마운트됨 🧹 언마운트 (unmount)컴포넌트가 화면에서 사라지는 시점React가 필요 없어진 컴포넌트를 DOM에서 제거하는 시점useEffect의 cleanup 함수가 실행되는 타이밍 (타이머 제거, 이벤트 해제 등)useEffec의 return 함수가 이 시점에 실행됩 🧩 예시{isVisible && }isVisible가 false..
[React/S3] 이미지 저장 구현 (+ CORS 에러 해결)
·
Library & Runtime/React
PWA에서 다운로드 버튼을 클릭하면 사용자의 갤러리에 이미지가 저장되도록 하는 것이 구현 목표이다.일반적인 웹에서의 다운로드 링크로는 한계가 있었다. 💾 이미지 다운 구현1. Blob 객체로 이미지 데이터 처리현재 나는 백엔드에서 받은 이미지 url을 가지고 있는 상황이다.이미지 url을 Blob으로 변환한다. 2. 패키지 설치file-saver 라이브러리를 활용해 Blob을 png로 변환한다.나 같은 경우는 파일명에 .png로 지정해 주어 png로 저장되지만, .jpg로 지정하면 jpg로 저장된다.yarn add file-saver 3. 파일 저장 구현const handleDownload = async () => { try { const response = await fetch(imageUrl..
camelCase 요청 데이터를 snake_case로 변환하기
·
Library & Runtime/React
🐫 snake_case 응답 데이터를 camelCase로 변환하기 이전에 백엔드(Python)에서 프론트엔드(React)로 보내는 응답을 받았을 때, snake_case로 작성되어 있어서 프론트엔드 코드와 key가 맞지 않는 문제가 있었다. 그래서 camelcase-keys 라이브러리를 사용했다. 이번에는 파라미터에 값을 넣고 보내려고 하니까 400번대가 뜨는 거 아닌가..?! 확인해보니 파라미터명이 맞지 않았다.생각해 보니 내 코드는 camelCase로 작성되어 있어서 요청할 때도 snake_case로 바꿔서 보내야 하는 것이었다.. 당연한데 저땐 생각 못했당 ㅠ 그래서 찾아보니 snakecase-keys 라이브러리도 있었다!! (앗싸) 🐍 snakecase-keysyarn, npmyarn add ..
snake_case 응답 데이터를 camelCase로 변환하기
·
Library & Runtime/React
여태까지 백엔드는 Spring(Java), 프론트엔드는 React(JavaScript/TypeScript)를 사용해서 둘 다 camelCase를 썼었다.그래서 이런 상황을 겪을 일이 없었는데, 이번에는 백엔드에서 파이썬을 사용하고 있어 이런 문제를 겪었다. 파이썬에서는 snake_case를 주로 사용해서 백엔드에서 응답으로 오는 데이터의 key가 snake_case로 작성되어 있었다.프론트엔드에서는 camelCase로 작성하고 있어서 어떻게 해야 하나 싶었는데 이를 변환해 주는 라이브러리를 찾았다. 🐫 camelcase-keysyarn, npmyarn add camelcase-keys위 패키지를 설치해서 사용하면 된다.우리 프로젝트의 경우, 모든 응답의 데이터 key를 snake_case에서 camel..