성능 · 접근성
화면을 그리는 방식과 속도·접근성 디테일까지. 남들은 그냥 넘어가는 부분을 의도적으로 챙긴 장치 모음.
P1 - DATA & RENDER
- 원칙·공개+SEO → RSC 서버 패칭 / 로그인+상호작용 → react-query
- 쓰기 후·서버액션 revalidatePath 또는 invalidateQueries 로 무효화
- 사용성·좋아요·댓글은 낙관적 업데이트로 즉시 반영 + 실패 시 롤백
화면마다 데이터를 가져오는 방식을 성격에 따라 다르게 골랐어요. 아무나 보는 화면(카드 목록 같은)은 검색에 잘 잡히고 첫 로딩이 빠르도록 서버에서 미리 그리고, 로그인 후 계속 바뀌는 부분(좋아요·댓글)은 클릭 즉시 반응하도록 다른 방식을 씁니다.
아래 그림은 ‘이 데이터는 어느 쪽이냐’를 가르는 갈림길이고, 그 아래는 좋아요·댓글이 눌리자마자 먼저 반영되고 실패하면 되돌리는 방식을 설명합니다.
실선 = 렌더 경로 / 점선 분기 = 데이터 성격. RSC·react-query 는 레거시 관계가 아니라 역할이 달라 공존한다.
P2 - FRONT PERFORMANCE & A11Y
- 집중·풀스크린·스와이프·필터가 겹치는 카드 목록(/cards)
- 측정·라이트하우스 - 시크릿 창(확장 노이즈 제거)에서
- 원칙·숨기되 상호작용 가능 → inert / 순수 장식 → aria-hidden
눈에 잘 안 띄지만 사용성을 좌우하는 성능·접근성 디테일들을, 그냥 넘기지 않고 하나씩 챙긴 목록이에요. 첫 화면 이미지 우선 로딩, 이미지 용량 최적화, 뒤로 가도 스크롤·검색 상태 복원, 저사양에서도 부드러운 애니메이션 같은 것들입니다.
아래 카드들이 각 장치가 무엇을·왜 하는지 하나씩 설명합니다.
above-the-fold 4장stagger 로 처음 등장하는 카드에만 priority 를 줘 fetchpriority=high + preload. 나머지는 lazy. 전부에 주면 화면 밖까지 받아 오히려 LCP 악화.
next/image2레이어 펄스가 같은 src 라 요청은 1장으로 합쳐짐(dedup). sizes 로 폭에 맞는 작은 본을 받고, AVIF→WebP 변환에 quality 90 을 쓰려 qualities 등록(Next 16 필수).
staleTimes검색·필터·정렬·스와이프 위치까지 URL 쿼리로 직렬화(router.replace). staleTimes 로 상세→목록 복귀 시 RSC 를 잠깐 재사용해 서버 재실행 없이 즉시 복원.
transform · opacitytransform/opacity 변화만 GPU 합성(repaint 없음). 해저드 흐름·카드 진입·CTA glint 를 translate 로 짜 저사양에서도 부드럽게. stroke-dashoffset 류 비합성은 별도 표시.
browserslist모던 타깃(Chrome/Edge/FF 111+, Safari 16+)을 지정해 Array.at·flat·Object.fromEntries 등 ~14KiB 폴리필을 번들에서 제외.
next.configpoweredByHeader:false 로 X-Powered-By 차단. CSP frame-ancestors 'none'(클릭재킹), nosniff, Referrer-Policy, Permissions-Policy 공통 적용.
저사양 기기에서도 부드럽게 돌리고 싶었어요. 화면이 버벅이는 건 대개 브라우저가 배치를 다시 계산(reflow)하거나 픽셀을 다시 칠(repaint)하기 때문이라, 그 둘을 건드리지 않는 속성만 골라 썼습니다.