React Server Component (RSC)와 SSR 함께 보기
·
🌃 Next.js
리액트 컴포넌트의 Data fetching하나의 페이지에서 서버에서 받은 데이터를 활용해 뷰를 그려주는 컴포넌트를 만들어야한다면,어떤식으로 구성하는것이 좋을까. 1️⃣ 부모 컴포넌트에서 API 호출 후 자식컴포넌트로 전달하기 이 방법은 클라이언트에서 서버로 요청해야하는 API요청을 줄일 수 있다. 하지만 이방법은 부모컴포넌트에서 -> 자식으로 데이터를 내려줘야하기 때문에 부모- 자식 컴포넌트 사이의 결합성이 커지고, 유지보수가 어려워진다. 만약 자식 컴포넌트 중 하나가 위치를 옮겨야하거나 데이터가 바뀌는 이슈가 발생한다면수정작업에 드는 리소스로 인해 생산성이 떨어진다. 2️⃣각 자식 컴포넌트에서 필요한 API 직접 호출하기 특정 컴포넌트만 가져야할 데이터 라면, 해당 컴포넌트만 가디게하는게 더 좋은 것..
모바일 PWA 에서 FCM 푸시알림이 노트북으로만 오던 버그
·
🌴트러블슈팅
무비부키를 운영하면서 가장 힘들고 어려웠던 부분은 FCM 알림이였다. 어렵고 헤맸던 만큼 지금 돌아보면서 해결까지 복잡하게 돌아왔던 것 같은데 왜 그랬었는지 , 시행착오를 지금이나마 기록으로 남겨보자!! 일단 처음에는 알림을 "수신"이 1차 목표였다. 하지만 PWA환경이 메인 서비스에서 PC로 수신이 되고있었다. 알림이 가긴가는데 엉뚱한 기기로 가고있는것인데... 모바일 PWA에서는 알림이 전혀오지 않았고, PC 에서는 무비부키가 꺼져있는데도, localhost:3000으로 알림이 수신됐다. 처음 문제보고 추측했던 원인들은..1. 모바일에서 권한 문제인가? => notification.permission은 "granted"였다 => 권한 문제 x2. service worker 등록이 제대로안됐나? ..
Tailwind 정적 분석 한계와 CSS 변수 배경색 문제 해결과정
·
🌴트러블슈팅
무한스크롤에서 스크롤 맨위로 가는 플로팅 버튼을 만들었다.디자인 토큰을 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 레이아웃에서 스크롤하단에서 이미지가 갑자기 바뀌는 문제
·
🌴트러블슈팅
틴터레스트 같은 벽돌형 레이아웃 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
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)
·
⛲ 프로젝트
이벤트 목록을 보러 들어온 사용자가 첫 화면을 보기까지 30초 이상 기다린다면,이미 절반은 떠났다고 봐야 한다..스크롤도, 탭 전환도, 버튼 클릭도 먹지 않는 멈추는 순간이 길어질수록새로고침을 누르거나 뒤로가기를 누르게 되는 경험을 해봐서 더욱이 초기 렌더링의 중요성을 크게 생각하고있다. 문제 상황0. 페이지 전체가 Client Component기존에는 페이지 전체가 use client로 감싸진 클라이언트 전용 렌더링(CSR) 구조였고, 서버는 사실상 빈 HTML을 내려보낸 뒤 브라우저가 모든 컴포넌트를 다운받아 하이드레이션을 마칠 때까지 화면에 보여줄 게 거의 없었다.반대로 SSR 을 쓰면 서버가 곧바로 HTML을 만들어 보내기 때문에 -> 사용자는 즉시 UI의 뼈대를 확인할 수 있다 1. 무거운 컴포..
10,000건 테스트, MSW 기반 대용량 가상+무한 스크롤 적용
·
⛲ 프로젝트
백오피스 서비스에서는 생각보다 데이터 양이 엄청 많은 상황을 마주하게 된다. 서울우유 백오피스에서 진행했던 전자세금계산서 진위 검증 업무 역시,한 번에 수천에서 수만 건의 데이터가 처리 대상이 되는 구조였다. “실제 기업에서 이런 규모의 데이터를 다뤄야 한다면?”이라는 가정에서 시작했다. 무한스크롤, 가상스크롤의 차이 무한 스크롤 무한 스크롤은 사용자가 화면을 아래로 내릴 때마다서버나 API에서 새로운 데이터를 조금씩 불러오는 방식이다.한 번에 모든 데이터를 가져오지 않기 때문에네트워크 요청 측면에서는 효율적이다. 하지만 불러온 데이터가 계속 DOM에 쌓이기 때문에,1만 건의 데이터를 모두 조회하면 브라우저는1만 개의 DOM 노드를 동시에 렌더링하고 유지해야 한다. 데이터가 많아질수록 렌더링과 레이..
카카오톡에서 앱 설치 유도하기: PWA 외부 브라우저 리다이렉션 전략
·
🌴트러블슈팅
프로그레시브 웹 앱(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 환경에서 빌드가 오래 걸리면 생산성에 직접적인 영향을 미치기 때문에, 해결해보자 🔍 문제 ..
[Next.js] 6. 페이지 캐싱
·
🌃 Next.js/🔜 next.js-study
🔖 풀 라우트 캐시Full Route Cache : Next 서버측에서 빌드 타임에 특정 페이지의 렌더링 결과를 캐싱하는 기능. 빌드 타임에 페이지를 생성하고, -> 렌더링 결과를 Next.js 서버의 캐시에 저장 이후 브라우저에서 해당 페이지 요청이 들어오면, 새롭게 페이지를 생성하지 않고 캐시된 페이지를 즉시 반환한다. - 사진처럼 마지막 단계에서 `페이지 생성 결과`를 저장한다.- next 서버가 가동되었을때, 같은 페이지 요청이 들어오면 Full Router Cache에 저장된 페이지를 전달 ( 다시렌더링x))) > 이런 풀 라우트 캐시 동작 방식은, Page Router에서 빌드 타임에 페이지를 생성하고, 미리 저장해두었다가 요청 시 반환하는 SSG(정적 사이트 생성) 방식과 매우 유..
[Next.js] 5. 데이터패칭
·
🌃 Next.js/🔜 next.js-study
🔖 데이터 패칭 Page Router에서의 데이터패칭에서는 SSR,SSG,ISR 방식 등으로 서버측에서 데이터를 불러와 브라우저 측으로 한번 더 넘겼어야했다. - 사진처럼 Props를 하위 컴포넌트까지 내려주는 프롭 드릴링이 발생 - > 비효율적 App Router에서는 서버컴포넌트가 존재하기 때문에 위문제를 겪지 않아도된다 - 클라이언트 컴포넌트에서 async 비동기 함수는 충돌을 일으킬 수 있기 때문에 사용을 안하지만, 서버컴포넌트에 선언이 가능하다 !- async 비동기 함수를 사용하여 데이터패칭 🔖 데이터 캐시: fetch 메서드를 활용해 불러온 데이터를 Next 서버에서 보관하는 기능영구적으로 데이터를 보관하거나, 특정시간을 주기로 갱신 가능 ✅ 불필요한 데이터 요청의 수를 줄여서 웹..
[Next.js] 4. 페이지 라우팅 설정하기
·
🌃 Next.js/🔜 next.js-study
- 앱라우터는 page router 와 다르게 page.tsx 파일만 페이지로 취급한다.- 경로를 만들고싶으면 무조건 파일 먼저 만들기 ! - 동적 경로일 경우에도 [id] 파일 밑에 page.tsx 파일을 만들어줘야한다.💭 App router 버전으로 다시 만들기- App -> Search -> page.tsx 생성- App router는 props로 쿼리의 값이 전달됨- searchParams의 q 값만 쓸것이기 때문에 q?: string q값은 string이며 없을 수도 있다고 타입명시 해주면 된다. - id는 string 일수도있고 배열일 수도 있기때문에 타입은 {id: string | string[]}으로 정해주자- [[...id]] 로 정하면 optional catch all segment..
[FLOLI] 사용한 탠스택쿼리, 로그인 에러핸들링 다시보기
·
카테고리 없음
1️⃣Tanstack Query 탠스택 쿼리(TanStack Query)는 데이터 fetching, 캐싱, 동기화, 업데이트를 쉽게 관리하도록 돕는 React 라이브러리 Mutation (useMutation)useMutation은 데이터를 서버에 생성, 수정, 삭제 등의 작업을 수행할 때 사용한다.이 코드에서는 createPlaylist API 호출을 처리하기 위해 사용되었다. const createPlayListMutation = useMutation({    mutationFn: createPlaylist,    onSuccess: () => {      queryClient.invalidateQueries({ queryKey: ['playlists'] })      handleToastSucces..