| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- 차이점
- js
- CSS
- TS
- 책으론 원리만
- Mac
- axios
- 다시 홧팅
- git
- git flow finish
- 개발일지
- freecodecamp
- Next.js
- 바닐라JS
- 실무는 공식문서로
- 서버 컴포넌트
- git flow start
- JavaScript
- 클라이언트 컴포넌트
- Main
- jQuery
- 백준
- fetch pull 차이
- HTML
- 공부할 거 넘많다~
- 끝까지 잘 마무리하기
- api 라우트
- 힘들었던 한주
- AJAX
- javascript30
- Today
- Total
다다의 개발일지 6v6
[Next.js] 서버 vs 클라이언트 컴포넌트에서 - fetch, axios로 API 호출 차이점 본문
클라이언트에서 fetch 요청 vs 서버에서 fetch 요청
Next.js에서는 fetch()를 클라이언트와 서버에서 모두 사용할 수 있음. 하지만 실행되는 환경이 다르기 때문에 성능과 보안 측면에서 차이가 있음.
📌 핵심 차이점 요약
| 클라이언트에서 fetch() 요청 | 서버에서 fetch() 요청 | |
| 실행 위치 | 브라우저 (클라이언트) | Next.js 서버 (Node.js) |
| 요청 횟수 | 사용자가 페이지 방문할 때마다 요청 | 서버에서 한 번 요청 후 결과 반환 |
| 보안 | API 키가 브라우저에서 노출될 수 있음 | API 키를 숨길 수 있음 |
| 성능 | 네트워크 요청이 많아질 수 있음 | 서버에서 미리 데이터 가져와서 빠름 |
| SEO | CSR 방식이므로 SEO 불리함 | SSR로 SEO 최적화 가능 |
1. 클라이언트에서 fetch 요청하는 방식
📌 클라이언트에서 실행되는 fetch 요청은 브라우저에서 직접 API에 요청을 보냄.
즉, 사용자 인터랙션이 있을 때 요청이 발생함.
- useEffect 또는 이벤트 핸들러에서 실행됨
- 페이지가 렌더링된 후 데이터가 로드됨 → 로딩 화면을 따로 처리해야 함
- API 키가 브라우저에 노출될 수 있으므로 보안상 주의 필요
✅ 클라이언트에서 fetch 요청 예제
"use client"; // 클라이언트 컴포넌트
import { useState, useEffect } from "react";
export default function ClientFetchExample() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => setData(data));
}, []);
return (
<div>
<h2>클라이언트에서 API 요청</h2>
{data ? (
<ul>
{data.map((user: any) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
) : (
<p>Loading...</p>
)}
</div>
);
}
✅ 클라이언트 fetch 요청의 특징
- useEffect를 사용하여 페이지가 로드된 후 API 요청 실행
-> 브라우저에서 실행되기 때문에 useEffect, onClick 이벤트 같은 곳에서 호출됨 - 브라우저에서 직접 요청 → 사용자가 방문할 때마다 API 호출
- API 응답이 올 때까지 로딩 화면이 표시될 수 있음
- API 요청이 많아질 경우, 클라이언트 성능 저하 가능
- SEO가 불리함 (페이지가 클라이언트에서 렌더링되므로 검색 엔진이 내용을 크롤링하기 어려움 : 검색 엔진은 api 응답을 기다리지 않으므로)
- 보안 문제가 있음 (API 키가 공개될 가능성이 있음)
2. 서버에서 fetch 요청하는 방식
📌 서버에서 실행되는 fetch 요청은 Next.js의 API 라우트 또는 서버 컴포넌트에서 실행됨.
즉, 클라이언트가 요청하기 전에 서버에서 데이터를 미리 가져와 렌더링할 수 있음.
✅ 서버에서 fetch 요청 예제 (서버 컴포넌트 사용)
// app/components/ServerFetchExample.tsx (서버 컴포넌트)
async function getUsers() {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await res.json();
return users;
}
export default async function ServerFetchExample() {
const users = await getUsers();
return (
<div>
<h2>서버에서 API 요청</h2>
<ul>
{users.map((user: any) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
✅ 서버 fetch 요청의 특징
- fetch()를 서버에서 실행 → 클라이언트는 HTML만 전달받음 -> 클라이언트 부담을 줄임.
- API 응답을 서버에서 미리 받아오기 때문에 초기 로딩 시간이 짧음
- SEO 최적화 가능 (페이지 로딩 전에 데이터가 준비됨, 검색 엔진이 완성된 HTML을 읽을 수 있음)
- API 키를 숨길 수 있음 (브라우저에서 직접 요청하지 않으므로)
- 데이터를 캐싱할 수 있음 (fetch의 next: { revalidate: 60 } 옵션 사용 가능)
- Next.js가 자동으로 처리
- _rsc 쿼리 파라미터가 붙음 → ?_rsc=XXXX
- 브라우저에서 직접 호출한 게 아니라, React Server Components의 렌더링 과정에서 호출됨
- 예시:
GET /user/create?_rsc=1q6r0
+ API 라우트 (Next.js 서버 API)에서 axios 사용하기 ( fetch도 같음.)
📌 API 키 보호 및 보안이 중요한 경우, Next.js API 라우트를 이용하여 axios 요청을 서버에서 실행하는 것이 좋음.
👉 이 방법을 사용하면 클라이언트에서 직접 API 요청하지 않고, Next.js 서버를 거쳐 API를 호출할 수 있음.
✅ API 라우트에서 axios 요청 예제
// app/api/users/route.ts (Next.js 서버 API)
import { NextResponse } from "next/server";
import axios from "axios";
export async function GET() {
try {
const res = await axios.get("https://jsonplaceholder.typicode.com/users");
return NextResponse.json(res.data);
} catch (error) {
return NextResponse.json({ message: "API 요청 실패" }, { status: 500 });
}
}
👉 이제 클라이언트에서는 이 API를 호출하면 됨!
✅ 클라이언트에서 Next.js API 호출하기
"use client";
import { useState, useEffect } from "react";
import axios from "axios";
export default function ClientAxiosWithAPI() {
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get("/api/users") // Next.js 서버 API 호출
.then((res) => setUsers(res.data))
.catch((error) => console.error("API 요청 실패:", error));
}, []);
return (
<div>
<h2>Next.js API 라우트 사용</h2>
<ul>
{users.map((user: any) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
✅ API 라우트를 사용하면 좋은 경우
✔ API 키 보호 가능 (클라이언트에서 직접 외부 API 호출 안 함)
✔ 클라이언트 요청을 Next.js 서버가 처리하여 보안 강화 가능
✔ 클라이언트에서는 내부 API(/api/users)를 호출하므로 더 간편함
✔ API 응답을 캐싱하여 성능 최적화 가능
| 서버 컴포넌트 | axios 클라이언트 컴포넌트 | axios API 라우트 (Next.js 서버 AP) | |
| 실행 위치 | Next.js 서버 | 브라우저 (클라이언트) | Next.js 서버 (백엔드 API) |
| 데이터 요청 시점 | 서버에서 미리 요청 | 클라이언트에서 페이지 로드 후 요청 | API 호출 시 요청 |
| API 키 보호 | ✅ 보호됨 | ❌ 노출 위험 있음 | ✅ 보호됨 |
| SEO | ✅ 가능 (HTML로 응답) | ❌ 불가능 (CSR 방식) | ❌ 불가능 (CSR 방식) |
| 초기 로딩 속도 | ✅ 빠름 (미리 데이터 준비) | ❌ 느림 (로딩 필요) | ❌ 느림 (CSR) |
| 상태 관리 | ❌ 불가능 (useState X) | ✅ 가능 (useState O) | ❌ 불가능 |
- 서버 컴포넌트에서 axios를 사용하면 SEO 최적화 + 보안 + 빠른 렌더링 가능
- 클라이언트 컴포넌트에서는 상태 관리(useState) 및 사용자 이벤트 처리 가능
- API 키 보호가 필요하면 API 라우트(/api)를 사용하여 보안 강화 가능
3. 클라이언트 vs 서버에서 API 요청 방식 비교 (fetch 외 다른 방법 포함)
| 실행 위치 | 주요 특징 | SEO | 보안 | |
| 클라이언트 fetch 요청 | 브라우저 | 사용자가 방문할 때마다 요청, useEffect 필요 | ❌ 불리 | ❌ API 키 노출 가능 |
| 서버 fetch 요청 | Next.js 서버 | 미리 데이터를 받아 클라이언트로 전달 | ✅ 유리 | ✅ API 키 보호 가능 |
| getServerSideProps (SSR) | Next.js 서버 | 요청 시마다 API 호출 후 HTML 생성 | ✅ 유리 | ✅ API 키 보호 가능 |
| getStaticProps (SSG) | Next.js 서버 | 빌드 시 한 번 API 호출 후 정적 HTML 생성 | ✅ 매우 유리 | ✅ API 키 보호 가능 |
| API 라우트 (/api 경로) | Next.js 서버 | API 프록시 역할, 백엔드처럼 사용 가능 | - | ✅ API 키 보호 가능 |
4. API 요청 방식별 사용하면 좋은 상황
✅ 클라이언트에서 fetch() 요청이 적합한 경우
- 사용자 상호작용 이후에 데이터를 가져올 때 (예: 버튼 클릭 시 API 호출)
- 실시간 데이터가 필요할 때 (예: 실시간 채팅, 주식 데이터 등)
- SEO가 필요 없는 경우 (예: 로그인 후 보여주는 대시보드)
✅ 서버에서 fetch() 요청이 적합한 경우
- 초기 페이지 로딩 속도를 최적화하고 싶을 때
- SEO가 중요한 페이지 (블로그, 상품 상세 페이지 등)
- API 요청을 클라이언트에서 직접 수행하지 않고 보호하고 싶을 때
✅ API 라우트 (Next.js /api)가 적합한 경우
- 백엔드 서버 역할을 하고 싶을 때
- API 키를 보호하고 싶을 때
- 클라이언트와 백엔드 간 데이터 변환이 필요할 때
5. 서버 fetch를 더 최적화하는 방법
Next.js는 서버 컴포넌트의 fetch 요청을 자동으로 캐싱한다.
👉 fetch()를 next: { revalidate } 옵션과 함께 사용하면 캐싱을 조절 가능!
✅ fetch 캐싱 예제
async function getUsers() {
const res = await fetch("https://jsonplaceholder.typicode.com/users", {
next: { revalidate: 60 }, // 60초 동안 캐시 유지
});
return res.json();
}
- 이렇게 하면 Next.js가 60초 동안 동일한 데이터를 캐싱하여 불필요한 API 호출을 줄일 수 있음
- 캐시를 사용하지 않고 항상 새로운 데이터를 가져오려면 { cache: "no-store" } 옵션을 사용
6. 결론
✔ 클라이언트 fetch() 요청: 사용자가 직접 브라우저에서 API 요청, 실시간 데이터가 필요할 때 적합하지만 SEO 불리하고 API 키 보안 문제 있음
✔ 서버 fetch() 요청: Next.js 서버에서 API를 미리 요청하여 최적화, SEO 최적화 가능, API 키 보호 가능
✔ API 라우트 (/api 경로 사용): Next.js를 백엔드처럼 사용 가능, API 키 보호 가능
💡 Next.js에서는 서버에서 fetch() 요청하는 것이 일반적으로 더 좋음!
하지만 사용자 상호작용이 필요한 경우에는 클라이언트에서 fetch() 요청을 사용할 수도 있음.
'Frontend > Next.js' 카테고리의 다른 글
| [Next.js] 모던 리액트 Deep Dive _ next.js 톺아보기 ( 공식문서로 공부하자.. ㅎ ) (0) | 2025.03.22 |
|---|---|
| [Next.js] 백엔드 설정하기, 서버 vs 클라이언트 컴포넌트 차이점 (0) | 2025.03.09 |
| [Next.js] Next.js에서 <a> 대신 <Link>를 사용하는 이유 ?! - SPA를 위해 (0) | 2025.03.01 |
| [Next.js] App Router - 디렉토리 기반의 라우팅! 신기하다.. (0) | 2025.03.01 |
| [Next.js] - react 기반의 풀스택 프레임워크!! 배워봅시당 (2) | 2025.03.01 |