Next.js 빌드에서 Google Fonts 타임아웃 해결, next/font/local과 @fontsource 적용
·
• TroubleShooting
배포 워크플로에서 빌드가 갑자기 실패하기 시작했다.FetchError: request to https://fonts.gstatic.com/s/poppins/v24/pxiByp8kv8JHgFVrLDz8Z11lFd2JQEl8qw.woff2 failed type: 'system', errno: 'ETIMEDOUT', code: 'ETIMEDOUT'Failed to compile.src/app/layout.tsx`next/font` error:Failed to fetch `Poppins` from Google Fonts.`ETIMEDOUT`는 파일이 없다는 뜻이 아니라 연결 자체가 시간 안에 끝나지 않았다는 뜻이다. 처음에는 빌드 시 Google Fonts에 한 번에 너무 많은 폰트 파일을 요청하면서 타임..
React Server Component (RSC)와 SSR 함께 보기
·
• Next.js
리액트 컴포넌트의 Data fetching하나의 페이지에서 서버에서 받은 데이터를 활용해 뷰를 그려주는 컴포넌트를 만들어야한다면,어떤식으로 구성하는것이 좋을까. 1️⃣ 부모 컴포넌트에서 API 호출 후 자식컴포넌트로 전달하기 이 방법은 클라이언트에서 서버로 요청해야하는 API요청을 줄일 수 있다. 하지만 이방법은 부모컴포넌트에서 -> 자식으로 데이터를 내려줘야하기 때문에 부모- 자식 컴포넌트 사이의 결합성이 커지고, 유지보수가 어려워진다. 만약 자식 컴포넌트 중 하나가 위치를 옮겨야하거나 데이터가 바뀌는 이슈가 발생한다면수정작업에 드는 리소스로 인해 생산성이 떨어진다. 2️⃣각 자식 컴포넌트에서 필요한 API 직접 호출하기 특정 컴포넌트만 가져야할 데이터 라면, 해당 컴포넌트만 가디게하는게 더 좋은 것..
모바일 PWA 에서 FCM 푸시알림이 노트북으로만 오던 버그
·
• TroubleShooting
무비부키를 운영하면서 가장 힘들고 어려웠던 부분은 FCM 알림이였다. 어렵고 헤맸던 만큼 지금 돌아보면서 해결까지 복잡하게 돌아왔던 것 같은데 왜 그랬었는지 , 시행착오를 지금이나마 기록으로 남겨보자!! 일단 처음에는 알림을 "수신"이 1차 목표였다. 하지만 PWA환경이 메인 서비스에서 PC로 수신이 되고있었다. 알림이 가긴가는데 엉뚱한 기기로 가고있는것인데... 모바일 PWA에서는 알림이 전혀오지 않았고, PC 에서는 무비부키가 꺼져있는데도, localhost:3000으로 알림이 수신됐다. 처음 문제보고 추측했던 원인들은..1. 모바일에서 권한 문제인가? => notification.permission은 "granted"였다 => 권한 문제 x2. service worker 등록이 제대로안됐나? ..
Tailwind 정적 분석 한계와 CSS 변수 배경색 문제 해결과정
·
• TroubleShooting
무한스크롤에서 스크롤 맨위로 가는 플로팅 버튼을 만들었다.디자인 토큰을 CSS 변수로 정의해 두고,Tailwind에서 bg-buttonBg, text-buttonText 같은 커스텀 색상 유틸을 써서라이트/다크 모드 색 전환을 구현하려 했었다. 그런데 .....다크 모드에서 버튼 배경이 투명(transparent) 처럼 보였다...텍스트 색(text-buttonText)은 잘 바뀌는데, 배경색만 안 먹는 문제를 마주했다. 1. 기존코드:root { --color-button-bg: #ffffff; --color-button-hover: #2563eb; --color-button-text: #111827;}.dark { --color-button-bg: #1e1e1e; --color-butto..
Masonry 레이아웃에서 스크롤하단에서 이미지가 갑자기 바뀌는 문제
·
• TroubleShooting
틴터레스트 같은 벽돌형 레이아웃 Mansonry 를 구현하고싶어서 columns 속성을 사용했는데, 스크롤을 내려서 새로운 이미지가 로드될 때마다 이미 보고 있던 이미지들이 갑자기 다른 이미지로 바뀌고 있었다.. 내의도는 로드된 이미지들은 그대로 있고, 하단부터 새 이미지목록들이 불러왔어야하는데, 깜빡거리면서 자연스럽지 못한 사용자 경험을 겪고있다... 초기 코드 {images.map((img) => ( ))}const fetchImages = async () => { const res = await fetch(`https://picsum.photos/v2/list?page=${page}&limit=20`); const data = await res.json(); ..
모든 링크가 같은 썸네일로 보이던 문제, 동적 OG 태그로 이벤트별 미리보기
·
• Next.js
영화를 함께 볼 이벤트를 만들고 링크를 공유할 때,카카오톡이나 트위터, 페이스북에서 어떤 썸네일 이미지와 제목, 설명이 미리보기로 노출되느냐가 사용자 클릭률에 큰 영향을 준다..나라도 설명을 보기보다는 썸네일 이미지에 더 눈길이 먼저간다. 하지만 정적 웹사이트라면 모든 링크가 동일한 OG 메타데이터를 가지기 때문에,이벤트나 게시물 같은 동적 페이지에서는 "어떤 링크를 공유해도 똑같은 썸네일" 이 보여진다. 그리고 실제 서비스를 운영하면서사용자 유입 경로를 GA4로 분석했을 때, 직접 검색해서 접속하는 수단보다는, 인스타그램/카카오톡 링크 공유 → 인앱브라우저 접속이 주요 패턴이었다.. 하지만 인앱브라우저 환경에서는 공유된 링크 미리보기가 단순 텍스트로만 노출되어, 실제 이벤트 참여로 이어지는 비율(참여..
실행 컨텍스트, 어떻게 설명할 수 있을까?
·
• JavaScript & CSS
Excution Context (실행 컨텍스트) 란 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다. JS에는 동일한 환경에 있는 환경정보들을 모은 실행 컨텍스트를 콜스택에 쌓아올린 후 실행하여 코드의 환경과 순서를 보장할 수 있게 된다. 풀어서 설명하면 스택의 경우 FILO (First In, Last Out) 의 구조이기에 순서를 보장,콜스택 내부에 쌓인 실행 컨텍스트의 정보를 통해 환경을 보장할 수 있는 것이다. 여기서 환경이란 전역공간이 될 수 있고, 함수 즉 함수 내부의 환경이 될 수 있다var temp = 'temp'; function b (){ console.log('안녕하세용');} function a (){ b();} a();처음 자바스크립트 코드를 실행하는 순..
이벤트 페이지 성능최적화 (LCP 37 => 2.5, CLS 0.219=>0.006)
·
• Project
이벤트 목록을 보러 들어온 사용자가 첫 화면을 보기까지 30초 이상 기다린다면,이미 절반은 떠났다고 봐야 한다..스크롤도, 탭 전환도, 버튼 클릭도 먹지 않는 멈추는 순간이 길어질수록새로고침을 누르거나 뒤로가기를 누르게 되는 경험을 해봐서 더욱이 초기 렌더링의 중요성을 크게 생각하고있다. 문제 상황0. 페이지 전체가 Client Component기존에는 페이지 전체가 use client로 감싸진 클라이언트 전용 렌더링(CSR) 구조였고, 서버는 사실상 빈 HTML을 내려보낸 뒤 브라우저가 모든 컴포넌트를 다운받아 하이드레이션을 마칠 때까지 화면에 보여줄 게 거의 없었다.반대로 SSR 을 쓰면 서버가 곧바로 HTML을 만들어 보내기 때문에 -> 사용자는 즉시 UI의 뼈대를 확인할 수 있다 1. 무거운 컴포..
10,000건 테스트, MSW 기반 대용량 가상+무한 스크롤 적용
·
• Project
백오피스 서비스에서는 생각보다 데이터 양이 엄청 많은 상황을 마주하게 된다. 서울우유 백오피스에서 진행했던 전자세금계산서 진위 검증 업무 역시,한 번에 수천에서 수만 건의 데이터가 처리 대상이 되는 구조였다. “실제 기업에서 이런 규모의 데이터를 다뤄야 한다면?”이라는 가정에서 시작했다. 무한스크롤, 가상스크롤의 차이 무한 스크롤 무한 스크롤은 사용자가 화면을 아래로 내릴 때마다서버나 API에서 새로운 데이터를 조금씩 불러오는 방식이다.한 번에 모든 데이터를 가져오지 않기 때문에네트워크 요청 측면에서는 효율적이다. 하지만 불러온 데이터가 계속 DOM에 쌓이기 때문에,1만 건의 데이터를 모두 조회하면 브라우저는1만 개의 DOM 노드를 동시에 렌더링하고 유지해야 한다. 데이터가 많아질수록 렌더링과 레이..
카카오톡에서 앱 설치 유도하기: PWA 외부 브라우저 리다이렉션 전략
·
• TroubleShooting
프로그레시브 웹 앱(PWA)이란프로그레시브 웹 앱은 웹 기술을 사용하여 개발된 애플리케이션으로, 사용자가 웹 브라우저에서 접속할 수 있으며 모바일 앱과 비슷한 사용자 경험을 제공한다.사용자는 PWA를 스마트폰에 설치할 수 있으며, 설치 후에는 홈 화면에 아이콘이 생성되고 별도의 앱처럼 실행된다. 무엇보다도 PWA는 운영체제(iOS/Android), 디바이스(폰/태블릿), 브라우저(Safari/Chrome 등)에 구애받지 않고 거의 모든 환경에서 동작할 수 있다는 장점이 있다. PWA의 단점 브라우저/OS별 지원 격차특히 iOS Safari에서는 PWA 관련 기능이 제한적이라, 설치를 자연스럽게 유도할 수 있는 API가 아예 제공되지 않는다.그래서 같은 기능이라도 안드로이드와 iOS에서 사용자 경험이 달라..
[Next.js] 에러핸들링, 서버액션( revalidatePath()
·
• Next.js
에러핸들링 error.tsx 파일을 만들어서 해당 파일의 위치와 하위폴더의 에러는 error.tsx가 대신사용된다.기본적으로 오류는클라이언트 서버 어떤환경이든 발생할 수 있기때문에 클라이언트 컴포넌트 설정해준다 - next.js는 에러발생시 에러컴포넌트에서 js에러타임의 에러객체를props로 전달해준다.- reset : error가 발생한 컴포넌트 복구하기위해 재렌더링하는 함수 ( 서버컴포넌트 다시 실행 x, 클라이언트 컴포넌트에서 발생한 에러만 복구 가능) 'use client';import { useEffect } from 'react';export default function Error({ error, reset }: { error: Error; reset: () => void }) { useE..
[Next.js] Vercel 빌드 속도를 60% 단축하기
·
• Next.js
❓ 문제 상황: 빌드 시간이 너무 오래 걸린다우리 팀의 Next.js 기반 프로젝트는 Vercel을 통해 배포되고 있었는데, 어느 순간부터 배포 빌드 시간이 3분 41초를 넘기기 시작했다.버셀에서 배포하면 프리뷰로 먼저배포되고, promote to production 할수 있는데pwa 웹앱을 구현중에서는 브라우저의 모바일기기 보다 실제 모바일 pwa 앱으로 확인해야할 때가 있었는데(fcm,노치 등)빌드시간이 너무 오래걸려서 빠르게 수정해서 배포하고 확인하기가 어려웠다. 페이지 수나 컴포넌트 수가 많지 않은 비교적 경량 프로젝트였기 때문에, 이 빌드 시간은 너무 과하다고 판단했음 Vercel의 Serverless 환경에서 빌드가 오래 걸리면 생산성에 직접적인 영향을 미치기 때문에, 해결해보자 🔍 문제 ..
[FLOLI] 사용한 탠스택쿼리, 로그인 에러핸들링 다시보기
·
카테고리 없음
1️⃣Tanstack Query 탠스택 쿼리(TanStack Query)는 데이터 fetching, 캐싱, 동기화, 업데이트를 쉽게 관리하도록 돕는 React 라이브러리 Mutation (useMutation)useMutation은 데이터를 서버에 생성, 수정, 삭제 등의 작업을 수행할 때 사용한다.이 코드에서는 createPlaylist API 호출을 처리하기 위해 사용되었다. const createPlayListMutation = useMutation({    mutationFn: createPlaylist,    onSuccess: () => {      queryClient.invalidateQueries({ queryKey: ['playlists'] })      handleToastSucces..
AWS 이미지 url 가져올때 이미지 깨짐 해결
·
• TroubleShooting
프론트엔드에서 s3에 이미지 파일을 업로드하고, 업로드한 url을 가져와서 미리보기를 통해 렌더했다. 근데 요청도 잘 오는데 , s3주소에 들어가보면 깨진 이미지로 보이고, UI에도 렌더가 깨진이미지로 되어있었다.  s3주소에서 깨진이미지여서 s3에 저장할때 (이미지를 업로드할때)문제가 있을거라고 생각했는데 구글링한 후 한글 파일 이름 때문이라는것을 알게되었다. 찾아보니, 'cat.jpg' => 'https://s3버킷주소.../cat.jpg''고양이.jpg' => 'https://s3버킷주소.../%EA%B3%A0%EC%96%91%EC%9D%B4.jpg'이런식으로 파일이름을 받아서url주소로 인코딩하는 과정에서 한글을 저렇게 바꾸어 놓는것이였다.  그래서 한글이름을 그대로 사용하려면, 인코딩된 주소를 ..
이미지 업로드 구현( 미리보기)
·
• React
🤔 이미지 업로드란?이미지 업로드는 사용자가 자신의 컴퓨터나 스마트폰에서 선택한 이미지를 웹 서버나 클라우드 스토리지(AWS S3 등)에 보내 저장하고, 저장된 이미지의 주소(URL)를 받아오는 작업입니다. 사용자 → 클라이언트(브라우저) → 서버 → 스토리지(AWS S3) → 서버 → 클라이언트🧠 1. 전체 흐름 이해하기이미지 업로드 기능은 이렇게 동작해요:이미지 선택: 사용자가 이미지를 선택합니다.미리보기: 선택한 이미지를 화면에 미리 보여줍니다.업로드: 이미지를 서버에 업로드합니다.서버 응답: 서버에서 이미지 URL을 반환받습니다.저장: 이미지 URL을 저장해서 나중에 사용할 수 있도록 합니다.📌 주요 파일들hooks/ useImagePreview.ts → 이미지 상태 관리 (미리보기, 선택 ..