Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save leedc0101/8f6eec71b53c137ca7f123e07e7b4e77 to your computer and use it in GitHub Desktop.

Select an option

Save leedc0101/8f6eec71b53c137ca7f123e07e7b4e77 to your computer and use it in GitHub Desktop.
frontend-briefing-2026-04-17-KST

Router cache and request memoization

핵심 요약

이 글은 Next.js App Router 캐싱을 이해할 때 가장 헷갈리는 두 층인 router cacherequest memoization을 분리해서 설명한다. 핵심은 둘 다 "같은 데이터를 다시 요청하지 않게 해준다"는 공통점이 있지만, 수명과 적용 범위가 완전히 다르다는 점이다.

1) Router cache는 브라우저 메모리에 있는 클라이언트 캐시다

  • 이미 방문한 route segment를 브라우저 메모리에 저장해서 뒤로 가기, 앞으로 가기, 링크 이동을 거의 즉시 처리하려는 목적이다.
  • layout과 loading state는 적극적으로 재사용되고, page는 기본적으로 완전 캐시라기보다 history navigation에서 재사용되는 쪽에 가깝다.
  • 새로고침하면 사라진다. 즉, 세션 메모리 성격이 강하다.
  • prefetch 방식과 정적/동적 여부에 따라 보존 시간이 달라진다. 기본 prefetch는 동적 페이지에서 짧고, prefetch={true}router.prefetch()를 쓰면 정적/동적 모두 더 오래 유지된다.

2) invalidation은 서버 액션과 client refresh가 주도한다

  • revalidatePath, revalidateTag, cookies.set/delete 같은 서버 측 조작은 router cache를 무효화할 수 있다.
  • 클라이언트에서는 router.refresh()로 현재 라우트 캐시를 날리고 새 서버 응답을 강제로 받는다.
  • 실무 포인트는 "mutation 이후 화면이 왜 안 바뀌지?" 문제가 생기면 data cache만 볼 게 아니라 router cache도 같이 봐야 한다는 점이다.

3) Request memoization은 한 번의 서버 렌더 사이클 안에서만 살아있는 중복 제거다

  • 같은 render pass 안에서 동일한 fetch(url, options)가 여러 번 호출되어도 실제 네트워크 요청은 1번만 보내고 결과를 재사용한다.
  • 서버 컴포넌트에서만 동작한다. route handler에서는 동작하지 않는다.
  • GET 요청에만 적용된다.
  • 수명은 한 요청이 끝날 때까지다. 다음 요청으로 넘어가면 memoization은 비워진다.

4) data cache와의 차이

  • request memoization은 "한 요청 안에서 중복 fetch 제거"다.
  • data cache는 요청 사이를 넘어 유지되는 더 긴 캐시다.
  • Next는 같은 fetch를 만나면 먼저 memoization을 보고, 없으면 data cache를 본다. 그래서 같은 요청 안에서는 fetch를 여러 번 써도 생각보다 부담이 적다.

5) 글의 실험에서 드러난 흥미로운 점

작성자는 cache 옵션과 next.revalidate 값을 다르게 준 동일 URL fetch를 여러 번 호출했는데도, 실제 API hit는 1번만 발생하는 상황을 확인했다. 즉, 이론적으로는 옵션 차이가 중요하지만, 실제 구현에서는 React/Next의 dedupe가 더 공격적으로 작동하는 구간이 있다. 실무에서는 "같은 요청을 여러 컴포넌트에서 불러도 괜찮다"는 자신감을 주는 대신, 캐시 파일이 왜 저렇게 생겼는지는 기대보다 덜 직관적일 수 있다는 뜻이다.

실무 메모

  • App Router에서 캐시 버그를 볼 때는 client cache / request memoization / data cache를 각각 따로 생각해야 한다.
  • 서버 컴포넌트에서 동일 fetch를 반복하는 패턴은 지나치게 겁낼 필요가 없다.
  • mutation 이후 stale UI가 보이면 revalidatePathrouter.refresh() 역할 분담을 먼저 점검하는 게 빠르다.

