2026/03 24

App Router 구조 오해로 인한 build 오류 문제 해결 과정

레시피 페이지의 route.ts 파일 작업을 마친 후, 작업 내용을 정리 한 pr을 올렸습니다. ci설정을 해뒀기 때문에 체크가 돌아가고 있었습니다. 평소보다 오래 걸리긴 했지만 lint, Type Check, build 체크가 모두 통과했고 내용도 그리 많지 않았기에 main 브랜치에 머지했습니다. 그러나 몇 시간 후, gmail로 build 오류가 발생했다는 메일이 왔습니다. 분명 내용도 많지 않았는데 어째서 build오류가 났는지 이해가 되지 않았지만 문제를 해결하기 위해 오류 로그를 체크 했습니다. 문제점 찾기// 오류 로그Run npm run build> MenuMate@0.1.0 build> next build⚠ No build cache found. Please configure build ..

TypeScript를 사용하는 이유

바닐라 JavaScript만으로도 충분히 좋은 개발을 할 수 있습니다. 저도 처음 개발을 배울 때는 HTML, CSS, JavaScript 이 세가지만 배웠고 이들 만으로도 프로젝트를 진행할 수 있었습니다. 하지만 최근의 대세는 TypeScript입니다. 어떤 이유로 JavaScript 를 대신해 TypeScript를 쓰게 된 것인지 이번 글을 통해 정리해 봤습니다. 타입스크립트를 사용하는 주요 이유로 크게 세 가지를 들 수 있습니다. 첫째, 정적 타이핑을 통해 코드의 안정성을 크게 향상시킬 수 있습니다. 개발 시 타입 오류를 런타임으로 실행하기 이전에 발견할 수 있어 런타임 에러를 줄이고, 코드의 품질을 개선할 수 있습니다. 이러한 장점은 특히 대규모 프로젝트에서 두드러집니다. 둘째, 개발자의 생산성을..

MenuMate 외부 API Raw타입 정규화 과정 정리, 레시피 페이지 조회 흐름 요약

레시피 페이지 또한 외부 API의 Raw 타입을 그대로 쓰기 보다는 정규화 하여 프론트 차원에서 쓰기 좋은 함수로 만들 필요가 있었습니다. 이번 글을 그 과정 및 과정에서 고민한 사항들을 정리한 것입니다. 문제점식약처의 조리식품 DB의 경우, 조리 단계를 배열이 아닌 string 타입이 펼쳐진 구조로 제시하고 있었습니다. // 조리 단계 Raw 데이터 타입 예시export type RecipeDetailRaw = {MANUAL01: string;MANUAL02: string;MANUAL03: string;MANUAL04: string;MANUAL05: string;MANUAL06: string;MANUAL07: string;MANUAL08: string;MANUAL09: string;MANUAL10: s..

이벤트 버블링과 이벤트 캡처링

이벤트 버블링이벤트 버블링은 이벤트가 발생했을 때 가장 안쪽의 타겟 요소에서 시작하여 부모 요소로 전파되는 방식입니다. 예를 들어, 버튼을 클릭했을 때 버튼 자체에서 이벤트가 발생한 후 이 이벤트가 상위 요소인 div, body, document, window로 전파되는 과정을 거치게 됩니다. 기본적으로 브라우저는 이벤트 전파를 버블링 단계에서 처리하도록 설계되어 있습니다. 이벤트 캡쳐링이벤트 캡처링은 이와 반대 방향으로 진행됩니다. 즉, 이벤트가 최상위 부모 요소에서부터 시작해 점점 타겟 요소로 내려오면서 전파됩니다. 예를 들어, window에서 이벤트가 시작되어 document, body, div를 거쳐 버튼에 도달하게 되는 방식입니다. 기본적으로 캡처링 단계는 비활성화되어 있지만, addEventL..

MenuMate 레시피 페이지(검색 결과 상세 페이지) 고민 사항들

검색 결과 카드는 음식의 이름, 이미지, 간단한 해시 태그 정도만 보여주고 있습니다.본 프로젝트의 목적에 맞게 레시피 같은 상세 정보를 불러오기 위해서 검색 결과 카드에서 이어지는 검색 결과 상세 페이지, 레시피 페이지를 설계할 필요가 있습니다. 1.레시피 페이지의 역할 정의사용자가 검색 시 나오는 검색 결과 카드를 통해 접근 가능한 상세 정보(기본정보, 재료, 조리 순서)를 확인하는 페이지 2. 라우팅 구조 정해보기id를 기준으로 상세 데이터를 다시 조회하는 구조리소스 중심 URL을 적용해볼지?리소스 중심 URL: 동사(행동) 대신 명사(자원, Resource)를 사용해서 URL을 구조화 하는 방식예시) /recipes/[id]라우팅은 식별자 중심으로 하는 편이 단순 3. 데이터 전달 방식 결정하기검..

webpack, rollup과 같은 번들러의 필요성

