분류 전체보기 88

단순 소개 문서를 넘어서, 전달력을 고민한 README 작성기

MenuMate 프로젝트 README 링크프로젝트 READMEhttps://github.com/kimin0401/MenuMate 서론 개인 프로젝트를 진행하면서 기능 구현에는 많은 시간을 들였지만, 정작 그 결과물을 어떻게 정리해서 보여줄지에 대해서는 갈피를 잡지 못하고 있었습니다.특히 GitHub의 README는 단순한 설명 문서라고 했지만, 실제로는 프로젝트의 첫인상을 결정짓는 중요한 요소라는 것을 깨닫게 되었습니다.이번 글에서는 MenuMate 프로젝트의 README를 작성하면서 고민했던 과정과, 단순한 기능 나열이 아닌 전달력을 높이기 위해 어떤 부분을 개선했는지 정리해보려고 합니다. 문제 상황처음 README를 작성할 때는 아래와 같은 고민이 있었습니다.무엇을 어디까지 작성해야 할지 기준이 없었..

CDN(Content Delivery Network) 개념 및 사용 이유

CDN(Content Delivery Network) CDN(Content Delivery Network)은 전 세계에 분산되어 있는 서버들을 통해 사용자에게 웹 컨텐츠를 빠르고 효율적으로 제공하는 기술입니다. 웹사이트의 이미지, CSS, JavaScript 파일, 동영상 등 정적 컨텐츠를 사용자와 물리적으로 가까운 서버에서 전달하는 방식입니다. CDN의 작동 방식은 간단합니다. 먼저, 자주 요청되는 컨텐츠를 전 세계 여러 지역에 위치한 "엣지 서버(Edge Server)"라고 불리는 서버들에 캐싱합니다. 그리고 사용자가 웹사이트에 요청을 보낼 때, DNS를 통해 가장 가까운 엣지 서버로 트래픽이 라우팅되어 처리되도록 합니다.엣지 서버(Edge Server)데이터 생성 지점(사용자/기기)과 가장 가까운 ..

MenuMate 레시피 조회 로직 리팩토링 및 문제 해결 과정 정리

1. 문제 상황프로젝트를 진행하던 중 특정 레시피(자두라떼)의 상세 페이지 접근이 실패하는 문제가 발생했습니다.검색 결과에서는 해당 레시피가 정상적으로 노출되었지만, 상세 페이지로 이동하면 데이터를 불러오지 못하는 현상이 발생했습니다.이 문제는 단순한 데이터 오류가 아니라, 사용자가 클릭한 콘텐츠에 접근하지 못하는 UX 문제로 이어질 수 있는 상황이었습니다. 2. 원인 분석기존 MenuMate의 레시피 조회 구조는 다음과 같았습니다.1. 일정 범위의 레시피 목록 조회 (1 ~ 1000)2. 해당 목록에서 RCP_SEQ(id)로 특정 레시피를 찾음 즉, RCP_SEQ로 직접 조회가 블가능하고 레시피 하나를 찾기 위해서도 넓은 범위의 전체 목록을 조회할 필요가 있는 구조였습니다.문제는 API가 한 번에 조회..

MenuMate 배포 전략 고민 사항 정리

MenuMate의 1차적인 구현 사항(레시피 검색, 상세 레시피 조회)을 개발완료했습니다. 이제는 배포 전략에 대해 고민해봐야 합니다.이번 글에는 배포 작업을 하기 전에 배포에 대해 알아보고 배포 전략을 고민한 사항을 정리해보고자 합니다. 배포(Deployment)배포는 개발자가 로컬 환경(개인 컴퓨터)에서 제작 및 테스트를 마친 애플리케이션을 실제 운영 서버에 올려, 인터넷을 통해 사용자들이 접근하고 사용할 수 있도록 만드는 전 과정입니다.개인의 컴퓨터에서 개발할 때는 보통 localhost라는 주소로 테스트를 하며 개발하게 됩니다.하지만, localhost는 다른 컴퓨터에서는 접근이 불가능합니다.배포를 하게 되면 IP나 도메인과 같은 고유의 주소를 부여받게 되고 해당주소를 통해 사용자들이 접근할 수..

MenuMate 검색 로직 리팩토링 이후 Recoverable Error 해결

1. 문제 상황검색 기능 리팩토링 이후, 개발 환경에서 다음과 같은 에러가 발생했습니다.Hydration failed because the server rendered HTML didn't match the client Next.js에서는 이를 Recoverable Error로 표시하며, 클라이언트에서 다시 렌더링을 시도하고 있었습니다. 2. 에러의 의미구글링 및 AI와 상의 결과, 이 에러는 단순한 렌더링 문제가 아니었습니다.서버가 만든 HTML과 클라이언트가 처음 렌더링한 결과가 다르다는 의미였습니다. 3. 실제 발생 상황로그를 보면 다음과 같은 차이가 있었습니다.+ - 즉 서버는 를 렌더하고 클라이언트는 를 렌더하는 상황입니다. 동일한 컴포넌트인데 결과가 달라진 것입니다. 4. 원인 분석핵심 원..