Next.js 15 Server Actions vs Route Handlers: When to Use Each (I Got This Wrong for 3 Months)

핵심 요약

이 글의 가장 강한 메시지는 한 줄로 정리된다. "사람이 UI에서 직접 트리거하면 Server Action, 기계가 HTTP로 호출하면 Route Handler". 작성자는 App Router 초기에 모든 mutation을 API처럼 Route Handler로 만들다가, 뒤늦게 Server Action으로 옮기면서 코드량과 캐시 갱신 복잡도가 크게 줄었다고 말한다.

1) Server Action이 잘 맞는 경우

  • 폼 제출, 버튼 클릭처럼 React 트리 안에서 발생하는 사용자 행동
  • mutation 직후 revalidatePath, revalidateTag로 화면 데이터를 바로 갱신해야 하는 경우
  • fetch('/api/...')를 클라이언트에서 한 번 더 감싸는 보일러플레이트를 줄이고 싶은 경우
  • progressive enhancement가 중요한 폼 UX

예시로 요금제 변경 폼을 들며, Server Action은 인증 확인, DB update, cache busting을 한 함수에서 끝낼 수 있다고 설명한다. 이게 큰 장점이다.

2) Route Handler가 맞는 경우

  • Stripe/GitHub/webhook 같이 외부 서비스가 호출하는 엔드포인트
  • 모바일 앱, 제3자 통합, 사내 스크립트 등 React 바깥 소비자가 부르는 API
  • 상태 코드 200/400/401/500을 명시적으로 제어해야 하는 경우
  • SSE, API key 인증, 공개 REST API처럼 HTTP 계약 자체가 중요한 경우

즉, Route Handler는 UI 편의보다 "외부 인터페이스" 성격이 강하다.

3) 자주 실수하는 지점

  • Server Action은 POST 기반 mutation용이다. GET 성격의 query endpoint로 쓰는 게 아니다.
  • 자체 UI 데이터를 읽는 일은 Server Component에서 직접 fetch/DB 호출하는 게 더 자연스럽다.
  • Server Action 에러는 error boundary나 useActionState 흐름으로 다뤄야 하고, Route Handler는 응답 객체 중심으로 에러 계약을 설계해야 한다.

4) 스트리밍도 둘의 모델이 다르다

  • React Suspense와 함께 자연스럽게 이어지는 서버 렌더 스트리밍은 Server Component/Server Action 쪽 모델이 잘 맞는다.
  • 비 React 소비자나 SSE는 Route Handler가 더 적합하다.

5) 테스트 관점 차이

  • Route Handler는 Request -> Response 함수라 단위 테스트가 쉽다.
  • Server Action은 Next 내부 API에 엮이기 쉬워서, 실제 비즈니스 로직을 별도 함수로 분리하고 액션은 얇게 유지하는 게 좋다.

