Community코딩 & 개발github.com

to110i/지각된성능

웹 UI가 실제보다 더 빠르게 느껴지도록 만듭니다. — 스켈레톤 스크린, 낙관적 UI, 로딩 상태, 탐색 피드백.

지각된성능란 무엇인가요?

이 스킬은 사용자에게 UI가 실제보다 더 빠르게 느껴지도록 하는 '지각된 성능(Perceived Performance)' 개념에 중점을 둡니다. 실제 로딩 시간을 단축하는 것뿐만 아니라 사용자가 기다리는 동안 즉각적인 피드백을 제공하여 애플리케이션의 반응성을 향상시키는 것이 목표입니다. 주요 기술로는 스켈레톤 스크린, 낙관적 업데이트(Optimistic UI), Suspense 스트리밍, 동적 임포트(Dynamic Import), SWR(Stale-While-Revalidate) 캐싱, 가상 스크롤링 등이 포함됩니다. 이 스킬은 Next.js와 같은 최신 React 프레임워크에서 특히 효과적이며, 코드 분석을 통해 사용자 경험을 저해하는 패턴(예: 순차적인 await 체인, 과도한 데이터 페칭)을 식별하고 해결책을 제시합니다. 분석 워크플로우는 사용자가 처음 보는 화면부터 시작하여 데이터의 긴급도를 분류하고, 점진적 렌더링을 적용하며, 최종적으로 지각된 성능을 검증하는 5단계로 구성됩니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add to110i/perceived-performance

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

프로그레시브 웹 UI

지각된 성능(Perceived performance)은 UI가 실제로 빠른 것뿐만 아니라 느껴지게 빠르게 만드는 것입니다. 2초에 로딩되지만 스켈레톤을 즉시 보여주는 페이지는 1.5초에 로딩되지만 내내 빈 화면을 보여주는 페이지보다 더 빠르게 느껴집니다.

사용자가 코드를 공유하면:

  1. 사용자가 로딩 및 대기 상태에서 현재 무엇을 보고 있는지 이해하기 위해 코드를 읽습니다.
  2. 아래 의사 결정 가이드를 사용하여 적용 가능한 기술(들)을 식별합니다.
  3. 무엇을 변경해야 하는지, 왜 그것이 지각된 속도를 향상시키는지, 그리고 어떻게 구체적인 코드로 구현하는지 설명합니다.

핵심 원칙

1. "첫 번째 뷰"와 나머지를 분리하십시오

항상 다음을 구분하십시오:

  • 첫 번째 페인트(First Paint)에 필요한 것
  • 셸(Shell)이 표시된 후에 로드할 수 있는 것
  • 사용자 상호작용까지 기다릴 수 있는 것

모든 데이터가 동일하게 긴급하다고 취급하지 마십시오.

2. 데이터보다 구조를 먼저 제공하십시오

페이지 셸(레이아웃, 탐색 슬롯, 헤더 프레임)은 데이터 가져오기가 완료되기 전에 브라우저로 전송되어야 합니다. 사용자는 처음 100-200ms 내에 속도 인상을 형성합니다. 구조를 즉시 표시하면 실제 로드 시간이 동일하더라도 지각된 대기 시간을 줄일 수 있습니다.

3. 클릭을 무시당한 채로 두지 마십시오

모든 상호작용(클릭, 탭, 탐색)은 첫 번째 프레임에서 눈에 보이는 응답을 생성해야 합니다. 실제 작업에 시간이 걸리는 경우 즉시 중간 상태를 표시하십시오.

4. 로딩 UI만 고치지 말고 구조를 고치십시오

loading.tsx와 스켈레톤은 외관을 개선하지만 과도한 데이터 가져오기나 순차적 데이터 종속성 문제를 해결하지는 않습니다. 항상 근본 원인을 해결하십시오:

  • 순차적인 await 체인 → Promise.all로 병렬화
  • 단일 대용량 가져오기 → 첫 번째 뷰와 지연된 것으로 분할
  • 탐색에서 전체 프로필 가져오기 → 경량 탐색 아이덴티티 헬퍼 사용

5. 탐색도 빠르게 느껴져야 합니다

지각된 속도는 초기 로딩에만 해당되지 않습니다. 페이지 전환, 재방문, 상호작용도 동등하게 빠르게 느껴져야 합니다:

  • 사용자가 클릭하기 전에 경로를 프리페치(Prefetch)하십시오.
  • 탐색 시작 시 즉시 loading.tsx를 표시하십시오.
  • SWR/캐시를 사용하여 즉시 재방문하십시오.

의사 결정 가이드

