TIL - 20260725

juni·2026년 7월 25일

TIL

목록 보기
414/471

0725 프론트엔드 실무 심화 (8/N): 성능 최적화, 렌더링과 이미지 최적화


✅ 1. 프론트엔드 성능 최적화란 무엇인가?

  • 프론트엔드 성능 최적화는 사용자가 화면을 더 빠르고 부드럽게 사용할 수 있도록 렌더링, 네트워크 요청, 이미지, JavaScript 번들, 상태 업데이트를 개선하는 작업입니다.
  • 단순히 “빠르게 보이게 하는 것”이 아니라, 고객이 이탈하지 않고 관리자도 답답함 없이 업무를 처리하게 만드는 작업입니다.
  • 온라인 휴대폰 판매몰에서는 상품 상세, 배너, 상담 신청 모달, 관리자 테이블, 이미지 로딩 속도가 특히 중요합니다.
사용자 접속
  ↓
HTML/CSS/JS 로드
  ↓
이미지 로드
  ↓
API 데이터 요청
  ↓
React 렌더링
  ↓
사용자 클릭/입력
  ↓
화면 반응

➕ 1-1. 성능이 중요한 이유

  • 고객 화면이 느리면 상담 신청 전 이탈할 수 있습니다.
  • 상품 이미지가 늦게 뜨면 페이지 신뢰도가 떨어집니다.
  • 상담 신청 버튼 반응이 느리면 중복 클릭이 생깁니다.
  • 관리자 테이블이 느리면 운영 업무 속도가 떨어집니다.
  • 성능 문제는 기능 오류가 아니어도 사용자는 “사이트가 불안정하다”고 느낍니다.
느린 상품 상세
  ↓
고객이 혜택 확인 전에 이탈
  ↓
상담 신청 감소

느린 관리자 테이블
  ↓
운영자가 필터/상태 변경을 반복 클릭
  ↓
중복 요청, 업무 실수 증가

✅ 2. 프론트엔드 성능의 주요 지점

  • 프론트엔드 성능은 한 가지 원인으로만 느려지지 않습니다.
  • 화면이 느릴 때는 여러 지점을 나눠서 봐야 합니다.
영역문제 예시
네트워크API 응답 느림, 이미지 용량 큼
JavaScript번들 크기 큼, 불필요한 라이브러리
React 렌더링불필요한 re-render, 무거운 컴포넌트
이미지원본 크기 과다, 포맷 미최적화
CSS/Layoutlayout shift, 무거운 애니메이션
상태 관리전역 상태 변경으로 전체 렌더링
테이블row 과다 렌더링, 컬럼 계산 반복
폼입력할 때마다 무거운 validation

➕ 2-1. 성능 최적화 기본 순서

1. 측정한다
2. 병목을 찾는다
3. 큰 문제부터 고친다
4. 다시 측정한다
5. 과한 최적화는 피한다
  • 성능 최적화는 감으로 하면 안 됩니다.
  • “왠지 느린 것 같다”가 아니라 어디서 느린지 확인해야 합니다.

✅ 3. 측정 없이 최적화하지 않기

  • 성능 최적화에서 가장 흔한 실수는 측정 없이 memo, useMemo, useCallback을 남발하는 것입니다.
  • 실제 병목은 이미지 용량이나 API 응답인데 React 코드만 만지는 경우가 많습니다.

➕ 3-1. 먼저 확인할 것

페이지 첫 로딩 시간
이미지 로딩 시간
API 응답 시간
번들 크기
렌더링 횟수
사용자 클릭 후 반응 시간
테이블 row 수
검색/필터 변경 시 체감 속도

➕ 3-2. 사용할 수 있는 도구

Chrome DevTools Network
Chrome DevTools Performance
React DevTools Profiler
Lighthouse
Web Vitals
TanStack Query Devtools
브라우저 console.time
  • 처음에는 Chrome DevTools Network만 제대로 봐도 많은 문제를 찾을 수 있습니다.
  • 이미지가 몇 MB인지, API가 몇 초 걸리는지부터 확인해야 합니다.

✅ 4. Core Web Vitals 기본

  • 고객 화면에서는 Core Web Vitals 개념을 알아두면 좋습니다.
  • 구글 검색 노출과 사용자 경험 측면에서 참고할 수 있는 성능 지표입니다.
