상세 페이지 OG(Open Graph) 메타데이터 동적 생성하기
·
🌃 Next.js
영화를 함께 볼 이벤트를 만들고 링크를 공유할 때,카카오톡이나 트위터, 페이스북에서 어떤 썸네일 이미지와 제목, 설명이 미리보기로 노출되느냐가 사용자 클릭률에 큰 영향을 줍니다.하지만 정적 웹사이트라면 모든 링크가 동일한 OG 메타데이터를 가지기 때문에,이벤트나 게시물 같은 동적 페이지에서는 "어떤 링크를 공유해도 똑같은 썸네일" 문제가 발생합니다.문제 상황서비스 초기에 이벤트 상세 페이지(/detail/[id])를 공유하면,항상 하드코딩해둔 기본 OG 메타데이터가 노출되었습니다.예를 들어 /detail/2를 카카오톡에 붙여넣으면 실제 이벤트 정보가 아니라,무비부키 메인 링크 + 기본 썸네일만 미리보기로 표시되는 문제가 있었습니다. => 모든 페이지가 동일한 정적 메타데이터를 사용했기 때문에 발생했습니다..
실행 컨텍스트, 어떻게 설명할 수 있을까?
·
🎭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의 뼈대를..
[Next.js] 'Link', 'router.push()', 'a' tag 알고쓰자
·
🌃 Next.js
Next.js 로 웹 개발을 할때면 수 많은 페이지의 링크 이동을 구현 하게 되는데, 페이지 이동을 다음과 같이 크게 3가지의 방식으로 구현할 수 있다. 1. next/link의 Link 컴포넌트// 3. a 태그를 이용HOME 빌드 후, a tag로 자동 변환된다.a tag 의 장점을 갖는다. (SEO 최적화, prefetch 가능, 우클릭 기능 사용 가능 등)페이지 렌더링 시점에, 이동할 주소가 정해져 있는 경우 사용내부 페이지로의 이동 시, 이 방식을 사용해야 SPA 방식으로 전체 html중 필요한 부분만 리렌더링 된다.2. router.push()// 2. router.push() 를 이용 router.push("/home")}>HOME빌드 후, 이동할 주소가 html 상에 노출되지 않기 때문에 ..
10,000건 테스트, MSW 기반 대용량 가상+무한 스크롤 적용
·
⛲ 프로젝트
대용량 데이터 처리 시나리오 테스트백오피스 서비스에서는 생각보다 데이터 양이 엄청 많은 상황을 마주하게 됩니다.서울우유 백오피스에서 진행했던 전자세금계산서 진위 검증 업무처럼, 한 번에 수천~수만 건의 데이터가 쏟아질 수 있습니다.이럴 땐 화면이 버벅이거나 로딩이 오래 걸리는 경우가 있는데,"만약 기업에서 이런 대용량을 다뤄야 한다면?" 이라는 가정에서 시작했습니다.무한 스크롤만으로는 부족했던 이유처음에는 "그냥 무한 스크롤 쓰면 되지 않나?" 생각했습니다 무한 스크롤은 한 번에 모든 데이터를 불러오지 않고, 스크롤이 끝에 닿을 때 다음 데이터를 가져오는 방식이라 네트워크 요청 부담은 줄여줍니다.하지만 렌더링되는 DOM의 개수는 계속 누적되기 때문에, 페이지를 오래 내리다 보면 브라우저가 점점 무거워집니..
카카오톡에서 앱 설치 유도하기: PWA 외부 브라우저 리다이렉션 전략
·
⛲ 프로젝트
프로그레시브 웹 앱(PWA)이란프로그레시브 웹 앱은 웹 기술을 사용하여 개발된 애플리케이션으로, 사용자가 웹 브라우저에서 접속할 수 있으며 모바일 앱과 비슷한 사용자 경험을 제공합니다.사용자는 PWA를 스마트폰에 설치할 수 있으며, 설치 후에는 홈 화면에 아이콘이 생성되고 별도의 앱처럼 실행됩니다.또한, 서비스 워커(Service Worker)를 기반으로 오프라인에서도 작동 가능하며, 백그라운드에서의 푸시 알림 기능도 지원합니다. 무엇보다도 PWA는 운영체제(iOS/Android), 디바이스(폰/태블릿), 브라우저(Safari/Chrome 등)에 구애받지 않고 거의 모든 환경에서 동작할 수 있다는 장점이 있습니다.PWA의 장단점장점설치 부담이 낮다: 대부분의 PWA는 1MB 미만의 용량을 가지며, 사용자..
Home 진입 40초 → 2.5초, LCP를 93% 줄인 Next.js 최적화
·
⛲ 프로젝트
Home 화면, 왜 이렇게 느릴까... 🐢 🐢최근프로젝트를 진행하면서 가장 먼저 마주한 문제는 홈 화면이 너무 느리다는 점이다. 유저들이 가장 처음 접하는 이 메인 페이지에는 추천 캐러셀부터 인기, 최신, 다양한 카테고리 콘텐츠까지 구성되어 있었다.문제는 이 다양한 카테고리들이 이 성능에 큰 부담으로 작용하고 있었다는 것이다..... 처음엔 그냥 포스터이미지들이 많아서 이미지때문인가 싶었는데, 실제 Lighthouse로 측정해보니…Performance 점수는 38점,LCP(Largest Contentful Paint)는 무려 39.8초가 나왔다. 단순히 숫자만 보면 체감이 안 올 수도 있지만, 39.8초면 사용자가 페이지를 클릭하고도 거의 40초 가까이 주요 콘텐츠가 보이지 않는다는 뜻이다. 이쯤 ..
[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..
이미지 업로드부터 OCR 자동화까지, 세금계산서 등록 프로세스
·
⛲ 프로젝트
문제 정의: 복잡하고 오류가 잦았던 세금계산서 등록 프로세스기존 세금계산서 등록은 이미지를 업로드한 후 사용자가 직접 수기로 입력하는 구조였습니다.하지만 이 방식은 실제 사용 과정에서 다음과 같은 심각한 비효율과 오류를 유발했습니다:이미지를 회전하거나 자르지 않고 업로드 → OCR 인식 실패여러 장이 포함된 사진 업로드 → 텍스트 누락 또는 잘못된 매칭중복 세금계산서 업로드 → 관리자 수동 확인 필요OCR 결과를 그대로 등록 → 오타, 누락된 정보 발생이로 인해 세금계산서 1건을 처리하는 데 평균 약 250분이 소요되었고, 사용자 오타율은 월 10건 이상에 달했습니다.이를 개선하기 위해 이미지 편집부터 OCR 자동화까지 전 과정 자동화 시스템을 구축하게 되었습니다. 개선한 전체 흐름 사용자 이미지 업로드..
[Next.js] Vercel 빌드 속도를 60% 단축하기
·
🌃 Next.js
❓ 문제 상황: 빌드 시간이 너무 오래 걸린다우리 팀의 Next.js 기반 프로젝트는 Vercel을 통해 배포되고 있었는데, 어느 순간부터 배포 빌드 시간이 3분 41초를 넘기기 시작했다.버셀에서 배포하면 프리뷰로 먼저배포되고, promote to production 할수 있는데pwa 웹앱을 구현중에서는 브라우저의 모바일기기 보다 실제 모바일 pwa 앱으로 확인해야할 때가 있었는데(fcm,노치 등)빌드시간이 너무 오래걸려서 빠르게 수정해서 배포하고 확인하기가 어려웠다. 페이지 수나 컴포넌트 수가 많지 않은 비교적 경량 프로젝트였기 때문에, 이 빌드 시간은 너무 과하다고 판단했음 Vercel의 Serverless 환경에서 빌드가 오래 걸리면 생산성에 직접적인 영향을 미치기 때문에, 해결해보자 🔍 문제 ..
모바일 PWA 수신안됨 트러블슈팅
·
🌴트러블슈팅
🚧 발생한 문제 정리1. 알림 권한 요청 누락현상처음 앱을 설치한 사용자는 알림 권한을 수락하지 않았기 때문에, 알림 자체가 전송되지 않음.원인알림 권한 요청 로직이 없거나 조건문이 너무 제한적으로 설정되어 있었음.해결 방법사용자가 앱에 진입했을 때 자동으로 Notification.requestPermission() 호출iOS PWA의 경우, 유저가 명시적으로 클릭할 수 있도록 알림 권한 배너 표시 if (Notification.permission === "default") { const permission = await Notification.requestPermission(); if (permission === "granted") { await requestPermissionAndToken..
[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..