증상기술
데이터 로딩 중 빈 화면스켈레톤 스크린 / Suspense 스트리밍
버튼 클릭에 즉각적인 응답 없음낙관적 UI / 즉각적인 피드백
페이지 전환이 클릭 후 시각적으로 시작되지 않음loading.tsx + 프리페치
무거운 컴포넌트가 초기 렌더링 속도 저하동적 임포트
동일한 데이터에 방문할 때마다 스피너 표시SWR stale-while-revalidate
하나의 느린 API가 전체 페이지를 차단Suspense 스트리밍(병렬 비동기 서버 컴포넌트)
인증/프로필 가져오기가 탐색 또는 페이지 셸 지연인증 레이아웃 분리(references/auth-performance.md 참조)
이미지로 인한 레이아웃 이동 또는 느린 느낌next/image + priority / blur 플레이스홀더
글꼴 스왑으로 인한 스타일 없는 텍스트 깜빡임next/font
양식 제출에 시각적 피드백 없음useFormStatus / useActionState
긴 목록으로 인한 스크롤 버벅임 또는 느린 렌더링가상 스크롤링(TanStack Virtual / react-window)
긴급하지 않은 상태 업데이트가 사용자 입력 차단지연 렌더링을 위한 startTransition

분석 워크플로우

1단계: 사용자가 먼저 보는 것을 식별하십시오

0-200ms 내에 무엇이 렌더링됩니까? 빈 화면이나 스피너라면 스타일링 수정 전에 구조적 변경이 필요합니다.

2단계: 데이터를 긴급도별로 분류하십시오

  1. 첫 번째 뷰 — 페이지가 의미를 가지기 위해 반드시 있어야 함
  2. 지연됨 — 셸이 표시된 후 스트리밍 가능
  3. 요청 시 — 사용자 상호작용 후에만 로드

3단계: 데이터 종속성을 수정하십시오

  • 순차적인 await → Promise.all 또는 별도의 비동기 서버 컴포넌트
  • 초기 로드 시 과도한 데이터 가져오기 → API 분할 또는 페이지네이션
  • 탐색에서 전체 프로필 → 별도의 탐색 아이덴티티 헬퍼

4단계: 점진적 렌더링을 적용하십시오

필요한 것에 따라 선택하십시오:

  • loading.tsx — 즉각적인 탐색 스켈레톤 (전체 페이지)
  • <Suspense> — 세분화된 스트리밍 (섹션별)
  • useOptimistic — 즉각적인 돌연변이 피드백
  • dynamic() — 무거운 컴포넌트 번들 지연
  • SWR — 캐시에서 즉시 재방문

5단계: 지각된 성능을 검증하십시오

  • 의미 있는 내용이 즉시 나타납니까 (< 200ms)?
  • 모든 로딩 상태에서 사용자에게 정보가 제공됩니까?
  • 전체 데이터가 도착하기 전에 UI가 반응적입니까?
  • 상호작용이 첫 번째 프레임에서 피드백을 생성합니까?

출력 형식

이 스킬을 적용할 때는 다음 구조로 응답하십시오:

## 현재 상황
- [사용자가 현재 경험하는 것을 설명]

## 근본 원인
- [코드에서 느린 느낌을 유발하는 것]

## 변경 사항 및 이유
- [변경 1]: [이것이 지각된 속도를 향상시키는 이유]
- [변경 2]: ...

## 구현

[코드]

## 참고 사항
- [주의 사항, 예외 사항 또는 후속 개선 사항]

참고 자료

전체 코드 예제가 포함된 구현 세부 사항은 다음을 참조하십시오:

  • references/nextjs-patterns.md — 스켈레톤 스크린, 낙관적 UI, Suspense 스트리밍, 프리페치, 동적 임포트, SWR, 이미지, 글꼴, 상호작용 피드백, useFormStatus, 가상 스크롤링, startTransition
  • references/auth-performance.md — 인증 레이아웃 분리, 탐색 아이덴티티 헬퍼, 요청/프로세스 워밍업, 폴백 상태 설계

특정 기술을 구현할 때는 관련 참조 문서를 읽으십시오.


수정해야 할 안티 패턴

항상 다음을 감지하고 해결하십시오:

  • 최상위 레이아웃에서 전체 프로필/인증을 await하는 경우 → 모든 페이지 지연
  • 독립적인 데이터에 대한 순차적인 await 체인 → 불필요한 직렬화
  • 기본적인 과도한 데이터 가져오기를 수정하지 않고 loading.tsx만 추가
  • 초기 로드 시 전체 데이터셋 렌더링 → 페이지네이션 또는 가상화
  • 작업이 완료될 때까지 클릭 시 시각적 피드백 없음 → 즉시 인지
  • 탐색과 페이지에서 서로 다른 인증 소스 사용 → 정식 사용자 이름 불일치
  • 서버가 응답한 후에만 양식 제출 상태 관리 → useFormStatus를 사용하여 즉시 대기 상태 표시
  • 마운트 시 긴 목록의 모든 항목 렌더링 → 가상화(보이는 행만 렌더링)
  • 값비싼 상태 업데이트(필터/정렬/검색)가 사용자 입력 차단 → startTransition으로 감싸기

관련 스킬