번들러는 다양한 파일과 모듈을 하나의 배포 가능한 번들로 묶는 역할을 합니다. 번들러가 필요한 주요 이유는 다음과 같습니다. 첫째, 네트워크 요청 성능을 개선하기 위해서입니다. 다수의 개별 파일에 대해 모두 네트워크 요청을 수행할 경우, 성능에 부정적인 영향이 있을 수 있습니다. 번들러는 다수의 파일을 하나 또는 소수의 파일로 묶어 네트워크 요청을 최적화합니다.예를 들어, 애플리케이션이 수백 개의 JavaScript, CSS, 이미지 파일을 사용한다면, HTTP 요청 수가 증가해 로딩 속도가 느려질 수 있습니다. 이때 번들러는 이들을 효율적으로 묶어 소수의 파일로 만듦으로써 네트워크 요청 수를 줄여줍니다. 둘째, 번들러는 트랜스파일링을 통해 더 효율적이고 호환성 있는 애플리케이션을 만드는데 기여합니다...

MenuMate 작업 상황 정리 및 앞으로의 작업 정리

사이드 프로젝트 MenuMate를 만들면서 지금까지의 작업 상황을 중간 정리하는 글입니다. 작업 상황 1. 기본 UI 제작메인 로고, 검색창 UI, 검색 결과 카드 UI 제작2026.03.16 - [개인 프로젝트 MenuMate] - MenuMate 검색창 UI 설계추후 CSS 수정 작업 및 디자인 변경 작업 할 예정(좀 더 보기 좋게) 2. 검색 상태 관리 설계검색 관련 컴포넌트를 UI 담당 컴포넌트 SearchBar와 검색 상태, 로직 담당 컴포넌트 SearchSection으로 나눠 관심사를 분리2026.03.19 - [개인 프로젝트 MenuMate] - MenuMate 검색 상태, 로직 담당 컴포넌트 SearchSection 설계 MenuMate 검색 상태, 로직 담당 컴포넌트 SearchSecti..

localStorage와 sessionStorage(+XSS 공격)

localStorage와 sessionStorage는 브라우저에서 제공하는 클라이언트 측 저장소 API로, 둘 다 데이터를 키-값 쌍 형태로 저장합니다.localStorage와 sessionStorage는 데이터의 지속성과 범위에서 차이점을 가집니다. localStorage localStorage는 데이터를 영구적으로 저장합니다. 브라우저를 닫거나 장치를 재부팅해도 데이터가 유지되며, 동일한 도메인 내의 모든 탭에서 데이터를 공유할 수 있습니다.사용 예로는 다크모드 같은 테마 설정이나 장바구니 데이터와 같이 장기적으로 유지해야 하는 데이터 저장에 적합합니다. sessionStorage sessionStorage는 데이터가 현재 브라우저 세션 동안만 유지되며, 브라우저 탭이나 창을 닫으면 데이터가 삭제됩니..

오픈 API 문서를 읽을 때 주의할 점

저는 지금까지 API를 연결할 때 swagger문서만을 활용했었습니다. 이번 사이드 프로젝트를 통해 처음으로 오픈 API 문서를 활용해 작업을 하게 되었습니다. 이에 구글링과 GPT 및 제미나이를 활용하여 오픈 API 문서를 활용할 시 주의할 점을 알아보고 이를 참고해 작업에 참고해보고자 합니다. 1. 구현하고자 하는 기능과 API가 정말 일치하는가 확인사실프로젝트 시작전부터 확인해야 하는 사항으로 해당 API가 만들고자 하는 기능과 일치하는 지를 확인해야 합니다. 2. 어떤 필드만 가져올지 계획API의 응답 형식을 바로 UI에 쓰는 것은 지양해야 합니다. 필드명을 바로 쓰지 말고 내부 타입으로 정규화 하거나 매핑해야 합니다. 3. 샘플 데이터 품질 확인샘플 데이터 몇 개를 확인하여 값이 비어있으면 어떻..

useEffect와 Suspense의 로딩 방식 차이

useEffect와 Suspense의 로딩 방식 차이 Suspense와 기존 로딩 상태 관리 방식인 useEffect()와 loading state는 로딩 상태를 관리하는 방식에서 근본적인 차이가 있습니다. 기존 방식에서는 데이터를 불러올 때 useEffect() 훅을 사용하고, 로딩 상태를 관리하기 위해 isLoading이라는 별도의 상태 변수를 만들어야 합니다. 예를 들어, 데이터를 불러오는 동안엔 isLoading을 true로 설정하고, 데이터가 다 불러온다면 false로 바꾸는 식입니다. 그래서 조건에 따라 로딩 UI를 보여주는 식으로 작동합니다. 이 방식은 간단한 상황에서는 충분히 유효하지만, 여러 개의 비동기 데이터를 다룰 때에는 조건부 렌더링 로직이 복잡해질 수 있습니다. Suspense는 ..