지표의미
LCP주요 콘텐츠가 화면에 보이는 시간
INP사용자 입력에 대한 반응성
CLS화면이 갑자기 밀리는 정도

➕ 4-1. 쉽게 이해하기

LCP:
상품 이미지나 핵심 제목이 빨리 보이는가?

INP:
상담 신청 버튼을 눌렀을 때 바로 반응하는가?

CLS:
이미지나 배너가 늦게 뜨면서 화면이 밀리지 않는가?

➕ 4-2. 휴대폰 판매몰 기준

상품 상세:
대표 이미지, 상품명, 월 예상 요금, 상담 신청 버튼이 빨리 보여야 함

배너:
이미지 크기와 높이를 미리 잡아 layout shift 방지

상담 신청:
버튼 클릭 후 즉시 로딩/모달 반응 제공
  • 고객 화면에서는 “첫 화면에서 핵심 정보가 얼마나 빨리 보이는가”가 중요합니다.
  • 관리자 화면에서는 Web Vitals보다 업무 반응성과 테이블 성능이 더 중요할 수 있습니다.

✅ 5. 네트워크 성능 최적화

  • 네트워크 성능은 API, 이미지, JS, CSS 파일 크기와 요청 수에 영향을 받습니다.
  • 화면이 느릴 때는 Network 탭에서 어떤 요청이 오래 걸리는지 먼저 봐야 합니다.

➕ 5-1. 확인할 항목

이미지 파일 크기
JS 번들 크기
CSS 크기
API 응답 시간
중복 API 호출
실패 요청
캐시 여부
압축 여부

➕ 5-2. 나쁜 예시

상품 상세 진입 시:
5MB 이미지 4장 로딩
사용하지 않는 관리자 JS까지 같이 로딩
같은 상품 API를 3번 호출
배너 이미지 크기 미지정으로 화면 밀림

➕ 5-3. 좋은 방향

이미지는 WebP/적절한 크기로 제공
필요한 JS만 로딩
같은 서버 데이터는 TanStack Query 캐시 활용
첫 화면에 필요한 데이터부터 로딩
아래쪽 섹션은 지연 로딩 고려
  • 가장 효과가 큰 최적화는 보통 이미지와 불필요한 요청 제거입니다.

✅ 6. 이미지 최적화

  • 온라인 휴대폰 판매몰에서는 이미지가 매우 중요합니다.
  • 상품 이미지, 배너, 사전예약 이미지, 리뷰 이미지가 크면 페이지가 느려집니다.

➕ 6-1. 이미지 최적화 기준

원본 그대로 업로드하지 않기
화면 크기에 맞는 이미지 제공
WebP/AVIF 검토
이미지 width/height 지정
Lazy loading 적용
중요 이미지는 우선 로딩
불필요하게 투명 PNG 남발하지 않기

➕ 6-2. 이미지 포맷 기준

포맷특징사용 기준
JPG/JPEG사진에 적합실사 상품 이미지
PNG투명 배경 가능, 용량 큼누끼 이미지, 로고
WebP용량 효율 좋음대부분의 웹 이미지
SVG벡터, 아이콘/로고단순 아이콘, 로고
AVIF압축률 좋음지원 환경 확인 필요

➕ 6-3. 실무 기준

상품 실사:
WebP 또는 최적화된 JPG

누끼 상품 이미지:
필요할 때만 PNG, 가능하면 WebP 투명 지원 검토

아이콘:
SVG

배너:
PC/모바일 비율 별도 제작 고려
  • 무조건 PNG가 고화질이라는 생각은 버려야 합니다.
  • PNG는 투명 배경에는 좋지만, 큰 배너에 쓰면 용량이 커질 수 있습니다.

✅ 7. 이미지 크기 지정과 CLS 방지

  • 이미지가 늦게 로딩되면서 화면이 아래로 밀리면 사용자 경험이 나빠집니다.
  • 이를 Layout Shift라고 볼 수 있습니다.

➕ 7-1. 나쁜 예시

<img src="/banner.png" alt="사전예약 배너" />
  • 이미지가 로드되기 전까지 브라우저가 높이를 예측하기 어렵습니다.
  • 로딩 후 화면이 갑자기 밀릴 수 있습니다.

