들어가며,Next.js 16 (App Router) 을 공부하다 보면 dynamic routes, params, generateStaticParams, runtime, cache 같은 개념이 한 번에 쏟아진다. 특히 공식 문서의 With Cache Components 섹션은 번역해서 읽으면 이해되지만, 실제로는 잘 와닿지가 않았다. 이 글에서 문서를 옮기기 보다 실제로 헷갈렸던 지점들을 기준으로 왜 동적 라우트가 런타임이 되는지, generateStaticParams는 왜 필요한지 정리해보려고 한다. 동적 라우트, 그냥 URL 변수라고 생각하면 안 된다.Next.js 16 에서의 동적 라우트는 단순히 "URL에 들어오는 변수" 정도로 생각하면 헷갈린다.URL 구조 자체가 렌더링 방식에 영향을 주기 때문이..
전체 글
들어가며,입사 초, LMS 온라인 강의 이수 처리 기능을 맡게 되었다.당시에도 이 내용을 글로 정리하려고 했지만, 임시저장만 해둔 채로 어딘가로 사라져 버린 것 같다. 그래서 이번에는 기억을 다시 곱씹으며, 처음 이수 처리 기능을 설계했던 과정부터2차년도 유지보수를 거치며 변경된 내용까지 정리해보려고 한다. 요구사항의 시작“학생이 강의 전체 100% 중 80%를 수강하면 자동으로 이수 처리되게 해주세요.” 하지만 이 한 문장 안에는 생각보다 많은 결정 포인트가 숨어 있었다. 당시에는 기획자가 따로 없었고, 이수 처리 기준과 방식에 대한 모든 결정은 함께 개발하던 동료 개발자들과 직접 설계해야 했다.어떻게 설계해야 할까? 강의 재생 시간을 어떤 기준으로 계산할지, 그리고 이수 처리 시점을 언제로 볼 것인지..
벌써 2년차 개발자가 되어간다.24년 1월부터 시작해서 지금까지 프론트엔드 개발자로 달려왔다.운이 좋게도, 좋은 동료들을 만나 프로젝트 구조부터 어떤 기준으로 기술을 선택해야 하는지까지 많은 것들을 배웠다. 2024년에는 동료들에게 민폐를 끼치고 싶지 않아 퇴근하고 집에 와서도, 개발 중에 해결하지 못했던 문제들을 붙잡고 머리를 싸매곤 했다. 그 과정에서 실력 차이가 나를 괴롭히기도 했지만, 결국 성장의 발판이 되었다. 끊임없이 완수해야 하는 프로젝트가 있었고, 중간에 파견도 다녀오며 시간은 속절없이 빠르게 흘러갔다.그 흐름 속에서 개발 속도와 이해도는 분명 올라갔지만, 잘 나아가고 있는지에 대한 의문은 스멀스멀 올라오곤 했다. 나는 어떤 개발자가 되고 싶었을까. 나는 단순히 기능을 구현하는 사람이 아니..
들어가며 새로 알게 된 지식으로 오랜만에 글을 써보려고 한다.프로젝트를 진행하면서 신청폼을 구현하고 있는 와중에 하나의 피드백이 들어왔다.신청서에서 뒤로가기를 눌렀을 때 Prompt 창을 띄워 사용자에게 메세지를 띄워주는 것 처럼 헤더에 있는 로고, 대메뉴, 마이페이지를 눌렀을 때도 같은 Prompt 창을 띄워줄 수 있는지 말이다! 처음에는 사용자가 뒤로가기, 새로고침을 했을때만 페이지 이동을 차단하도록 막아놨었는데 헤더에 있는 무언가를 눌렀을 때 이동을 막는 것은 처음 시도해봐서 이것저것 시도해보다 useBlocker 라는 훅을 발견했다!중구난방인 방법들을 헤매다 적용에 성공했다. react-router-dom v6 화면 이탈 프롬프트를 만들기위해서 react-router-dom 의 최신버전으로 유지..
들어가며프로젝트를 진행하면서 리스트 순서를 바꾸는 기능이 필요했다. 리스트 순서를 변경하는 라이브러리는 react-beautiful-dnd 와 react-dnd 두 가지가 있었다.처음에는 react-beautiful-dnd 를 사용해서 테스트를 해보다가 곧 종료된다는 이야기가 있어서, 주말간에 react-dnd 를 새로 설치해 테스트 해보았다!react-beautiful-dnd 를 적용했을 때 애니메이션이 미리 정의되어 있어서 좀 더 유연한 느낌이지만 용량이 react-dnd 보다 크다.반면에 react-dnd 는 hover 중일 때 순서가 변경되는 애니메이션이나 위치 변경을 직접 정의해야해 처음 적용시킬 때 살짝 어려운 편이다. 설치하기# react-dnd를 사용하기 위해 필요한 라이브러리 instal..
들어가며 프론트단을 개발하면서 데이터를 post 해야하는 상황이 항상 생긴다. 이번에는 유저가 파일과 텍스트를 올렸을 때 그 안의 내용을 post 하는 상황이었다. formData를 처음 써보는거라 많은 고민을 했다. 그리고 백앤드 개발자 분에게 전송이 제대로 되었는지 계속 물어봐야해서 좀 미안하기도 했다.. 아무튼, formData로 데이터 post 하는법을 알아보자~! 본문 먼저 폼을 만들어준다. 나는 유저가 설명을 입력하고 파일을 업로드하도록 만들었다. 제출! 여기서 textarea에 받은 value 값과 input을 이용해 올린 파일이 데이터로 전송될 것이다. 처음에는 리액트쿼리를 이용하지 않고 짰다가 리액트 쿼리를 이용하면 좀 더 간편하게 보여진다고 해서 리액트 쿼리를 이용했다. 리액트 쿼리를 ..
들어가며, 회사에서 디자인 시안에 따라 개발을 하던 중, 탭 메뉴를 눌렀을 때 background-image를 다르게 보여줘야 했다. 컴포넌트에 배경이미지를 적용하면 컴포넌트 내, 즉 컴포넌트 크기만큼만 사용할 수 있기 때문에 전체너비를 다 차지하지 못한다. 어떻게 해야할 지 고민을 하던 와중, 탭을 눌렀을 때 변하는 상태에 따라서 배경이미지 css를 조절하면 어떨까라는 생각에 도달했다. 본문 먼저 가장 부모 컴포넌트를 만들어준다. 가장 바깥 부모에서 상태관리를 해준 이유는 가장 바깥 컴포넌트에 배경이미지를 적용해야하기 때문이다. 위에서 말했듯이, 전체 너비에 배경이미지를 적용하기 위해선 만들어낸 컴포넌트가 아닌 가장 바깥 컴포넌트에 적용한다. // App.jsx import React, { useSta..
들어가며, react-responsive 라이브러리를 사용해 반응형 웹을 만들며 여러가지 테스트를 해봤다. 타입스크립트를 사용했기 때문에 타입 지정을 해줘야 했다. 타입을 지정하는 방법 중에 interface와 type이 있는데 두 가지의 정확한 차이점을 알고 정리해놓으려고 한다. 본론 function Pc({ children }) { const isPc = useMediaQuery({ query: '(min-width: 768px)', }); return {isPc && children}; } react-responsive 라이브러리 내 useMediaQuery를 사용했다. PC 버전과 Mobile 버전일 때를 나눠 만드려고 했으며, children을 통해 값을 받아오도록 코드를 짰다. return {..
들어가며, 리액트로 반응형 웹을 만들기 위해 프로젝트 초기설정을 하고 있던 와중, 정보가 너무나 많아서 한 번에 정리하고 나중에 다시 보기 위해 글을 써서 정리해두려고 한다. 예전에 Vite로 스캐폴딩하는 법은 써놨으니 Vite로 설정하는 방법은 맨 아래 추가하겠다. 본론 일단 난 CRA를 통해 프로젝트를 만들었고 여기에 typescript 와 eslint, prettier를 설치할 것이다. 1. CRA + typescript 설치하기 npx create-react-app --template typescript 이렇게 프로젝트를 만들어주면 루트에 tsconfig.json 파일이 생긴다. 이때, "baseUrl" : "./src" 코드를 추가해준다. 추가해주는 이유는 기본 절대 경로를 사전에 설정해 추후 ..
들어가며, react로 반응형 웹을 만들어 보려고 cra를 이용해 리액트 프로젝트를 시작했다. 타입스크립트와 기본적인 것들을 설치했는데 이런 경고가 장황하게 떴다. 대충 바벨에 관련해서 말하는 것 같았다. 경고문구 발생 해당 경고 문구! One of your dependencies, babel-preset-react-app, is importing the "@babel/plugin-proposal-private-property-in-object" package without declaring it in its dependencies. This is currently working because "@babel/plugin-proposal-private-property-in-object" is already..