블로그

이정환 Winterlood

한 입 크기로 잘라먹는 Next.js 사전 등록 이벤트

안녕하세요 이정환입니다 😃오늘은 돌아오는 월요일인 8월 19일(월) 출시되는 제 신규 강의한 입 크기로 잘라먹는 Next.js(15+)를 여러분께 소개 드림과 동시에오픈 직전 진행하는 사전 등록 이벤트를 안내드리려고 이렇게 글을 쓰게 되었습니다.간략하게 이벤트 부터 안내 드리고 그 이후에 강의를 소개하는 순서로 진행하겠습니다이벤트 안내사전등록 이벤트 | 한입 크기로 잘라먹는 Next.js8월 18일(일) 자정까지 신청하실 수 있습니다.신청해 주신 모든 분들에게 50%(반값) 할인 쿠폰을 지급해드립니다.추첨을 통해 50분께는 100%(무료) 쿠폰을 지급해드립니다.히든 이벤트 참가 방법을 안내해드립니다. 강의 소개한입 시리즈의 3번째 강의 한 입 크기로 잘라먹는 Next.js는약 15시간의 분량으로 Page Router부터 App Router 버전까지 Next.js의 모든 개념을 자세히 살펴보는 강의입니다.강의 특징특징 1. 직관적인 애니메이션 시각자료!Next.js는 복잡한 매커니즘을 갖는 기능이 많은 편입니다.따라서 쉬운 이해를 위해 애니메이션을 활용한 직관적인 시각자료를 준비했습니다!특징 2. 2배속으로 들어도 다 들리는 딕션과 발성!오랜 시간 제 목소리를 들으셔야 하는 만큼 좋은 발성과 딕션을 위해 항상 노력하고 있습니다.이를 위해 2배속으로 재생해도 다 알아 들으실 수 있게끔 강의를 제작했습니다.한번 들어보세요! 아래는 2배속으로 재생되는 한입 Next 소개 영상입니다.https://www.youtube.com/watch?v=bOpc-HU-v3Y커리큘럼 소개🌱 Section 1. Next.js를 소개합니다기술을 잘 이해하려면 그것이 어떤 배경에서 탄생했는지 알 필요가 있습니다.1섹션에서는 본격적인 학습에 앞서 Next.js라는 기술은 무엇인지오늘날 왜 이렇게 많은 관심을 받고 있는지 살펴봅니다.🌱 Section2. Page Router 핵심 정리(선택 수강) 프로젝트와 함께 Next.js 출시 초기부터 제공된 Page Router에 대해 빠르게 살펴봅니다.동시에 Page Router에 어떠한 불편함과 기술적 한계점 들이 있는지도 함께 살펴봅니다.🌱 Section 3. App Router 시작하기화제의 중심! App Router에 대해 살펴봅니다.App Router란 무엇인지, 어떤 기술적 차이가 있는지 알아보며 기본적인 사용법에 대해서도 함께 살펴봅니다.🌱 Section 4. 데이터 페칭서버 컴포넌트를 활용한 데이터 페칭에 대해 살펴봅니다.더불어 Next에서 제공하는 다양한 캐싱(데이터 캐시, 리퀘스트 메모이제이션)에 대해서도 함께 살펴봅니다.🌱 Section 5. 페이지 캐싱App Router 버전의 페이지 캐싱인 풀 라우트 캐시와 클라이언트 라우터 캐시에 대해 자세히 살펴봅니다.더불어 페이지의 캐싱 옵션을 강제로 설정하는 라우트 세그먼트 옵션에 대해서도 추가로 살펴봅니다🌱 Section 6. 스트리밍 & 에러 핸들링페이지에서 빠르게 준비되는 부분부터 바로 렌더링 하도록 도와주는 스트리밍에 대해 살펴봅니다.Loading 파일을 이용한 방식과 Suspense를 이용한 두가지 방식을 모두 살펴봅니다.또한 Error 파일을 이용한 에러 핸들링 및 페이지 복구 방법에 대해서도 살펴봅니다.🌱 Section 7. 서버 액션공개당시 뜨거운 반응을 불러일으킨 서버액션에 대해 살펴봅니다.서버액션을 이용해 데이터를 추가하거나 삭제하며 로딩 상태와 에러 상태를 처리하는 방법까지 살펴봅니다.🌱 Section 8. 고급 라우팅 패턴(패럴랠, 인터셉팅)App Router에서 새롭게 제공되는 패럴랠(병렬) 라우트와 인터셉팅(가로채기) 라우트에 대해 살펴봅니다.이를 통해 페이지 이동시에 사용자의 탐색을 방해하지 않도록 특정 페이지를 모달로 보여주는 기능을 구현합니다.🌱 Section 9. 최적화와 배포이미지, 메타데이터, 페이지, 리전 등의 최적화 방법을 살펴봅니다.최적화 된 프로젝트를 Vercel에 배포하고 한번 더 성능을 개선하는 작업을 진행합니다.닫는 말마지막으로 신규 강의를 끝까지 마무리 할 수 있도록 계속해서 응원해주신제 기존 강의의 수강생 분들 그리고 주변 지인 분들께 모두 감사드립니다.또 이 글을 보고 관심을 가져주신 모든 벨로그 여러분께도 감사드립니다.사전등록 이벤트 | 한입 크기로 잘라먹는 Next.js