➕ 7-2. 좋은 예시

<img
  src="/banner.webp"
  alt="사전예약 배너"
  width={1200}
  height={400}
/>

➕ 7-3. CSS 비율 유지

.banner-image {
  width: 100%;
  aspect-ratio: 3 / 1;
  object-fit: cover;
}
  • 이미지 영역의 비율을 미리 잡아두면 화면 밀림이 줄어듭니다.
  • 배너와 상품 이미지는 특히 width/height 또는 aspect-ratio를 챙겨야 합니다.

✅ 8. Lazy Loading

  • Lazy Loading은 화면에 당장 보이지 않는 이미지를 나중에 로딩하는 방식입니다.
  • 상품 상세 아래쪽 리뷰, FAQ 이미지, 상세 스펙 이미지 등에 유용합니다.

➕ 8-1. 기본 예시

<img
  src="/product-detail.webp"
  alt="상품 상세 이미지"
  loading="lazy"
/>

➕ 8-2. Lazy Loading에 적합한 이미지

페이지 아래쪽 상세 이미지
리뷰 이미지
FAQ 이미지
관리자 상세 모달 내부 이미지
아래쪽 배너

➕ 8-3. Lazy Loading을 조심할 이미지

첫 화면 대표 이미지
LCP 대상 이미지
Hero 이미지
상단 핵심 배너
  • 첫 화면 핵심 이미지는 lazy loading하면 오히려 느리게 보일 수 있습니다.
  • 중요한 이미지는 빠르게 로딩하고, 아래쪽 이미지만 지연 로딩하는 것이 좋습니다.

✅ 9. 코드 스플리팅

  • 코드 스플리팅(Code Splitting)은 필요한 JavaScript만 나눠서 로딩하는 방식입니다.
  • 고객 화면에서 관리자 페이지 코드까지 한 번에 로딩하면 비효율적입니다.

➕ 9-1. 필요한 이유

초기 JS 번들 감소
첫 로딩 속도 개선
관리자 기능을 고객 화면에서 로딩하지 않음
무거운 라이브러리 지연 로딩 가능

➕ 9-2. React lazy 예시

const AdminDashboardPage = React.lazy(() =>
  import('./pages/admin/AdminDashboardPage'),
);

➕ 9-3. Suspense 예시

<Suspense fallback={<PageLoading />}>
  <AdminDashboardPage />
</Suspense>
  • 라우트 단위 코드 스플리팅은 효과가 큽니다.
  • 관리자 페이지, 차트 페이지, 엑셀/에디터 기능처럼 무거운 화면은 분리하면 좋습니다.

✅ 10. 무거운 라이브러리 지연 로딩

  • 차트, 에디터, 엑셀, 지도, 이미지 편집 라이브러리는 번들 크기를 크게 만들 수 있습니다.
  • 처음부터 로딩하지 말고 실제 필요할 때 로딩하는 방식을 고려해야 합니다.

➕ 10-1. 지연 로딩 후보

차트 라이브러리
엑셀 관련 라이브러리
리치 텍스트 에디터
이미지 크롭/편집 도구
지도 라이브러리
대형 날짜 선택기

➕ 10-2. 관리자 화면 예시

상담 목록:
일반 테이블 코드만 로딩

엑셀 다운로드 모달 열기:
엑셀 관련 모듈 로딩

통계 대시보드 진입:
차트 라이브러리 로딩
  • 모든 기능을 첫 화면 번들에 넣으면 초기 로딩이 느려집니다.
  • 자주 쓰지 않는 무거운 기능은 나중에 불러오는 것이 좋습니다.

✅ 11. React 렌더링 성능

  • React 성능 문제는 보통 불필요한 re-render에서 시작됩니다.
  • 상태가 바뀔 때 필요한 컴포넌트만 다시 렌더링되어야 합니다.

➕ 11-1. re-render가 많아지는 원인

전역 상태를 너무 넓게 사용
부모 컴포넌트에서 상태를 과하게 많이 가짐
inline object/function을 props로 계속 전달
큰 테이블 row가 모두 다시 렌더링
필터 입력마다 전체 테이블 재계산
context 값 변경으로 하위 전체 렌더링

➕ 11-2. 먼저 할 것