실무 메모

  • App Router에서 내부 폼 처리까지 /api/*로 빼는 습관은 다시 볼 필요가 있다.
  • UI mutation은 Server Action으로 당기고, 외부 계약은 Route Handler로 남기면 구조가 훨씬 선명해진다.
  • 코드 스타일 논쟁이 아니라 캐시 무효화, 테스트성, progressive enhancement까지 묶인 설계 선택이라는 점이 중요하다.

SWR vs TanStack Query 2026: Which React Data Fetching Library Should You Choose?

핵심 요약

작성자는 SWR과 TanStack Query를 둘 다 실무에 써본 경험을 바탕으로, 둘 다 훌륭하지만 프로젝트 복잡도에 따라 선택 기준이 명확하다고 정리한다. 결론은 이렇다. 단순하고 가벼운 Next.js/CRUD면 SWR, mutation과 캐시 정책이 복잡해지면 TanStack Query.

1) SWR의 강점

  • 번들 크기가 작다. 글에서는 gzip 기준 4.2KB로 소개한다.
  • stale-while-revalidate 모델이 단순해서 배우기 쉽다.
  • Vercel이 만든 도구라 Next.js와 잘 맞는다.
  • 간단한 읽기 중심 CRUD, 빠른 프로토타입, 경량 앱에서 생산성이 높다.

2) TanStack Query의 강점

  • mutation 전용 API(useMutation)가 훨씬 성숙했다.
  • DevTools가 강력해서 실무 디버깅 효율이 높다.
  • v5 기준 TypeScript 추론과 Suspense 지원이 좋아졌다.
  • staleTime, gcTime, invalidate 전략 등 캐시 제어가 세밀하다.
  • 대규모 앱이나 다수의 API endpoint를 다룰 때 유리하다.

3) 성능 비교에서 중요한 포인트

  • SWR이 훨씬 작지만, 실제 현장에서는 이미지 1장 최적화가 라이브러리 9KB 차이보다 더 큰 영향을 주는 경우가 많다.
  • TanStack Query v5는 필드 단위 추적을 통해 필요한 부분만 리렌더링하는 최적화가 강점이다.
  • 요청 deduplication은 둘 다 잘 한다.

4) mutation 경험 차이

글은 이 지점을 사실상 승부처로 본다.

  • SWR은 쓰기 요청도 가능하지만, mutate()와 수동 fetch 조합이 많아져 관리가 늘어난다.
  • TanStack Query는 pending/error/success/invalidation 패턴이 구조적으로 내장돼 있어서 복잡한 화면일수록 이점이 커진다.

5) 선택 기준

  • SWR 추천: Next.js 마케팅 사이트, 블로그, 간단한 대시보드, 빠른 MVP, read-heavy 앱
  • TanStack Query 추천: 무거운 admin, enterprise 앱, infinite query, pagination, optimistic update, 복잡한 동기화가 필요한 제품

실무 메모

  • "요즘 뭐가 더 핫하냐"보다 팀이 감당해야 할 mutation 복잡도를 먼저 보는 게 맞다.
  • App Router에서 서버 fetch를 많이 쓰더라도, 클라이언트 상태와 서버 상태가 복잡하게 얽히는 화면은 여전히 Query 계열 도구가 필요하다.
  • 디버깅 비용까지 포함하면 TanStack Query DevTools 가치는 꽤 크다.

5 Next.js Performance Patterns That Cut Our Load Time by 60%

핵심 요약

Quran.com 규모의 서비스에서 실제로 적용한 성능 최적화 5가지를 소개한다. 글이 좋은 이유는 추상론이 아니라, "어떤 병목을 어떤 패턴으로 줄였고 수치가 어떻게 바뀌었는지"가 명확하다는 점이다.

1) 폰트 서브셋팅

  • 전체 아랍어 폰트 600KB를 페이지에 필요한 유니코드 범위만 남긴 woff2로 줄였다.
  • 결과는 600KB → 48KB.
  • 모바일 첫 렌더가 크게 빨라졌고, 느린 네트워크 지역에서 효과가 컸다.
  • 폰트는 감으로 두지 말고 unicode-range와 subset 툴체인을 적극 쓰라는 메시지다.

2) ISR과 on-demand revalidation

  • 모든 페이지를 매번 다시 빌드하면 배포 시간이 너무 길어진다.
  • revalidatefallback: 'blocking'을 섞어, 정적 생성과 점진 재생성을 조합했다.
  • 변경 이벤트가 올 때만 on-demand revalidation을 호출해 CDN 캐시를 갱신했다.
  • 결과적으로 글로벌 응답 속도가 100ms 이하 수준으로 안정됐다.

3) 무거운 컴포넌트는 dynamic import

  • 오디오 플레이어처럼 많은 유저가 실제로는 쓰지 않는 기능을 초기 번들에서 빼냈다.
  • next/dynamic으로 필요할 때만 로드하니, 사용하지 않는 68% 유저는 다운로드 자체를 안 하게 됐다.
  • "모든 사람에게 한 번에 보내는 JS"를 줄이는 전형적인 승리 패턴이다.

4) 업로드 이미지 파이프라인 정리

  • 3~5MB 원본 JPEG를 썸네일 크기로 줄이지 않고 바로 쓰던 문제를, 서버 측 resize + webp/png 생성으로 해결했다.
  • 결과는 45~80KB 수준까지 감소.
  • FE 최적화가 꼭 브라우저 내부에서만 일어나는 게 아니라, 업로드/저장 단계 설계와 직결된다는 점을 잘 보여준다.

5) 의도적인 prefetch

  • 다음 화면으로 갈 가능성이 높은 링크에 hover/touch 시점 prefetch를 걸었다.
  • 사용자 체감상 즉시 이동처럼 느끼게 만들 수 있었다.
  • 무조건 prefetch가 아니라 "예측 가능한 다음 행동"에만 쓰는 게 포인트다.

6) 실제 결과

글이 제시한 before/after는 꽤 인상적이다.

  • FCP 3.2s → 1.8s
  • LCP 4.8s → 1.9s
  • TTI 6.2s → 2.4s
  • 페이지 크기 2.8MB → 1.1MB
  • Lighthouse 42 → 86

실무 메모

  • 성능은 자잘한 팁 몇 개보다, 폰트/이미지/렌더링/전달 전략 같은 구조적 선택의 누적 효과가 더 크다.
  • 특히 한글 서비스도 웹폰트와 이미지 파이프라인만 바로잡아도 큰 폭의 개선이 나는 경우가 많다.

CSS in 2026: The new features reshaping frontend development

  • 원문 제목: CSS in 2026: The new features reshaping frontend development
  • 원문 링크: https://blog.logrocket.com/css-in-2026/
  • 정리일: 2026-04-17 KST
  • 정리 방식: 원문 저작권을 존중해 전문 번역 대신 한국어 상세 요약 제공

핵심 요약

이 글은 "인터랙션은 JS, 스타일은 CSS"라는 오래된 분업이 무너지고 있다는 점을 강조한다. 요즘 CSS는 단순 장식이 아니라, 예전엔 JS로만 만들던 UI 동작을 꽤 많이 흡수하고 있다. 특히 실무자가 바로 체감할 포인트는 customizable select, tree-counting 함수, typed attr() 같은 기능이다.

1) customizable select가 의미하는 변화

  • appearance: base-selectselect::picker(select)를 쓰면 native <select>를 유지한 채 훨씬 자유롭게 꾸밀 수 있다.
  • 접근성, 키보드 내비게이션, focus 관리, overflow 처리, anchor positioning fallback 같은 귀찮은 부분을 브라우저가 맡는다.
  • 예전처럼 접근성 깨진 커스텀 드롭다운을 JS로 다시 만드는 비용이 줄어든다.

2) sibling-index()로 nth-child 하드코딩을 줄인다

  • 형제 순번을 함수로 읽어 transition delay 같은 값을 동적으로 계산할 수 있다.
  • 목록 길이가 바뀌어도 CSS가 스스로 순서를 계산해 애니메이션을 맞춘다.
  • 결국 "마크업에 인덱스 심기"나 긴 :nth-child() 열거를 줄여준다.

3) typed attr()는 data-driven styling의 범위를 넓힌다

  • 과거 attr()는 사실상 content용이었다.
  • 이제 타입을 지정하면 색상 같은 값도 attribute에서 직접 읽어 쓸 수 있다.
  • 예시에서는 option마다 data-bg-color를 두고 CSS에서 바로 읽어 hover/background를 제어한다.

4) 핵심 메시지

작성자는 새 CSS 기능으로 150줄 넘는 JS 커스텀 드롭다운을 훨씬 적은 코드로 대체할 수 있었다고 말한다. 중요한 건 단순 코드량 감소가 아니라, 브라우저 기본 동작을 그대로 살리면서도 인터랙션 수준을 높일 수 있다는 점이다.

5) 다만 아직은 실험적이다

  • 브라우저 지원이 완전히 안정된 상태는 아니다.
  • 그래서 production 즉시 도입보다는 progressive enhancement 전략이 맞다.
  • 내부 도구, 실험 UI, 한정된 브라우저 타깃부터 검증하는 접근이 안전하다.

실무 메모

  • 앞으로 드롭다운, 캐러셀, 툴팁 같은 컴포넌트는 "라이브러리부터 찾기" 전에 최신 CSS로 가능한지 먼저 확인하는 습관이 점점 중요해질 것 같다.
  • 특히 AI가 코드를 많이 짜는 시대일수록, declarative하고 native한 플랫폼 기능을 쓰는 쪽이 과한 JS를 줄이는 데 유리하다.

Announcing TypeScript 6.0

핵심 요약

TypeScript 6.0은 기능 추가만 있는 릴리스라기보다, TS 7의 네이티브(Go 기반) 컴파일러 시대로 넘어가기 위한 브리지 버전이라는 성격이 강하다. 그래서 새 기능도 있지만, 앞으로의 마이그레이션 노이즈를 줄이는 준비 작업이 더 중요하다.

1) TS 7 전환을 염두에 둔 릴리스

  • 현행 JS 코드베이스 기반 TypeScript의 마지막 큰 릴리스가 될 가능성이 크다고 밝힌다.
  • TS 7은 Go 기반 구현으로 더 빠른 컴파일과 병렬 처리 방향을 노린다.
  • 지금 TS 6에 올라타는 건, 나중에 TS 7로 갈 때 충격을 줄이는 사전 정비에 가깝다.

2) --stableTypeOrdering가 실무적으로 중요하다

  • 병렬 타입 검사 환경에서는 타입/심볼 방문 순서가 달라져 출력 순서가 흔들릴 수 있다.
  • TS 6의 --stableTypeOrdering는 TS 7과 비슷한 순서 체계를 미리 맞춰서, declaration diff나 타입 표시 노이즈를 줄여준다.
  • 단, 최대 25%까지 느려질 수 있어 상시 사용보다 migration 점검용에 가깝다.

3) 추론 동작 일부가 더 엄격해졌다

  • generic call이나 generic JSX 안의 함수 표현식 타입 체크가 바뀌며, 예전보다 버그를 더 잘 잡을 수 있다.
  • 반대로 기존 코드가 깨질 수도 있어, 명시적 타입 인자나 변수 annotation을 추가해야 할 수 있다.
  • "대충 inferred 되던 코드"가 점점 덜 통과하는 방향이라고 보면 된다.

4) 모듈 해석과 경로 별칭 쪽 개선

  • Node의 subpath import에서 #/ 패턴을 지원한다.
  • --moduleResolution bundler--module commonjs 조합도 허용해, 점진적 이전 경로를 현실적으로 열어준다.
  • 웹앱/번들러 기반 프로젝트가 CJS 레거시와 공존할 때 꽤 유용하다.

5) 런타임 API 타입 지원 확대

  • es2025 target/lib 추가
  • Temporal 타입 포함
  • Map/WeakMap의 getOrInsert, getOrInsertComputed 타입 추가
  • RegExp.escape 타입 지원
  • dom에 iterable/asynciterable이 통합돼 설정이 단순해짐

실무 메모

  • 지금 당장 눈에 띄는 화려한 문법보다, 팀 레포에서 TS 7 준비를 시작할 신호탄으로 보는 게 맞다.
  • monorepo나 선언 파일 diff를 CI에서 엄격히 보는 팀은 --stableTypeOrdering 검토 가치가 크다.
  • 타입 추론 변화 때문에 업그레이드 전후 스냅샷 비교와 명시적 타입 보강 계획을 같이 잡는 게 안전하다.

Next.js Across Platforms: Adapters, OpenNext, and Our Commitments

  • 원문 제목: Next.js Across Platforms: Adapters, OpenNext, and Our Commitments
  • 원문 링크: https://nextjs.org/blog/nextjs-across-platforms
  • 정리일: 2026-04-17 KST
  • 정리 방식: 원문 저작권을 존중해 전문 번역 대신 한국어 상세 요약 제공

핵심 요약

Next.js 16.2의 Adapter API 안정화는 배포 생태계 관점에서 꽤 큰 사건이다. 그동안 Next는 프레임워크 기능은 강했지만, 플랫폼 사업자 입장에서는 build output과 동작 계약이 충분히 공개돼 있지 않아 "완전한 호환"을 맞추기 어려웠다. 이번 글은 그 문제를 공식적으로 풀겠다는 선언에 가깝다.

1) Adapter API가 하는 일

  • 빌드 결과물에 routes, prerender 정보, static assets, runtime target, caching rules 같은 내용을 타입화된 공개 계약으로 담는다.
  • 플랫폼은 이 출력을 읽어 자기 인프라에 맞게 매핑하면 된다.
  • 중요한 점은 Vercel도 같은 공개 계약을 쓴다고 명시한 부분이다. 즉, 사설 훅 없이 같은 규칙으로 간다는 뜻이다.

2) 왜 실무 FE 팀도 이걸 봐야 하나

  • 멀티 인스턴스 배포에서 캐시 동기화, on-demand revalidation 전파, streaming 정합성은 옵션이 아니라 기능 요구사항이다.
  • 지금까지는 "어떤 호스팅에 올리면 어디가 미묘하게 깨지는지"가 암묵지였다.
  • Adapter API와 공용 테스트 스위트가 생기면, 프레임워크 기능을 쓸 때 배포 타깃 차이를 예측하기 쉬워진다.

3) 공용 테스트 스위트와 verified adapter

  • 어댑터 작성자가 공식 테스트 묶음을 돌려 pass/fail을 확인할 수 있다.
  • open source + 전체 테스트 통과 시 verified adapter로 인정된다.
  • 이건 FE 팀 입장에선 "플랫폼 호환성 주장"을 문서가 아니라 테스트 결과로 볼 수 있게 된다는 의미다.

4) OpenNext의 역할

  • OpenNext가 먼저 사실상 호환 레이어를 만들며 AWS, Cloudflare, Netlify 방향 가능성을 증명했다.
  • 이번 안정화는 그 커뮤니티 실험을 공식 계약으로 끌어올린 셈이다.

5) 앞으로 기대할 변화

  • 새 Next 기능이 나오면 adapter contract에도 반영된다.
  • 배포 플랫폼들이 릴리스 뒤늦게 따라가는 게 아니라, 작업 그룹에서 미리 조율할 수 있다.
  • "Next는 결국 Vercel 전용 아니냐"는 불신을 줄이는 방향이다.

실무 메모

  • Vercel 외 플랫폼에 Next를 올리는 팀은 이제 framework feature 채택 판단을 더 공격적으로 해도 될 가능성이 커졌다.
  • 특히 cache/revalidation/streaming 민감한 앱은, 호환성 문서보다 adapter 테스트 커버리지를 먼저 보는 시대가 열릴 것 같다.

frontend-briefing-2026-04-17-KST

2026-04-17 프론트엔드 데일리 브리핑 아카이브.

선별 기준:

  • 최근 1개월 내 공개된 글
  • FE 실무 적용성이 높은 주제 우선
  • 커뮤니티 글(DEV 등)을 우선하고, 플랫폼 변화는 공식 글로 보완

참고:

  • 원문 저작권을 존중해 전문 번역 대신 한국어 상세 요약으로 정리했다.
  • 각 파일 상단에 원문 제목, 원문 링크, 정리일을 넣었다.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment