본문 바로가기
FrontEnd/Next.js

Next.js에서 data를 받아오는 방식에 따른 장단점

by 위그든씨 2024. 12. 9.

Next.js에서 서버로부터 data를 받아오는 방식으로는 크게 5가지가 있다고 생각한다.

  1. 서버 컴포넌트에서의 바로 데이터 페칭
  2. api/route.ts를 활용한 Route Handlers 사용
  3. server actions를 사용
  4. SWR 사용
  5. React Query 사용

각 방식의 특징과 주의점을 우선 살펴본다

1. 서버 컴포넌트에서의 데이터 페칭

// app/page.tsx
async function getData() {
  const res = await fetch('https://api.example.com/data')
  return res.json()
}

export default async function Page() {
  const data = await getData()
  return <div>{data.title}</div>
}

이 방식을 채택한다면 SEO에 유리, 자동 캐싱, 클라이언트 번들 크기 감소 라는 장점을 가질 수 있다.

하지만 비동기 방식에 따라 데이터가 페칭 되는 동안 Suspense나 loading.tsx와 같은 것을 생성하지 않았다면 유저는 긴 시간을 기본 로딩 화면만을 보게 되므로 주의점이 필요하다. 따라서 대규모 데이터 페칭을 하는 것이라면 소수의 갯수만 초기에 받아오고 이후에는 pageParams에 따라 추가적으로 가져온다는 조작이 필요할 수 있음

( fetch 주의점 )

Next.js에서 fetch를 사용한다면 자동 캐싱이 되는 것은 서버 컴포넌트에서의 fetch만 그러할 뿐 클라이언트 단에서 사용되는 fetch는 자동 캐싱이 되지 않는다. 따라서 use client 단에서 사용되는 fetch에서 캐싱 작업이 필요하다면 직접 설정해주거나 React Query와 같은 라이브러리를 사용하는 것을 고려해야 함

2. Route Handlers 사용

// app/api/route.ts
export async function GET() {
  const data = await db.query('SELECT * FROM users')
  return Response.json(data)
}

API 엔드포인트 생성하는 것으로 커스텀 헤더/ 상태코드 처리에 용이하고 복잡한 API 로직 구현이 좋다. 

네트워크 통신이 많아질 수 있다는 단점이 있지만, 백엔드 API와의 명확한 분리가 필요하거나 미들웨어적인 처리가 필요할 때 유용.

특히 인증/인가 로직을 처리하거나, 외부 API 응답을 가공해야 할 때 활용도가 높음.

특히 CORS 에러를  route handler를 통해 서버끼리 데이터 통신하는 것으로 해결하기 편함.

이 때 주의할 점은, route handler를 서버 컴포넌트에서 fetch 할 때 경로를 /api/route.ts가 아닌 http://localhost:3000/api/route.ts와 같은 풀 주소를 입력해줘야 경로를 잡아준다. 즉 상대 경로가 아닌 절대 경로를 입력하라는 것인데, 이것은 서버 컴포넌트가 빌드 시점에 실행되는 환경이기 때문이다.

// ❌ 잘못된 방법
const data = await fetch('/api/route')

// ✅ 올바른 방법
const data = await fetch('http://localhost:3000/api/route')
// 또는
const data = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/route`)

3. server action

'use server'

export async function submitData(formData: FormData) {
  const name = formData.get('name')
  await db.users.create({ data: { name } })
}

server action 을 통해서도 데이터를 받아오는 것이 가능하지만 서버 액션같은 경우에는 기본적으로 post 처리 되어 캐싱이 안된다.

서버 사이드에서 직접 실행되므로 보안적으로 안전하기에 이는 폼 제출 처리에 특화되어 있음.

별 생가 없이 서버 액션으로 데이터를 get 하는 행위를 한다면 데이터 통신 시간 초과로 다운 되는 경우 생길 수 있음

4. SWR (클라이언트단)

const { data, error } = useSWR('/api/user', fetcher)

Vercel에서 만든 데이터 페칭 라이브러리로, React Query와 비슷한 목적을 가지고 있음.

  • 캐시 및 자동 재검증
  • 낙관적 UI 업데이트
  • 포커스시 재검증
  • 인터벌 폴링
  • 페이지네이션 지원

Next.js와의 통합이 자연스럽고 설정이 간단하다는 장점이 있. 실시간성이 중요한 데이터를 다룰 때 특히 유용

5. React Query 사용(클라이언트단)

const { data, isLoading } = useQuery({
  queryKey: ['todos'],
  queryFn: () => fetch('/api/todos').then(res => res.json())
})

가장 강력한 클라이언트 상태 관리 도구

  • 강력한 캐싱 메커니즘
  • 백그라운드 업데이트
  • 무한 스크롤/페이지네이션
  • 낙관적 업데이트
  • 재시도 로직
  • 복잡한 종속성 관리

SWR보다 더 많은 기능을 제공하지만, 그만큼 설정이 복잡

 

====

 

  • 정적이고 SEO가 중요한 데이터 → 서버 컴포넌트
  • API 중간 처리가 필요한 경우 → Route Handlers
  • 폼 제출과 같은 데이터 변경 작업 → Server Actions
  • 간단한 실시간 데이터 → SWR
  • 복잡한 데이터 관리가 필요한 경우 → React Query