React DevTools Profiler로 확인
어떤 컴포넌트가 자주 렌더링되는지 확인
렌더링 비용이 큰 컴포넌트부터 개선
불필요한 전역 상태 분리
상태 위치를 더 가까운 컴포넌트로 이동
  • memo, useMemo, useCallback은 무조건 쓰는 것이 아닙니다.
  • 실제로 렌더링 비용이 있는 곳에 선택적으로 써야 합니다.

✅ 12. React.memo 사용 기준

  • React.memo는 props가 바뀌지 않으면 컴포넌트 렌더링을 건너뛸 수 있게 도와줍니다.
  • 하지만 props가 매번 새 객체/함수면 효과가 떨어집니다.

➕ 12-1. 적합한 경우

테이블 Row가 많음
상태 Badge가 많이 반복됨
무거운 카드 컴포넌트
props가 자주 바뀌지 않음
렌더링 비용이 실제로 있음

➕ 12-2. 예시

const ConsultTableRow = React.memo(function ConsultTableRow({
  consult,
  onOpenDetail,
}: {
  consult: Consult;
  onOpenDetail: (id: number) => void;
}) {
  return (
    <tr>
      <td>{consult.createdAt}</td>
      <td>{consult.customerName}</td>
      <td>{consult.phone}</td>
      <td>
        <button onClick={() => onOpenDetail(consult.id)}>
          상세
        </button>
      </td>
    </tr>
  );
});

➕ 12-3. 주의할 점

모든 컴포넌트에 memo 붙이지 않기
props가 매번 새로 만들어지면 효과 낮음
비교 비용이 더 클 수 있음
코드 복잡도 증가 고려
  • memo는 만능이 아닙니다.
  • 테이블 row처럼 반복이 많고 렌더링 비용이 있는 곳부터 검토하면 됩니다.

✅ 13. useMemo 사용 기준

  • useMemo는 계산 결과를 메모이제이션합니다.
  • 무거운 계산이나 derived data가 있을 때 유용합니다.

➕ 13-1. 적합한 경우

큰 목록을 필터링/정렬
복잡한 컬럼 정의
차트 데이터 가공
권한 기반 메뉴 계산
상태별 count 계산

➕ 13-2. 예시

const columns = useMemo(
  () => [
    { key: 'createdAt', label: '신청일' },
    { key: 'customerName', label: '고객명' },
    { key: 'phone', label: '전화번호' },
    { key: 'status', label: '상태' },
  ],
  [],
);

➕ 13-3. 권한 메뉴 계산 예시

const visibleMenus = useMemo(
  () =>
    adminMenus.filter((menu) =>
      hasPermission(me?.permissions, menu.requiredPermission),
    ),
  [me?.permissions],
);
  • 간단한 계산에는 굳이 useMemo가 필요 없습니다.
  • 코드가 복잡해지는 비용도 같이 봐야 합니다.

✅ 14. useCallback 사용 기준

  • useCallback은 함수를 메모이제이션합니다.
  • memo된 자식 컴포넌트에 함수를 props로 넘길 때 유용할 수 있습니다.

➕ 14-1. 적합한 경우

React.memo된 자식 컴포넌트에 handler 전달
테이블 row 액션 handler
무거운 child component에 callback 전달
dependency가 안정적인 함수

➕ 14-2. 예시

const handleOpenDetail = useCallback((consultId: number) => {
  setSelectedConsultId(consultId);
  setIsDetailOpen(true);
}, []);
<ConsultTable
  items={consults}
  onOpenDetail={handleOpenDetail}
/>

➕ 14-3. 주의할 점

모든 함수에 useCallback 붙이지 않기
dependency 관리가 복잡해질 수 있음
자식이 memo되지 않았다면 효과가 적을 수 있음
  • useCallback도 성능을 무조건 좋게 만드는 것이 아닙니다.
  • 렌더링 최적화가 필요한 구조에서만 쓰는 것이 좋습니다.

✅ 15. 상태 위치 최적화

  • 성능 문제는 상태가 너무 위에 있어서 생기는 경우가 많습니다.
  • 상태는 필요한 가장 가까운 곳에 두는 것이 좋습니다.

➕ 15-1. 나쁜 예시

