분류 전체보기 173

[맛길] Zustand + sessionStorage로 맛집 리스트 캐싱하기

Zustand와 sessionStorage로 데이터를 캐싱하게 된 계기 맛길을 배포 후 지인들에게 피드백을 요청했습니다. 가장 많이 받은 피드백이 페이지를 이동할 때마다 이전 데이터가 사라져 불편하다는 내용이었습니다.피드백을 바탕으로 생각해보니 아래와 같은 문제가 있을 수 있을 것 같습니다.페이지 전환이나 새로고침 시 기존 데이터를 다시 불러오기 위해 불필요한 API 요청이 발생API 응답이 길어질 경우, UX(사용자 경험) 저하길 찾기 기능에서 prop drilling 발생이 문제를 해결하기 위해 Zustand를 도입해 맛집 리스트와 위치 정보를 전역으로 관리하고, 맛집 리스트를 sessionStorage에 저장해 불필요한 API 호출을 줄이기로 했습니다.Zustand를 선택한 이유 : 상태 관리 라이..

[맛길] 이미지 최적화 (LCP 최적화)

LCP는 가장 큰 콘텐츠가 화면에 렌더링 되는 시간을 측정한 지표입니다. lighthouse로 측정한 결과 LCP(이미지)가 느림으로 측정되었습니다.  LCP가 낮게 측정되었다는 것은 화면에 콘텐츠가 늦게 렌더링 된다는 얘기입니다. 이는 사용자 경험(UX)에 큰 영향을 줄 수 있고 이탈로까지 이어질 수 있습니다. Next.js에서 제공하는 Image 컴포넌트를 사용해 해당 이슈를 해결해 보겠습니다. 이슈를 해결하기 전에 html img 태그를 사용했을 때 결과를 먼저 측정해 보겠습니다. img 태그 (제약 없음, Slow 4G, 3G)50kB의 작은 용량임에도 이미지를 내려받는데 4G 환경에서는 3.5초, 3G 환경에서는 12초가 소요됩니다. 이는 사용자에게 부정적인 경험을 줄 수 있습니다.이제 Next..

[맛길] 접근성, SEO 개선

사이트 배포 후 lighthouse를 이용해 접근성, SEO를 체크했습니다.분명 접근성과 SEO를 고려하면서 작업했다고 생각했는데 결과가 92점이네요. 낮은 점수는 아니지만 완성도 높은 서비스를 만들기 위해 개선 작업을 해보겠습니다.접근성 개선위 사진은 접근성 테스트에서 통과하지 못한 요소들입니다. 차례대로 하나씩 살펴보면서 수정해 보겠습니다. 1️⃣ 텍스트 & 배경색 명암비텍스트 색과 배경 색의 대비는 저시력자나 고령자도 인식할 수 있도록  4.5:1 이상이어야 한다고 합니다.기존 버튼의 경우 배경색이 #059669, 텍스트가 #FFFFFF로 3.7:1입니다. 명암비 접근성 테스트 사이트를 이용해 접근성을 준수하도록 수정했습니다. 2️⃣ 버튼 터치 영역 수정버튼의 크기를 W3C에서 권장하는 터치 영역 ..

[맛길] 안드로이드(AOS) 위치 정보(Geolocation API) 지연 문제 해결

사이트 배포 후 모바일 디바이스(AOS, IOS)에서 아래 브라우저들을 통해 길 찾기 기능을 테스트했습니다.Chrome (IOS, AOS)Naver 앱 (IOS, AOS)카카오 인 앱 브라우저 (IOS, AOS)Firefox (IOS, AOS)Edge (IOS, AOS)Opera (IOS, AOS)safari (IOS)삼성 인터넷(AOS)IOS에서는 길 찾기가 정상적으로 동작하는 반면, AOS( Android OS)의 경우 경로를 받기까지 매우 오래 걸리는 문제가 발생했습니다. 테스트에 사용한 기종이 오래된 갤럭시 S10이라는 의심이 들어, 가장 최신 기종인 갤럭시 s25로도 테스트해봤지만 결과는 같았습니다. 혹시 서버에서 응답이 늦게 오는건 아닐까 하는 생각에 Vercel의 로그도 확인해 봤지만, 실행..

[맛길] Naver Directions API를 이용한 길 찾기 기능 개발

현재 Naver Map API를 이용해 맛집 가게의 지도를 불러오고 마커를 찍는 기능까지 구현했습니다. 지인들에게 테스트와 피드백을 부탁했습니다. 모바일 디바이스에서 터치로 화면을 움직일 때 지도가 움직여서 불편하다.맛길 서비스 내에 지도에서 길 찾기 기능을 사용할 수 있으면 좋을 것 같다.첫 번째 피드백을 토대로 테스트 해보니 모바일 디바이스에서 지도 영역의 인터랙션 때문에 화면을 스크롤하기가 불편했습니다. 이 부분은 사용자 입장에서 부정적인 경험이라고 생각해 인터랙션 옵션을 제거하는 방법으로 수정했습니다. 두 번째 피드백인 길찾기 기능입니다.사용자 입장에서 생각해보니 맛길 서비스에서 맛집의 위치를 찾아도 별도의 길 찾기 서비스를 이용해야 한다는 점에서 번거로울 것 같습니다. 이런 불편함을 제거하고 사..

