기술 블로그
웹과 앱을 만들며 남긴 기록 447편입니다.
여러 웹 서비스를 하나의 MongoDB Atlas 클러스터에서 운영하다 보면 트래픽이 증가할 때 서비스별 클러스터 분리나 멀티 리전 구성을 고민하게 됩니다. 특히 해외 사용자의 콘텐츠 조회가 늘어나면 데이터베이스를 사용자와 가까운 국가에 추가해야 하는지 판단하기 어려울...
MongoDB Atlas를 운영하다 보면 Performance Advisor에서 Drop Indexes, Unused Indexes, Redundant Indexes 같은 권고를 발견할 수 있습니다. 이때 권고된 인덱스를 Atlas 화면이나 MongoDB Shell에서...
force-dynamic 대신 ISR을 선택하는 기준과 콘텐츠 성격별 revalidate 주기, Redis 2중 캐시 구성으로 Vercel 비용과 DB 부하를 줄이는 방법을 정리했습니다.
목록 페이지가 매 요청마다 본문 전체를 읽어 발췌를 만들던 구조를 excerpt 필드와 Mongoose .select()로 바꾼 과정을 정리했습니다. DB 읽기 I/O와 직렬화 비용을 줄이는 방법을 살펴봅니다.
Vercel Image Optimization 과금이 줄지 않는 원인과 next.config.ts 전역 unoptimized 설정, S3 고아 이미지 정리 자동화를 정리했습니다. 최적화를 다시 켤 때 필요한 비용 방어 설정도 함께 살펴봅니다.
트래픽이 늘 때 페이지 응답이 느려지고 MongoDB 커넥션 사용량이 비정상적으로 높아지는 현상이 있었습니다. 이상한 건 읽기 페이지(글 목록이나 상세 화면)인데도 유저 관련 DB 쿼리가 계속 찍혔다는 점입니다. 글을 읽는 데 왜 유저 컬렉션을 조회하고 있었을까요? 범...
수동으로 관리하던 URL 필드를 YouTube API 자동화와 다국어 구조로 리팩터링한 과정을 정리했습니다. search 대신 playlistItems로 API 쿼터를 아끼는 방법을 살펴봅니다.
존재하지 않는 인덱스를 조회하던 코드와 불필요한 다국어 루프, 남아 있던 레거시 데이터를 걷어내 API 호출 비용과 응답 지연을 줄인 과정을 정리했습니다.
최근 MongoDB에서 특정 컬렉션의 응답 시간이 간헐적으로 튀는 현상을 확인했습니다. 평균 지연 시간만 보면 아주 심각한 수준은 아니었습니다. 대부분의 요청은 빠르게 처리되고 있었지만, 일부 요청에서 평균보다 훨씬 높은 지연 시간이 발생하고 있었습니다. 처음에는 단순...
MongoDB 및 Mongoose 환경에서 조회 속도가 느려지는 원인인 In-Memory Sort(메모리 정렬) 해결법과 .select(), populate 프로젝션을 통한 쿼리 성능 최적화 실무 사례를 소개합니다. 다른 페이지보다 5배 느린 조회 서비스 서비스를 운영...
grep과 sed, awk, Emacs에서 함께 쓸 수 있는 정규표현식 문법 차이를 정리했습니다. 환경이 달라도 깨지지 않는 표현식을 쓰는 기준을 살펴봅니다.
React Custom Hook 분리 타이밍이 고민이신가요? 헬퍼(일반) 함수와의 명확한 차이점부터 실무 적용 기준, 클린 코드를 위한 Before&After 예시까지 한눈에 깔끔하게 정리해 드립니다. "이 코드, 꼭 Custom Hook으로 만들어야 할까?" 리액트로...
React는 언제 리렌더링되는가? 방법을 알아보기 전에, React가 리렌더링을 수행하는 트리거를 명확히 이해해야 합니다. State(상태) 변경: 컴포넌트의 state가 바뀌면 리렌더링됩니다. Props 변경: 부모로부터 전달받은 props가 바뀌면 리렌더링됩니다....
한 눈에 보는 요약 컴포넌트는 레고 블록과 같습니다. 이때 Props는 외부에서 조립할 때 끼워주는 부품(설정값) 이고, State는 블록 내부에서 스스로 움직이는 스위치(상태값) 입니다. 특징 Props State 개념 컴포넌트 외부에서 전달받는 데이터 컴포넌트 내부...
Next.js App Router에서 쿼리 스트링을 다룰 때 발생하는 대표적인 경고 및 빌드 에러의 원인을 분석하고, Suspense를 활용한 올바른 해결 방법을 학습합니다. 문제 상황 및 에러 원인 분석 Next.js 빌드 시 에러 발생: Entire page deo...
Hydration Mismatch란? Next.js의 SSR 또는 SSG 환경에서 미리 생성된 서버 측의 HTML 결과물과, 브라우저에서 JavaScript가 실행되며 구축한 클라이언트 측의 DOM 트리가 서로 일치하지 않을 때 발생하는 에러입니다. 왜 발생할까요? N...
웹 페이지에서 이미지는 전체 리소스 크기의 가장 큰 비중을 차지합니다. 이미지만 잘 최적화해도 웹사이트 속도가 획기적으로 빨라지고, UX와 SEO 점수가 크게 올라갑니다. Next.js는 이를 자동으로 처리해 주는 강력한 next/image 컴포넌트를 제공합니다. 일반...
Next.js의 App Router는 강력한 메타데이터 API를 제공합니다. 정적인 페이지는 export const metadata를 사용하면 되지만, 블로그 포스트, 상품 상세 페이지, 연예인 프로필 등 동적으로 변하는 페이지의 SEO를 극대화하려면 generateM...
Next.js에서 동적 라우팅은 게시글 상세 페이지, 상품 상세 페이지, 사용자 프로필 페이지처럼 URL의 일부가 데이터에 따라 달라지는 페이지를 만들 때 사용합니다. 예를 들어 /posts/1, /posts/2, /products/macbook처럼 주소는 다르지만 같...
Next.js App Router를 처음 배우면 use client를 언제 사용해야 하는지 헷갈릴 수 있습니다. 결론부터 말하면, 브라우저에서 동작해야 하는 기능이 있을 때만 use client를 사용합니다. Next.js App Router에서는 기본적으로 컴포넌트가...