AdminPage가 모든 상태를 가짐:
검색 폼 입력값
상세 모달 열림
테이블 row hover
드롭다운 열림
토스트 상태
권한 상태
  • 작은 상태가 바뀔 때 큰 페이지 전체가 다시 렌더링될 수 있습니다.

➕ 15-2. 좋은 방향

검색 조건:
URL 상태

서버 데이터:
TanStack Query

모달 열림:
해당 기능 컴포넌트 근처

드롭다운 열림:
드롭다운 컴포넌트 내부

전역 토스트:
전역 UI store
  • 상태를 가까운 곳에 두면 불필요한 렌더링과 복잡도가 줄어듭니다.

✅ 16. Context 성능 주의

  • Context는 편하지만 값이 바뀌면 해당 Context를 사용하는 하위 컴포넌트들이 다시 렌더링됩니다.
  • 전역 상태처럼 무분별하게 쓰면 성능 문제가 생길 수 있습니다.

➕ 16-1. 주의할 Context

자주 바뀌는 입력값
테이블 hover/selection
대량 데이터 목록
실시간 상태
자주 갱신되는 통계

➕ 16-2. Context에 적합한 것

테마
로그인 사용자 정보
언어 설정
FormProvider
Modal 내부 공유 상태
  • 자주 바뀌는 값은 Context보다 로컬 상태나 전용 상태 관리 도구를 고려하는 것이 좋습니다.
  • Context를 쓸 때는 provider 범위를 너무 크게 잡지 않는 것도 중요합니다.

✅ 17. 관리자 테이블 성능 최적화

  • 관리자 테이블은 프론트 성능 문제가 자주 발생하는 영역입니다.
  • 상담/주문/상품 데이터가 늘어나면 테이블 렌더링과 검색이 느려질 수 있습니다.

➕ 17-1. 기본 원칙

서버 페이지네이션 사용
한 번에 너무 많은 row 렌더링하지 않기
limit 최대값 제한
검색/필터는 서버에서 처리
무거운 컬럼 렌더링 최소화
row action handler 최적화
대량 데이터는 Export로 분리

➕ 17-2. 나쁜 방식

전체 상담 5000건을 한 번에 가져옴
프론트에서 filter/sort
모든 row에 복잡한 모달 상태 포함
각 row마다 API query 실행
전화번호/상태 포맷을 렌더링마다 반복 계산

➕ 17-3. 좋은 방식

page/limit 기반 서버 조회
queryKey에 필터 조건 포함
row는 표시만 담당
상세 데이터는 모달 열 때 조회
상태 라벨/variant는 매핑 객체로 관리
필요 시 row memo 적용
  • 테이블은 “많은 데이터를 한 번에 보여주는 것”보다 “필요한 데이터를 빠르게 찾게 하는 것”이 중요합니다.

✅ 18. 가상 스크롤

  • 가상 스크롤(Virtualization)은 실제 화면에 보이는 row만 렌더링하는 방식입니다.
  • row가 수백~수천 개 이상일 때 성능에 도움이 됩니다.

➕ 18-1. 필요한 경우

한 페이지에 수백 개 이상 row 렌더링
스크롤이 버벅임
row 높이가 비교적 일정함
대량 데이터를 화면에서 빠르게 탐색해야 함

➕ 18-2. 조심할 점

구현 복잡도 증가
접근성 고려 필요
row 높이가 동적이면 어려움
일반 페이지네이션이면 굳이 필요 없을 수 있음
  • 일반 관리자 페이지에서는 먼저 서버 페이지네이션과 limit 제한을 적용하는 것이 우선입니다.
  • 그래도 부족할 때 가상 스크롤을 검토하면 됩니다.

✅ 19. API 요청 최적화

  • 같은 API를 여러 번 호출하거나 불필요한 refetch가 많으면 성능이 떨어집니다.
  • TanStack Query를 잘 쓰면 중복 요청을 줄일 수 있습니다.

➕ 19-1. 중복 요청 원인

같은 데이터를 여러 컴포넌트에서 각각 useEffect로 호출
queryKey가 매번 바뀜
검색 input 입력마다 즉시 API 호출
페이지 진입마다 캐시 없이 새 요청
mutation 후 너무 넓은 invalidate

➕ 19-2. 해결 방향