프론트엔드Nextjs넥스트NextAppRouterNext13

이정환 Winterlood

한입 FE 완강 챌린지 2기를 모집합니다

🏃 시작부터 완강까지! 함께합니다.한입 FE 챌린지는 수강생 여러분들의 완강을 도와드리고자 하는 목적으로 기획되었습니다.매일 매일(일요일 및 공휴일 제외) 조금씩 강의를 완강하실 수 있도록 진도표를 제공해드리며당일 배운 내용을 바로 복습하실 수 있도록 매일 미션도 함께 제공해 드립니다.미션 검사도 당연히 제공됩니다 🫡 챌린지 강의 목록한입 FE 챌린지 2기는 다음 2개의 강의로 진행됩니다.한 입 크기로 잘라먹는 Next.js  한 번에 끝내는 자바스크립트: 바닐라 자바스크립트로 SPA 개발까지자바스크립트 학습을 염두에 두셨던 분들이라면 “한 번에 끝내는 자바스크립트” 챌린지에Next.js 학습을 염두에 두셨던 분들이라면 “한 입 크기로 잘라먹는 Next.js”에 참여하시는걸 추천드립니다. 상세 안내참여 혜택참여 리워드참가하시기만 해도 받으실 수 있는 리워드입니다.완강 의지를 불태우기 위한 특별 강의 할인 쿠폰을 제공합니다. (미 구매자 한정)완주 리워드모든 미션을 완료해야 받을 수 있는 리워드입니다.한입 FE 멘토들의 다른 강의 할인 쿠폰을 제공합니다.향후 챌린지 개설시 프리패스로 참여하실 수 있습니다.기간 및 일정모집 기간 :09월 1일 ~ 09월 07일(토) 자정까지활동 기간 :한 번에 끝내는 자바스크립트 : 09.09(월) ~ 09.27(금), 전체 기간 3주, 미션 수행일 14일한 입 크기로 잘라먹는 Next.js : 09.09(월) ~ 10.05(토), 전체 기간 4주, 미션 수행일 20일매주 일요일, 공휴일(추석 연휴 기간 포함)에는 쉽니다 😴활동 내용진도표에 맞춰 강의 수강하기하나의 강의를 선택해 완강합니다.매일 매일 체계적으로 수강하실 수 있도록 강의별 진도표를 제공합니다.커뮤니티를 통해 매일 인증합니다.퀴즈 및 과제 수행하기당일 배운 내용을 복습할 수 있는 퀴즈(or 과제)를 매일 제공합니다.커뮤니티를 통해 매일 인증합니다.커뮤니티에서 지식&경험 공유하기챌린지 참여자분들과 함께 한입 FE Discord 채널에서 소통합니다.미션 제출, 수강 인증, 스몰톡 등의 활동을 진행합니다.접수 방법https://bit.ly/4cJqGgZ위 링크로 신청해주세요 문의onebite.fe@gmail.com