MenuMate 검색 로직 리팩토링 작업 (상태 관리 -> 캐시 관리)

1. 리팩토링의 필요성 기존 검색 기능은 다음과 같은 UX를 보였습니다. 검색 후 결과 페이지 이동 -> 정상상세 페이지 -> 뒤로가기 -> 검색 결과 유지 ✅하지만 새로고침 시-> 다시 검색이 실행되면서 마치 다시 검색하는 것 같은 UI가 먼저 보이는 문제 발생사용자 입장에서 생각해본다면,"방금 본 검색 결과인데 왜 다시 검색하지??"분명 이런 생각이 들 것 같았습니다. 이는 분명 사용감의 저하로 이어질 것 같았고 리팩토링이 필요하다고 생각했습니다. 2. 추정되는 문제점 처음에는 페이지 구조 문제를 의심했습니다.현재 검색 결과 페이지가 별도로 존재하는 것은 아니기에 검색 결과를 별도 페이지로 분리해야 하는가?메인 페이지에서 상태로 관리하는 구조가 문제인가? 문제가 없는 뒤로가기는 문제가 없기 때문에 ..

TypeScript가 css import를 타입으로 인식하지 못하는 문제 해결 과정

1. 문제 상황 프로젝트에 캐싱 전략을 고민하던 중, TanStackQuery를 도입해보고자 했습니다. 앱 전체에서 Query를 쓸 수 있도록 기존의 레이아웃을 TanStackQuery용 Providers 컴포넌트로 감싸 줄 필요가 있었습니다.레이아웃 파일을 수정하던 도중, 에러가 발생한 것을 발견했습니다. 2. 해결 방법 모색이제와서 globals.css의 경로 문제가 발생했다는 것이 이상했습니다. 구글링 및 AI와 상의한 결과,tsconfig.json에 noUncheckedSideEffectImports: true 설정이 되어있다면 엄격한 체크 때문에 발생할 수 있음 TypeScript가 “일반 CSS 파일 import”를 타입으로 이해하지 못하는 상황두 가지 가능성이 있음을 깨달았습니다. tscon..

event.target과 event.currentTarget의 차이점(+ 이벤트 버블링)

event.target과 event.currentTarget은 모두 이벤트 객체의 속성이며, 각각 "이벤트가 실제로 발생한 요소" 와 "이벤트 리스너가 연결된 요소" 를 가리킵니다. 이 둘의 차이점을 이해하려면 이벤트 버블링을 알아야 합니다. 이벤트는 특정 요소에서 발생한 후 부모 요소들로 전파되는 과정(버블링)을 거치는데, 이 과정에서 target과 currentTarget이 다르게 동작합니다. 예를 들어, 부모 요소에 이벤트 리스너를 등록했지만 자식 요소에서 이벤트가 발생하여 버블링된 상황에서, target은 "이벤트가 발생한 요소"인 자식 요소를 가리킵니다. 반면, currentTarget은 "이벤트 리스너가 연결된 요소"인 부모 요소를 가리킵니다. target은 “사용자가 직접 상호작용한, 즉 ..

Next.js 검색 API 500 에러 디버깅 및 문제 해결 과정 정리

1. 문제 상황MenuMate 프로젝트에서 레시피 검색 기능을 구현하던 중, 다음과 같은 문제가 발생했습니다.검색어 입력 후 제출 시에는 정상적으로 결과가 나옴뒤로가기 / 새로고침 시 간헐적으로 500 에러 발생검색 중 오류 발생시 출력되는 '레시피 검색 기능을 구현하던 중, 다음과 같은 문제가 발생'가 나옴 항상 성공하는 것도 아니고 항상 실패하는 것도 아닌 간헐적으로 검색 요청이 실패하는 문제 상황을 이해할 수 없었습니다. 2. 초기 의심 포인트처음에는 다음과 같은 가능성들을 의심했습니다.API route(/api/search) 로직 문제searchRecipes()(검색 유스케이스 진입점) 내부 로직 문제JSON 파싱 에러네트워크 오류이중에서 특정 상황에서만 발생하는 조건부 원인을 찾아보고자 했습니..

길이 단위 px, em, rem

PXpx은 화면의 물리적인 픽셀 단위를 기준으로 한 고정 단위입니다. 이 값은 절대적인 크기를 나타내며, 요소의 크기가 고정되어 디바이스의 해상도나 사용자 설정에 영향을 받지 않습니다. 예를 들어, font-size: 16px으로 설정하면 항상 16픽셀 크기로 표시됩니다. 픽셀 단위는 간단하고 정확한 제어를 제공하지만, 사용자의 접근성 설정(예: 브라우저에서 텍스트 크기 확대)에 따라 조정되지 않아 유연성이 떨어질 수 있습니다. emem은 해당 요소에 현재 적용된(즉, 부모 요소 또는 현재 요소의) font-size를 기준으로 하는 상대 단위입니다. 기본적으로, 브라우저의 초기 폰트 크기가 16px이므로, 상속받은 기본값이 없을 경우 1em은 16px로 계산됩니다. 그러나 상위 요소에 따라 상대적으로 크..