TanStack Query queryKey 통일
staleTime 조정
검색어 debounce
검색 버튼 제출 방식 사용
필요한 query만 invalidate
상세 데이터는 필요할 때 enabled 조건으로 조회

➕ 19-3. enabled 옵션

const consultDetailQuery = useQuery({
  queryKey: ['admin', 'consult', selectedConsultId],
  queryFn: () => adminConsultApi.getConsultDetail(selectedConsultId!),
  enabled: !!selectedConsultId,
});
  • 상세 모달을 열기 전에는 상세 API를 호출하지 않게 할 수 있습니다.
  • 필요할 때만 요청하는 것이 중요합니다.

✅ 20. 검색 입력 Debounce

  • 검색어 입력마다 API를 호출하면 요청이 너무 많아집니다.
  • 자동 검색을 한다면 debounce가 필요합니다.

➕ 20-1. Debounce 개념

사용자가 입력 중:
API 호출하지 않음

입력이 멈춘 뒤 일정 시간:
API 호출

➕ 20-2. 기준

고객 검색:
300ms ~ 500ms

관리자 검색:
검색 버튼 방식 또는 500ms debounce

무거운 검색:
검색 버튼 방식 권장

➕ 20-3. 관리자 페이지 기준

상담/주문 목록:
검색 버튼 방식 추천

상품 자동완성:
debounce 추천

간단한 필터:
즉시 적용 가능
  • 관리자 목록은 URL 상태와 연결되는 경우가 많으므로 검색 버튼 방식이 더 안정적일 수 있습니다.
  • 자동 검색은 UX는 좋지만 API 요청이 늘어날 수 있습니다.

✅ 21. Prefetch

  • Prefetch는 사용자가 필요로 할 가능성이 높은 데이터를 미리 가져오는 방식입니다.
  • 잘 쓰면 화면 전환이 빨라집니다.

➕ 21-1. 적합한 상황

상품 카드 hover 시 상세 데이터 미리 가져오기
다음 페이지 데이터 미리 가져오기
관리자 상세 모달 열 가능성이 높은 데이터
자주 보는 카테고리 데이터

➕ 21-2. 다음 페이지 prefetch 예시

useEffect(() => {
  if (data?.meta.page < data?.meta.totalPages) {
    queryClient.prefetchQuery({
      queryKey: ['admin', 'consults', { page: page + 1, limit }],
      queryFn: () =>
        adminConsultApi.getConsults({
          page: page + 1,
          limit,
        }),
    });
  }
}, [data, page, limit, queryClient]);

➕ 21-3. 주의할 점

너무 많은 prefetch는 API 낭비
모바일 데이터 사용량 증가 가능
권한 필요한 데이터는 주의
정말 쓸 가능성이 높은 것만
  • Prefetch는 체감 속도를 올릴 수 있지만, 요청이 늘어납니다.
  • 꼭 필요한 곳에만 적용해야 합니다.

✅ 22. 애니메이션 성능

  • 애니메이션은 UI를 부드럽게 만들지만, 잘못 쓰면 성능을 떨어뜨립니다.
  • 특히 모바일에서 무거운 그림자, blur, layout 변경 애니메이션은 버벅임을 만들 수 있습니다.

➕ 22-1. 좋은 애니메이션 대상

transform
opacity

➕ 22-2. 조심할 대상

width
height
top
left
margin
padding
box-shadow 과다
filter blur 과다

➕ 22-3. 기준

짧고 빠르게
사용자 행동을 보조하는 목적
중요 정보 전달 방해 금지
모바일에서 과한 효과 피하기
  • 애니메이션은 “멋”보다 “피드백”이 목적이어야 합니다.
  • 상담 신청 버튼, 모달 열림, 토스트 정도는 적절히 쓰면 좋습니다.

✅ 23. 관리자 페이지와 고객 페이지 최적화 차이

구분고객 페이지관리자 페이지
핵심 목표빠른 첫 화면, 전환율빠른 업무 처리, 안정성
중요 지표LCP, INP, CLSAPI 응답, 테이블 렌더링, 필터 반응
주요 병목이미지, 배너, JS 번들테이블, 필터, 상태 변경, 대량 데이터
최적화이미지/코드 스플리팅/CTA 반응서버 페이지네이션/queryKey/mutation 관리
메시지안심, 간결정확, 다음 행동 안내