[Coworkers] 접근 권한 관련 이슈 해결

멤버 관련 테스트 작업을 진행하던 중 이슈를 발견했습니다.🚨 문제 상황 팀의 멤버가 아닌 유저가 팀 페이지(/[teamid])와 할 일 목록(/[teamid]/[tasklist])에 접근 및 추가/수정/삭제를 할 수 있습니다. 팀의 멤버가 아닌 사용자가 해당 페이지에 접근할 수 있는 유일한 방법은 URL을 직접 입력하는 것입니다. 하지만 URL을 직접 입력하여 접근한 후 수정/삭제 등의 작업을 시도할 가능성도 존재합니다. 이를 방지하기 위해 추가적인 보안 조치가 필요해 보입니다. 요청/추가/수정/삭제 동작이 모두 가능한 것을 보니, 서버에서 API 요청 시 팀 멤버 여부를 확인하는 로직이 없는 것 같습니다. 프론트엔드에서 처리할 수 있는 방법을 생각해 본 결과 아래 두 가지 정도가 있을 것 같습니다. ..

[맛길] Naver Map API를 이용한 맛집 지도 추가

오늘은 맛집 상세 페이지에 지도를 추가해 보겠습니다. 지도는 Naver Map API를 이용해 볼 계획입니다. 0️⃣ Naver Map API 선택 이유Naver Map API v3 특징  프레임워크에 의존하지 않고 독립적으로 동작하기 때문에 불필요한 의존성을 최소화할 수 있고,  React & Next.js로 제작된 맛길 프로젝트에 적합할 것 같아 선택했습니다. DOM 처리 및 웹 브라우저 호환 코드를 내장하고 있어 크로스 브라우징 이슈를 최소화하면서 손쉽게 지도 기능을 구현할 수 있을 거라 생각해 선택했습니다.별도의 CSS를 필요로 하지 않도록 설계된 내용을 보고, 개발 부담을 줄일 수 있을 것 같아서 선택했습니다. 모바일 환경에서도 최적화된 성능을 제공하기 때문에 별도의 최적화 작업이 필요하지 않아..

[Coworkers] IOS 이미지 업로드 이슈

🚨 문제 상황팀 수정하기 관련해서 IOS 기기에서 이미지가 업로드되지 않는 이슈가 생겼습니다.이미지 업로드 관련 코드uploadImage.tsimport postImage from '@/app/lib/image/postImage';const uploadImage = async (profile: FileList) => { if (!profile || !(profile[0] instanceof File)) return null; const formData = new FormData(); formData.append('image', profile[0]); const { url } = await postImage(formData); return url;};export default uploadImag..

[Coworkers] 리팩토링

오늘은 1차 배포 테스트가 얼마 남지 않아서 리팩토링을 진행해 보겠습니다.계획 없이 리팩토링을 진행하면 결과물의 퀄리티가 떨어질 수 있을 것 같아, 작업을 시작하기 전에 어떤 방향으로 개선할 것인지 계획을 세워보겠습니다.리팩토링 중점 사항1️⃣ 가독성변수와 함수를 이름만 보고도 어떤 역할을 하는지 알 수 있도록 의미 있게 수정하겠습니다.불필요한 로직이나 변수를 제거해 코드를 간결하게 유지하겠습니다.코드를 간결하게 유지하기 위해 컴포넌트를 기능별로 적절히 분리하겠습니다.2️⃣ 재사용성특정 UI가 반복적으로 사용되는 경우 컴포넌트화해 재사용하겠습니다.자주 사용되는 로직이나 기능은 커스텀 훅, 유틸 함수로 분리해 재사용하겠습니다. 3️⃣ 유지보수성컴포넌트와 함수가 하나의 책임만 갖도록 수정하겠습니다. SOLI..

[맛길] 상세 페이지 - Youtube 영상 추가

오늘은 상세 페이지를 작업할 건데요.처음 기획 당시 페이지 상단에 맛집 소개 Youtube 영상을 띄우기로 했었네요.. 어떤 방법이 있는지 찾아볼게요👀✨ 영상 추가 방법1️⃣ 기본 태그 이용  유튜브 영상에 자체적으로 퍼가기 기능을 제공하고 있네요😀 iframe의 src를 보니 프로젝트에서 사용하는 데이터의 videoId를 embed/ 뒤에 추가하면 될 것 같아요. 2️⃣ react-youtube 라이브러리 및 Youtube API 사용 사용법을 보니 videoId 부분에 Youtube API에서 요청을 통해 받아온 videoId를 넣어주면 되는 것 같아요. 원래라면 Youtube API를 연동해서 아래와 같은 과정을 거치겠죠🤔  서버에서 Youtube로 API key를 포함한 데이터 요청 유튜브..