프론트엔드챌린지스터디완강JSNext.jsJavaScriptNextjsNext

RTK 쿼리는 SSR을 하고 싶어!

서론요즘 RTK 쿼리와 함께 Nextjs에서 SSR을 적용하는데 꽤 시간을 들이고 있습니다. 물론 리액트 쿼리라는 걸출한 패키지가 존재합니다. 그런데 어쩌겠습니까, 저의 마음 속 한 켠에는 이미 RTK 쿼리에 대한 열망이 불타올랐던 겁니다!... 사실은 리덕스로 노는 와중에 찾아볼 게 있어서 문서에 들어갔다가 영업당한 것에 가깝습니다. 이 글을 작성할 동기를 제공한 리덕스 공식 문서에게 크나큰 박수를 보내주시면 감사하겠습니다.그래서 사용하는 김에 SSR까지 적용해보면 어떨까? 라는 생각을 했습니다. 그렇습니다, 여러분. 오늘 글의 주제입니다.RTK 쿼리는 외로워요SSR의 원리는 간단합니다. 클라이언트사이드에서 요청을 보내면 서버사이드에서 원래 클라이언트사이드에서 했어야 할 작업들을 대신 수행해 주는 겁니다. 그리고 그 결과가 적용된 말끔한 HTML을 응답해 줍니다.Nextjs는 이런 작업을 아주 멋지게 처리해 줄 getServerSideProps라는 함수를 제공합니다. 해야 하는 작업을 수행한 후 얻은 데이터를 페이지 컴포넌트의 props로 넣어 주는거죠.이 쯤에서 문제가 생깁니다. 우리는 props가 아닌 RTK 쿼리를 사용해야 하기 때문입니다. getServerSideProps 함수 안에서 RTK 쿼리를 디스패치하는 부분까지는 가능합니다. 그러나 클라이언트사이드의 RTK 쿼리는 서버사이드에서 무슨 일이 생겼는지 알지 못합니다. 서버사이드의 RTK 쿼리 혼자 외롭게 남아있게 되는 겁니다.그럼 어떻게 해야 할까요? 어떤 방식으로 서버사이드의 RTK 쿼리 스토어를 클라이언트사이드로 전달해 줄 수 있을까요?next-redux-wrappernext-redux-wrapper 패키지가 나설 차례입니다. 이 패키지는 서버사이드의 스토어를 클라이언트사이드 스토어에 덮어 씌워 줍니다. 서버사이드에서 실행된 RTK 쿼리를 클라이언트사이드로 가져오는 게 가능해진다는 의미이기도 합니다.store.tsnext-redux-wrapper를 적용하기 위해 약간의 수정이 필요합니다.// store.ts /** * configureStore를 감싸는 makeStore 함수를 작성 * @param context `next-redux-wrapper`에서 제공하는 context */ export const makeStore = (context: Context) => { return configureStore({ reducer: { something: somethingReducer, [rtkQueryApi.reducerPath]: rtkQueryApi.reducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat( rtkQueryApi.middleware, ), }); }; // makeStore 함수의 ReturnType를 가져와 타입 작성 type AppStore = ReturnType<typeof makeStore>; export type AppState = ReturnType<AppStore["getState"]>; export type AppDispatch = AppStore["dispatch"]; /** * `next-redux-wrapper`에서 제공하는 `createWrapper` 함수로 만들어진 wrapper를 export */ export const wrapper = createWrapper<AppStore>(makeStore, {debug: true}); // ^ // 작성된 makeStore 함수를 넘김다음과 같이 리덕스 스토어를 설정합니다. configureStore 함수로 만들어진 store를 바로 쓰는 대신 next-redux-wrapper 패키지에서 제공하는 createWrapper 함수로 wrapper를 만들어 사용합니다._app.tsx// _app.tsx function MyApp({ Component, pageProps }: AppProps) { return ( <Component {...pageProps} /> ); } // `store.ts`에서 생성된 wrapper로 MyApp 컴포넌트를 감쌈 export default wrapper.withRedux(MyApp)react-redux 패키지의 Provider 컴포넌트로 감싸던 기존의 방식 대신 wrapper.withRedux 함수로 MyApp 컴포넌트를 감쌉니다.좋습니다. next-redux-wrapper를 사용할 준비가 끝났습니다.SSR이제 RTK 쿼리를 서버사이드에서 사용해봅시다. 생각보다 정말 간단합니다.// store를 쓰기 위해 작성한 `wrapper`의 `getServerSideProps` 함수를 사용함 export const getServerSideProps = wrapper.getServerSideProps( (store) => async (context) => { // RTK 쿼리 디스패치 store.dispatch(rtkQueryApi.endpoints.getSomething.initiate({})); // 실행된 것이 끝날 때까지 대기 await Promise.all(cropApi.util.getRunningOperationPromises()); return { props: {}, }; } );다음과 같이 RTK 쿼리를 서버사이드에서 실행할 수 있습니다.하지만 문제가 생기게 됩니다. 클라이언트사이드의 스토어는 아무 것도 바뀌지 않았습니다. next-reudx-wrapper 패키지를 설정하는 과정에서 문제라도 생겼던 걸까요?RTK Query 설정이런, RTK Query의 api를 확인해 보니 한 가지 설정을 빠뜨렸습니다.export const rtkQueryApi = createApi({   ...   // 서버사이드에서 실행된 쿼리를 클라이언트에 hydrate   extractRehydrationInfo(action, { reducerPath }) {     if (action.type === HYDRATE) {       //                ^       //   next-redux-wrapper에서 제공          // 실행된 쿼리(reducerPath)를 리턴       return action.payload[reducerPath];     }   }   ... });HYDRATE 액션 때 서버사이드에서 실행된 쿼리를 전해주는 extractRehydrationInfo 함수를 설정해줘야 합니다.혹시 다 설정해줘야 하냐구요? 맞습니다. 서버사이드에서 실행될 예정인 쿼리와 뮤테이션을 다루는 createApi 함수는 모두 같은 설정을 해야 합니다. 안하면 쿼리와 뮤테이션들이 외로워 합니다.확인해봅시다이제 제대로 데이터가 전해졌는지 확인해봅시다.redux devtools에 들어가 액션을 살펴보세요. __NEXT_REDUX_WRAPPER_HYDRATE__ 안에 원하는 데이터가 들어 있다면 성공입니다.사용const ExampleComponent = () => { const { data } = useGetMyCropsQuery({}); return ( { data ? <div>{data.something}</div> : <div>...</div> } ) }기존과 같이 훅으로 사용합니다.TMI왜 Provider 컴포넌트를 사용하지 않나요?next-redux-wrapper가 Provider 컴포넌트의 역할을 합니다.도움이 됐나요?날씨가 추우니 손도 어는 기분이네요. 여러분들은 따뜻한 손으로 개발하고 있으시죠?그렇다고요? 좋습니다, 오늘도 즐거운 개발 되세요!References[createApi | Redux Toolkit # extractRehydrationInfo](https://redux-toolkit.js.org/rtk-query/api/createApi#extractrehydrationinfo)[Server Side Rendering | Redux Toolkit](https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering)[GitHub - kirill-konshin/next-redux-wrapper: Redux wrapper for Next.js](https://github.com/kirill-konshin/next-redux-wrapper)  

프론트엔드SSRRTKQueryReduxReduxToolkitReduxToolkitQueryNextjs

채널톡 아이콘