➕ 23-1. 고객 페이지 우선순위

대표 이미지 최적화
상품명/혜택/CTA 빠르게 표시
배너 용량 줄이기
상담 신청 모달 빠른 반응
모바일 layout shift 방지

➕ 23-2. 관리자 페이지 우선순위

목록 API 응답 최적화
서버 페이지네이션
검색/필터 URL 상태
queryKey 정리
상태 변경 후 필요한 query만 갱신
테이블 row 렌더링 최적화
  • 고객 화면과 관리자 화면은 최적화 기준이 다릅니다.
  • 같은 방식으로 접근하면 중요한 문제를 놓칠 수 있습니다.

✅ 24. 성능 최적화에서 자주 하는 실수

➕ 24-1. memo부터 붙이는 실수

문제:
측정 없이 React.memo/useMemo/useCallback 남발

결과:
코드는 복잡해졌는데 체감 속도 개선 없음
실제 문제는 이미지나 API였음

➕ 24-2. 이미지 원본 그대로 쓰는 실수

문제:
PC용 대형 배너를 모바일에도 그대로 사용

결과:
모바일 로딩 느림
데이터 사용량 증가
전환율 저하

➕ 24-3. 서버 데이터를 전부 가져오는 실수

문제:
관리자 상담 5000건을 한 번에 받아서 프론트에서 필터링

결과:
API 느림
브라우저 렌더링 느림
메모리 사용 증가

➕ 24-4. queryKey 조건 누락

문제:
필터 조건은 바뀌는데 queryKey는 같음

결과:
잘못된 캐시 표시
화면 갱신 안 됨

✅ 25. 실무 체크리스트

➕ 25-1. 고객 화면 성능 체크리스트

  1. 첫 화면 대표 이미지 용량이 과하지 않은가?
  2. 상품명, 핵심 혜택, CTA가 빠르게 보이는가?
  3. 이미지 width/height 또는 aspect-ratio가 지정되어 있는가?
  4. 아래쪽 이미지는 lazy loading이 적용되어 있는가?
  5. 모바일 배너가 너무 큰 이미지를 쓰지 않는가?
  6. 상담 신청 모달이 빠르게 열리는가?
  7. 버튼 클릭 후 즉시 피드백이 있는가?
  8. 불필요한 관리자 코드가 고객 화면 번들에 포함되지 않는가?

➕ 25-2. 관리자 화면 성능 체크리스트

  1. 목록은 서버 페이지네이션을 사용하는가?
  2. limit 최대값이 제한되어 있는가?
  3. queryKey에 모든 검색 조건이 포함되어 있는가?
  4. 상태 변경 후 필요한 query만 invalidate하는가?
  5. 상세 데이터는 필요할 때만 조회하는가?
  6. 테이블 row가 과하게 무겁지 않은가?
  7. 검색 입력마다 불필요하게 API를 호출하지 않는가?
  8. 대량 데이터는 ExportJob으로 분리되어 있는가?

➕ 25-3. 이미지 체크리스트

  1. WebP 또는 최적화된 이미지 포맷을 사용하는가?
  2. PC/모바일 이미지 비율을 따로 고려했는가?
  3. 투명 PNG를 과하게 사용하지 않는가?
  4. 이미지 alt가 적절한가?
  5. LCP 이미지에 lazy loading을 걸지 않았는가?
  6. 아래쪽 이미지는 lazy loading을 적용했는가?
  7. 배너 이미지 텍스트가 모바일에서도 읽히는가?
  8. S3/CloudFront 캐시 정책을 고려했는가?

➕ 25-4. React 렌더링 체크리스트

  1. React DevTools Profiler로 병목을 확인했는가?
  2. 상태가 필요한 위치보다 너무 위에 있지 않은가?
  3. 전역 상태 변경으로 큰 화면이 전부 렌더링되지 않는가?
  4. 테이블 row memo가 필요한 수준인지 확인했는가?
  5. 무거운 계산은 useMemo를 검토했는가?
  6. handler props 때문에 memo가 깨지는지 확인했는가?
  7. Context 값이 너무 자주 바뀌지 않는가?
  8. 최적화로 코드가 과하게 복잡해지지 않았는가?

