Zustand로 전역 상태 관리하기
Frontend
React에서 전역 상태를 관리하는 방법은 여러 가지가 있다.Context API, Redux, Recoil 등 다양한 선택지가 있지만, 최근에는 Zustand가 주목받고 있다. Zustand는 용량이 가볍고 사용법이 직관적이며, 보일러플레이트 코드가 적다는 장점이 있다.이 글에서는 Zustand의 기본 사용법부터 실무에서 유용한 최적화 기법과 미들웨어 활용법까지 정리해봤다. Zustand를 사용하는 이유Context API의 한계Context API는 Props drilling 문제를 해결할 수 있지만, 범용적인 전역 상태 관리보다는 국소적인 데이터 공유에 더 적합하다.Context 값이 변경되면 해당 Context를 구독하는 모든 컴포넌트가 리렌더링되는 문제도 있다.Zustand의 장점매우 가벼운 용..
aria-label과 텍스트 콘텐츠
Frontend
aria-label을 쓰다 보면 헷갈리는 부분이 있다. 텍스트 콘텐츠와 aria-label을 함께 넣었을 때, 스크린 리더가 둘 다 읽을지 아니면 하나만 읽을지 애매한 것이다. 예를 들어 버튼에 "삭제"라고 써있고 aria-label="이 리뷰 삭제하기"를 추가하면 "이 리뷰 삭제하기 삭제"로 읽힐까? 아니면 둘 중 하나만 읽힐까? 정답은 요소마다 다르다. 어떤 요소는 aria-label이 텍스트를 완전히 대체하고, 어떤 요소는 텍스트와 함께 읽힌다.aria-label이 텍스트를 대체하는 요소들상호작용하는 요소들버튼, 링크, 입력 필드처럼 사용자가 클릭하거나 입력하는 요소들은 aria-label이 기존 텍스트를 대체한다.삭제수정여기에 해당하는 요소: , , , , 페이지 구조 요소들헤더, 네비게이션, ..
Next.js의 이미지 최적화
Frontend/Next.js
기본 사용법Next.js에서는 이미지 최적화를 위해 next/image컴포넌트를 사용한다.import Image from 'next/image'src: 이미지 소스 URLwidth 및 height:필수 속석으로, 이미지의 원본 크기를 지정레이아웃 시프트 방지 및 적절한 공간 확보에 사용반응형 이미지 설정 방법alt: 접근성을 위한 대체 텍스트quality:선택적 속성으로, 1-100 사이의 값 지정(기본값 75)WebP 등으로 변환 시 이미지 품질 조절에 사용 Next.js는 이 정보를 바탕으로 자동 WebP 변환, 레이지 로딩, 디바이스 크기에 맞는 이미지 제공 등의 최적화를 수행한다. 외부 이미지 사용외부 이미지를 사용할 경우, next.config.mjs에 다음과 같이 설정해줘야만 해당 이미지 주소..
Next.js 앱 라우터 고급 라우팅 패턴
Frontend/Next.js
Parallel RouteParallel Route(병렬 라우트)는 하나의 화면 안에 여러 페이지 컴포넌트를 병렬로 렌더링할 수 있게 해주는 기능이다.소셜 미디어 서비스나 관리자 대시보드와 같은 복잡한 구조의 서비스 구축에 특히 유용하다.여러 페이지 컴포넌트를 동시에 렌더링슬롯(Slot)을 사용하여 구현복잡한 레이아웃 구성에 적합 Slot슬롯은 병렬로 렌더링 될 페이지 컴포넌트를 보관하는 폴더이다.슬롯 이름은 @로 시작한다.슬롯 안의 페이지 컴포넌트는 자동으로 부모 레이아웃 컴포넌트에 props로 전달된다.폴더 구조 . ├── app │ └── parallel │ ├── @sidebar // slot 폴더 │ │ └── page.tsx │ ..
서버 액션 (Server Action)
Frontend/Next.js
서버 액션이란?서버 액션은 Next.js에서 제공하는 기능으로, 브라우저에서 직접 호출할 수 있는 서버 측 비동기 함수이다. 이를 통해 별도의 API 엔드포인트를 만들지 않고도 클라이언트에서 서버 측 로직을 실행할 수 있다.서버 액션을 사용하려면 함수 내부에 "use server" 지시어를 추가하면 된다.export default function Page() { const saveName = async (formData: FormData) => { "use server"; const name = formData.get("name"); await sql`INSERT INTO Names (name) VALUES (${name})`; }; return ( 제출 ..
Next.js 앱 라우터의 에러 핸들링
Frontend/Next.js
error.tsxApp Router에서는 error.tsx 파일을 사용하여 특정 경로 및 그 하위 경로에서 발생한 에러에 대한 UI를 설정할 수 있다.기본 사용법"use client";export default function Error() { return ( 오류가 발생했습니다. );};"use client" 지시어를 통해 반드시 클라이언트 컴포넌트로 설정해야 한다.서버와 클라이언트 양쪽에서 발생할 수 있는 모든 에러에 대응할 수 있다. Props 활용Next.js는 error와 reset props를 에러 컴포넌트에 자동으로 전달한다."use client";import { useEffect } from "react";export default function Error({ ..
스트리밍 (Streaming)
Frontend/Next.js
스트리밍이란?스트리밍은 서버에서 클라이언트로 대용량 데이터를 전송할 때, 데이터를 작은 조각으로 나누어 순차적으로 전송하는 기술이다.데이터 크기가 크거나 서버에서 데이터 준비에 시간이 많이 소요될 때 유용하다.작동 원리서버에서 데이터를 여러 조각으로 분할준비된 데이터 조각을 순차적으로 클라이언트에 전송클라이언트는 전체 데이터를 기다리지 않고 받은 조각부터 처리장점사용자 경험 향상: 긴 로딩 시간 없이 콘텐츠를 점진적으로 표시리소스 효율성: 서버와 클라이언트의 메모리 사용 최적화반응성 개선: 부분적인 데이터로도 사용자 상호작용 가능 Next.js의 HTML 스트리밍Next.js는 자체적으로 HTML 페이지를 스트리밍하는 기능을 제공한다.특징컴포넌트 단위의 스트리밍: 개별 컴포넌트를 독립적으로 스트리밍우선순..
라우트 세그먼트 옵션과 클라이언트 라우터 캐시
Frontend/Next.js
Route Segment Option라우트 세그먼트 옵션은 Next.js에서 특정 페이지의 동작을 강제로 설정할 수 있는 옵션이다.모든 컴포넌트를 개별적으로 확인하지 않고도 페이지를 정적(Static) 또는 동적(Dynamic) 페이지로 설정하거나, 페이지의 리밸리데이트 시간을 강제로 설정할 수 있다.dynamic 옵션dynamic 옵션을 사용하여 특정 페이지의 유형을 강제로 설정할 수 있다.export const dynamic = '옵션';설정 값'auto' 기본값으로, 아무것도 강제하지 않는다.Next.js가 페이지 내 컴포넌트들의 동작을 분석하여 자동으로 페이지 유형을 결정한다.'force-dytnamic' 페이지를 강제로 dynamic 페이지로 설정한다.모든 요청에 대해 서버에서 페이지를 렌더링한..
풀 라우트 캐시 (Full Route Cache)
Frontend/Next.js
풀 라우트 캐시는 Next.js 서버에서 빌드 타임에 특정 페이지의 렌더링 결과를 캐싱하는 기능이다.작동 방식빌드 타임에 페이지를 미리 렌더링하는 과정에서 해당 페이지에 필요한 데이터들은 Request Memoizations이나 Data Cache 등의 캐싱 기능을 거친다.렌더링이 완료된 결과를 'Full Route Cache'라는 이름으로 서버 측에 저장한다.빌드 후 Next.js 서버가 실제로 가동되었을 때, 해당 페이지로 접속 요청이 들어오면 새롭게 렌더링할 필요없이 캐시된 페이지를 그대로 브라우저에 전송한다. 페이지 분류Next.js에서 페이지는 정적 페이지와 동적 페이지로 분류되는데, Full Route Cache는 정적 페이지에만 적용된다.동적 페이지로 설정되는 기준동적 페이지는 특정 페이지가..
데이터 캐시와 리퀘스트 메모이제이션
Frontend/Next.js
Data Cache기본 사용법fetch 함수의 두 번째 인수로 객체를 전달하여 캐시 설정을 저장할 수 있다.기본적으로는 캐시되지 않는 요청으로 동작한다. (auto no-cache)const response = await fetch('url', { 캐싱 설정 });주의 사항이 캐싱 옵션들은 Next.js의 fetch 구현에서만 사용 가능하다.Axios 등 다른 HTTP 요청 라이브러리에서는 이 옵션들을 직접 사용할 수 없다. 캐싱 옵션cache: 'no-store'데이터 페칭의 결과를 저장하지 않는다.const response = await fetch('url', { cache: 'no-store' });실시간 데이터가 필요한 경우 (주식 시제, 실시간 채팅)cache: 'force-cache'요청된 결..