개발자
안녕하세요. 선배 개발자 선생님들. 오늘도 한 단계 성장하기 위해 질문을 남겨봅니다. 저는 NextJs, App router 방식으로 코드를 구현중이며, 서버 상태는 React-Query로 상태값을 관리하고 있었습니다. 왜 리액트 쿼리를 사용했는가? why? 1. Optimistic update, 무한스크롤에 대해 공부하고 적용해보고 싶었습니다. 2. 클라이언트 상태, 서버 상태를 나눈다는 개념이 너무 좋아서 서버 상태는 React-Query로 다뤘습니다. 3. statleTime, gcTime을 조정하여 캐싱기능이 좋았습니다. 갑자기 문득 나는 NextJS를 잘 쓰고 있는건가? 리액트랑 폴더 구조 말고는 다른게 없는거 아닌가? 라는 생각이 들었고, NextJs의 기능을 최대한 활용하고 나머지 불편한 부분이 생긴다면 외부 라이브러리를 사용하자! 라는 생각이 들었습니다. 그래서 저는 React-Query로 상태를 관리하던걸 NextJs의 확장 fetch로 바꿀려고 합니다. Optimistic update, 무한스크롤 기능을 제외하고 나머지 모든 서버 상태는 확장 fetch로 바꿀려고 합니다. 페이지네이션 페이지네이션 처럼 사용자와 상호 작용하는 부분, 즉 동적으로 데이터를 받아오게 하기 위해 url을 변경한 뒤, [id]/page.tsx에서 param로 받던지 혹은 header()를 통해 params를 받아서 처리를 할 수 있다고 생각하고, 저는 header()로 params를 받아서 처리를 했습니다. 모달에서의 페이지네이션 그런데 문제는 모달을 띄우고, 모달 내부에서 페이지네이션이 있는 경우 어떻게 데이터를 동적으로 받아오는지 고민을 해봐도 방법이 없는 것 같습니다. 1. 모달에서 다음 페이지 클릭시 url을 변경한다. -> 안해봤지만 동작을 할 수 있더라도 뭔가 느낌적으로 아닌 것 같습니다. 2. 클라이언트 컴포넌트에서 상태값을 서버 컴포넌트로 전달한다 -> 불가능 궁금한 점 1. 모달 내부에서 페이지네이션을 처리할때 url을 변경해서 서버 컴포넌트에서 확장 fetch로 데이터를 관리하는 게 적절할까요? 2. 모달 내부에서는 페이지네이션을 처리할 때는 react-query로 데이터를 관리하는 걸 확장 fetch로 바꿀 수 없는 건가요?? 바꿀 필요가 없는 건가요? 3. 더 좋은 방법이 있는 건가요?
답변 2
1. 방법은 자유입니다. 뭐가 정답이고 틀리고는 없습니다. 뭔가 서버컴포넌트로만 하고 싶어 하시는듯 합니다. 제 추측이 맞다면 Next의 Link 컴포넌트로 페이지 클릭시 정보를 넘기세요. 그 후 서버 페이지에 자동으로 넘어오는 searchParam을 사용 하세요. 2. 본인 마음입니다. 상관 없습니다. 3. server action을 쓰셔도 원하는 동작을 처리할 수 있습니다.
안녕하세요. 약간 개념적으로 이해가 필요할 것 같아 답변 전달드립니다. 모달 내부에서 페이지네이션을 처리하는 가장 일반적인 방법은 클라이언트 컴포넌트에서 상태를 관리하는 것입니다. Next.js에서 제공하는 서버 컴포넌트는 서버에서 데이터를 가져와 정적으로 페이지에 렌더링할 때 매우 유용하지만, 동적인 사용자 상호작용이 필요한 경우 클라이언트 측에서 상태를 관리하는 것이 더 적합합니다. React Query와 같은 상태 관리 라이브러리에서 React Query를 사용하여 서버 데이터를 비동기적으로 가져오고, 캐싱 및 상태 관리를 수행할 수 있습니다. 서버 컴포넌트와 클라이언트 컴포넌트의 적절한 조합에서 초기 데이터를 가져오고, 클라이언트 컴포넌트에서 그 데이터를 기반으로 동적인 UI를 처리하는 방식이 좋은 균형이 될 수 있습니다. 결론적으로, 모달 내부의 페이지네이션과 같은 동적인 인터페이스에서는 클라이언트 측에서 상태를 관리하는 것이 더 적합하며, 서버 컴포넌트를 통해 초기 데이터를 가져오는 구조를 사용하는 것이 좋습니다. React Query와 같은 도구를 사용하여 서버 상태를 관리하는 것이 적절할 것으로 보입니다. 아래의 코드를 보면서 이해 하시길 바랍니다. 감사합니다. 화이팅.😎😎 예시) 1. 서버 컴포넌트에서 초기 데이터 가져오기 // app/posts/page.tsx import { Suspense } from 'react'; import PostsList from './PostsList'; export default function PostsPage() { return ( <div> <h1>Posts</h1> <Suspense fallback={<div>Loading...</div>}> <PostsList /> </Suspense> </div> ); } 2. 클라이언트 컴포넌트에서 React Query로 데이터 패칭 및 모달 구현 // app/posts/PostsList.tsx 'use client'; import { useQuery } from 'react-query'; import { useState } from 'react'; import Modal from './Modal'; async function fetchPosts(page: number) { const response = await fetch(`/api/posts?page=${page}`); return response.json(); } export default function PostsList() { const [page, setPage] = useState(1); const { data, isLoading, error } = useQuery(['posts', page], () => fetchPosts(page)); if (isLoading) return <div>Loading...</div>; if (error) return <div>Error loading posts</div>; return ( <div> <ul> {data.posts.map((post: any) => ( <li key={post.id}>{post.title}</li> ))} </ul> <button onClick={() => setPage((prev) => prev + 1)}>Next Page</button> {/* 모달을 열 수 있는 버튼 */} <button onClick={() => setModalOpen(true)}>Open Modal</button> {/* 모달 내부에서 페이지네이션 처리 */} <Modal isOpen={modalOpen} onClose={() => setModalOpen(false)}> <ul> {data.posts.map((post: any) => ( <li key={post.id}>{post.title}</li> ))} </ul> <button onClick={() => setPage((prev) => prev + 1)}>Next Page in Modal</button> </Modal> </div> ); } 3. 모달 컴포넌트 구현 // app/posts/Modal.tsx import React from 'react'; interface ModalProps { isOpen: boolean; onClose: () => void; children: React.ReactNode; } export default function Modal({ isOpen, onClose, children }: ModalProps) { if (!isOpen) return null; return ( <div className="modal"> <div className="modal-content"> <button onClick={onClose}>Close</button> {children} </div> </div> ); } 4. API 라우트 예시 // pages/api/posts.ts export default function handler(req, res) { const { page } = req.query; const postsPerPage = 10; const allPosts = [ /* 데이터 배열 */ ]; // 실제로는 데이터베이스나 외부 API에서 가져온 데이터일 것임 const start = (page - 1) * postsPerPage; const end = start + postsPerPage; const posts = allPosts.slice(start, end); res.status(200).json({ posts }); }
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
커리어리 AI 봇
GPT가 달아주는 답변입니다.
2024년 08월 09일
Next.js의 server components와 확장 fetch 기능을 이용하시려는 접근은 매우 훌륭합니다. 그러나 아쉽게도 Next.js의 서버 컴포넌트는 현재 실험 단계에 있습니다. 그래서 안정화되지 않은 기능들이 많고, 이로 인해 제대로 작동하지 않는 경우가 있을 수 있습니다. 1. 모달에서의 페이지네이션: 일반적으로 URL 변경을 통한 페이지네이션 처리를 권장하지만, 만약 모달 내부에서 페이지네이션을 진행하고자 한다면 클라이언트 사이드 렌더링(CSR) 방식을 사용해야할 가능성이 큽니다. 이런 경우 React-Query 같은 도구를 계속 사용하여 상태 관리를 진행하는 것이 효과적일 수 있습니다. 2. 서버 컴포넌트에서 클라이언트 컴포넌트로 상태 전달: 현재 Next.js의 서버 컴포넌트는 CSR과 다른 접근 방식을 가지고 있어서, 클라이언트와 서버 간에 상태를 직접적으로 공유하는 것은 어렵습니다. 3. 좋은 방법: - React-Query 및 SWR과 같은 데이터 패칭 라이브러리 사용: 이 라이브러리 들은 내부적으로 자체 캐싱 및 무효화 메커니즘을 가지고 있어 데이터 패칭 관련 로직을 간단하게 만들 수 있습니다. - 모달의 페이지네이션에는 클라이언트 사이드 렌더링 사용: Next.js의 서버 컴포넌트가 아직 실험 단계라는 점, 그리고 모달에서 동적으로 페이지네이션을 처리하는 경우 URL 변경 없이 상태 변화에 따른 렌더링 갱신을 해야하기 때문입니다. 결론적으로, 서버 컴포넌트에서 동적인 API 요청을 처리하는 것은 쉽지 않아보입니다. 현재 Next.js의 서버 컴포넌트 기능이 안정화 될 때까지 기다리거나, React-Query 등의 외부 라이브러리를 계속 이용하는 것을 추천드립니다.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!