프로젝트에서 이미지 파일을 압축하고 webp로 변환하여 서버로 전송하도록 했다. 분명 file.type이 image/webp가 되는 걸 확인했는데 서버에서 받은 이미지 URL에는 원본 파일의 확장자가 적용되어 있었다. import Compressor from 'compressorjs';export async function compressImage( file: File, quality: number = 0.8,): Promise { return new Promise((resolve, reject) => { new Compressor(file, { quality, mimeType: 'image/webp', maxWidth: 880, maxHeight: 62..
프로젝트의 서비스 운영을 앞두고, 운영 중 오류에 대응하기 위해 모니터링 툴로 Sentry를 도입하기로 했다. 이 과정에서 ErrorBoundary를 적용하여 오류 발생 시 UX, DX를 개선하는 작업을 했다. Sentry와 ErrorBoundary를 적용한 과정을 정리해 보려고 한다. Sentry 도입 Sentry 초기화(libs/sentry.ts)import * as Sentry from '@sentry/react';import { useEffect } from 'react';import { useLocation, useNavigationType, createRoutesFromChildren, matchRoutes,} from 'react-router-dom';import { version..
프로젝트에서 S3에서 받아온 이미지 URL을 파일로 변환해서 서버로 보내야 하는 경우가 있었다. 파일 변환을 위해 S3 URL에 GET 요청을 해서 blob 타입으로 응답을 받아와야 했는데 여기서 CORS 오류가 발생했다. 요청 코드는 다음과 같다.import axios from 'axios';export const convertURLtoFile = async (url: string) => { try { const response = await axios.get(url, { responseType: 'blob', withCredentials: true, }); const blob = response.data; return new File([blob], 'pro..
프로젝트 작업을 하던 도중, 게시글의 댓글 목록에 Pagination을 적용하게 되었다. 공통 컴포넌트로 만들었던 Pagination 컴포넌트를 사용했는데 이 컴포넌트는 페이지 이동을 할 때마다 스크롤 위치를 최상단으로 이동하도록 동작하고 있었다. 그런데 이 동작은 Pagination을 게시글 목록 조회 같은 곳에서 사용하면 자연스럽지만, 게시글 영역의 아래에 위치하는 댓글 목록 조회에서 사용하니 조금 불편하다는 생각이 들었다. 특히 모바일 같은 경우에는 여러 페이지가 있을 때 다음 페이지 이동을 하려면 스크롤을 꽤 많이 내려야 했다. 또한 이는 게시글 본문 내용이 길어지면 더 심해질 것이다. 그래서 페이지 이동 시, '댓글 목록 최상단으로 스크롤 위치를 이동하면 어떨까?' 하는 생각을 했다. 게시글 ..
프로젝트에서 쿠키를 설정하면서 발생했던 문제 및 해결 방법을 기록한다. 1. 로컬 환경에서 서로 다른 도메인 간 쿠키 사용하기 - proxy 사용 도메인 - localhost, http://ec2-.xxx.com proxy를 사용하기 전에는 쿠키 도메인이 백엔드 도메인으로 세팅이 되어서 새로고침 시 쿠키가 삭제되고, 서버에서도 내가 보낸 쿠키를 읽을 수 없는 오류가 있었다. 로컬 환경에서는 proxy를 사용하여 동일한 도메인에서 요청한 것처럼 동작하게 할 수 있다. proxy를 설정할 수 있는 setup 파일에서 proxy 설정을 추가한다.vite.config.jsimport react from '@vitejs/plugin-react-swc';import { defineConfig, loadEnv..
프로젝트에서 쿠키를 사용하게 되었는데, 로컬 환경에서는 프론트엔드와 백엔드의 도메인이 달라 proxy를 적용해 주어야 했다. proxy 서버 URL은 환경 변수에 저장했다. 그런데 vite.config.js에 proxy 값으로 환경 변수를 설정했는데 proxy가 동작하지 않았고, 확인해 보니 환경 변수 값이 undefined로 나왔다. env 값을 제대로 가져오지 못한 게 원인이었다. import.meta.env를 사용했을 때 'ImportMeta' 형식에 'env' 속성이 없습니다.ts(2339)라는 오류가 떠서 Node에서 하듯이 process.env를 사용했는데 오류는 없었지만 값을 가져오지 못했다. 찾아보니 Vite는 .env 파일을 기본적으로 로드하지 않는다고 한다. 참고로 Vite는 Vit..
위와 같은 페이지에 리스트 데이터가 렌더링 되기 전까지 스켈레톤을 보여주려고 한다. Next.js에서도 React와 마찬가지로 Suspense를 사용하여 Skeleton UI를 적용할 수 있다. Skeleton 컴포넌트 구현하기(app/components/Skeleton.tsx)import styles from '@/styles/skeleton.module.scss'interface SkeletonProps { w: number h: number radius?: number wUnit?: string style?: React.CSSProperties}export default function Skeleton({ w, h, wUnit = 'px', radius = 8, style,..
서버 컴포넌트에서 api 요청 결과에 따라 redirect 경로를 설정하는 코드가 있었는데 try-catch로 감싸줬더니 오류가 발생했다. Error: NEXT_REDIRECT at getRedirectError (webpack-internal:///(rsc)/./node_modules/next/dist/client/components/redirect.js:49:19) at redirect (webpack-internal:///(rsc)/./node_modules/next/dist/client/components/redirect.js:60:11) at ... Next.js 공식 문서에 따르면 redirect가 NEXT_REDIRECT 오류를 발생시켜 try-catch 블록 내에서 사용하면 에러에 잡..
설치한 라이브러리npm i -D jest ts-jest jest-environment-jsdom @testing-library/jest-dom @testing-library/react 이전에 작성한 jest 설정 코드(jest.setup.js)import '@testing-library/jest-dom'(jest.config.js)const nextJest = require('next/jest')const createJestConfig = nextJest({ dir: './',})const customJestConfig = { rootDir: '.', setupFilesAfterEnv: ['/jest.setup.js'], moduleNameMapper: { '^@/(.*)$': '/app..
Next.js로 만든 프로젝트에서 SEO 최적화를 작업해 보고 구글과 네이버에 사이트를 등록해 보았다. 1. Metadata 설정하기Next.js 공식 문서를 참고하여 Metadata를 설정한다.검색 결과에 포함되지 않길 원하거나, 페이지 내 포함된 다른 링크가 검색 결과에 포함되지 않게 하려면해당 페이지 내 metadata.robots의 index, follow 옵션을 수정한다. 기본은 index, follow 모두 true이다. 필요에 따라 Caronical Tag 등을 추가한다. - Open Graph 설정 Next.js에서는 Open Graph를 설정하지 않아도 기본적으로 title과 image를 설정해 준다. title의 경우 페이지의 title과 동일하게 설정되고 이미지는 페이지 내에 이미..