✅ 26. AI를 활용해 프론트엔드 성능을 점검할 때 질문법

  • AI에게 성능 점검을 요청할 때는 화면 종류, 현재 문제 증상, API 구조, 이미지 사용 방식, 상태 관리 방식, 테이블 규모를 함께 알려줘야 합니다.
  • “사이트가 느려”라고만 하면 일반론만 나옵니다.

➕ 26-1. 좋은 질문 예시

React + TanStack Query 기반 온라인 휴대폰 판매몰 프론트엔드 성능을 점검하고 싶어.

상황:
1. 고객 화면에는 상품 목록, 상품 상세, 상담 신청 모달이 있음
2. 상품 상세에는 대표 이미지, 배너, 혜택 안내, 리뷰, FAQ가 있음
3. 관리자 화면에는 상담 목록 테이블, 검색/필터, 상태 변경, 엑셀 다운로드가 있음
4. 상담 목록은 page, limit, keyword, status, source 조건으로 API 조회함
5. 서버 데이터는 TanStack Query로 관리함
6. 일부 배너 이미지는 PNG이고 용량이 큰 편임
7. 모바일에서 상품 상세 첫 로딩이 느리게 느껴짐
8. 관리자 테이블은 필터 변경 시 약간 버벅임

요청:
- 고객 화면과 관리자 화면을 나눠 성능 병목 후보 정리
- Chrome DevTools에서 확인할 항목
- 이미지 최적화 기준
- queryKey/staleTime/invalidate 점검 기준
- 테이블 렌더링 최적화 기준
- React.memo/useMemo/useCallback 사용 기준
- 우선순위 높은 개선 순서
- 과한 최적화를 피하는 기준
을 실무 기준으로 정리해줘.

➕ 26-2. AI 답변 검증 기준

  1. 측정 없이 memo부터 붙이라고 하지 않는가?
  2. 이미지 용량과 포맷을 우선 점검하는가?
  3. 고객 화면과 관리자 화면의 최적화 기준을 구분하는가?
  4. TanStack Query의 queryKey, staleTime, invalidate를 점검하는가?
  5. 서버 페이지네이션과 limit 제한을 언급하는가?
  6. lazy loading을 첫 화면 이미지에 무조건 적용하라고 하지 않는가?
  7. 실제 병목 확인 도구를 제안하는가?
  8. 현재 서비스 규모에 맞는 개선 순서를 제안하는가?

📌 요약

  • 프론트엔드 성능 최적화는 렌더링, 네트워크 요청, 이미지, JavaScript 번들, 상태 업데이트를 개선해 사용자가 더 빠르고 부드럽게 서비스를 쓰게 만드는 작업입니다.
  • 성능 최적화는 감으로 하지 말고 Chrome DevTools, Lighthouse, React Profiler, Network 탭으로 먼저 측정해야 합니다.
  • 고객 화면에서는 상품 이미지, 배너, 첫 화면 핵심 정보, 상담 신청 버튼 반응성이 중요합니다.
  • 관리자 화면에서는 목록 API 응답, 서버 페이지네이션, 검색/필터 반응, 테이블 row 렌더링, 상태 변경 후 query 갱신이 중요합니다.
  • 이미지 최적화는 체감 성능에 가장 큰 영향을 주는 경우가 많으며, WebP, 적절한 크기, width/height 지정, lazy loading을 상황에 맞게 적용해야 합니다.
  • 첫 화면 대표 이미지나 LCP 대상 이미지에는 무조건 lazy loading을 적용하면 오히려 느리게 보일 수 있습니다.
  • 코드 스플리팅을 통해 고객 화면에서 관리자 페이지 코드나 무거운 차트/엑셀 라이브러리를 불필요하게 로딩하지 않게 해야 합니다.
  • React.memo, useMemo, useCallback은 실제 렌더링 병목이 확인된 곳에 선택적으로 사용해야 하며, 무조건 붙이면 코드만 복잡해질 수 있습니다.
  • 관리자 테이블은 서버 페이지네이션, queryKey 정리, 필요한 데이터만 조회, 상세 데이터 지연 조회가 기본입니다.
  • 성능 최적화의 핵심은 “측정 → 병목 확인 → 큰 문제부터 개선 → 다시 측정”입니다.

0개의 댓글