티스토리 뷰

✅ route.ts(라우트 API) vs. Server Actions 비교

라우트 API (route.ts) 서버 액션 (use server)

방식 HTTP 요청(예: fetch, axios)을 통해 API 엔드포인트를 호출 서버에서 직접 함수를 호출하여 실행
사용법 app/api/.../route.ts에 작성 (GET, POST, PUT, DELETE 가능) use server 키워드를 사용하여 서버 함수 실행
보안 API 호출을 통한 요청이므로 CSRF 방어 필요 클라이언트에서 직접 실행할 수 없어 CSRF 공격 걱정 없음
유연성 외부 API와의 통합이 용이 클라이언트와의 직접적인 상호작용에 적합
상태 관리 fetch 요청으로 데이터를 가져와야 함 클라이언트 컴포넌트에서 바로 실행 가능
최적화 캐싱 및 CDN을 활용할 수 있음 페이지 새로고침 없이 상태 변경 가능

🔥 route.ts(API Routes)를 사용하는 이유

1️⃣ 다른 클라이언트(모바일 앱, 외부 서비스)와 공유 가능

라우트 API는 Next.js 프론트엔드뿐만 아니라, 모바일 앱(React Native, iOS, Android)이나 다른 웹사이트에서도 API로 사용할 수 있음.
반면, 서버 액션은 Next.js 내부에서만 사용 가능.

예: route.ts를 사용하면 https://yourdomain.com/api/register와 같은 API 엔드포인트를 만들어, 모바일 앱에서도 회원가입 요청 가능.


2️⃣ RESTful API 구조를 활용 가능

✅ route.ts는 **HTTP 메서드(GET, POST, PUT, DELETE)**를 활용할 수 있어 RESTful API 패턴을 따를 수 있음.
✅ 서버 액션은 주로 POST 요청에 적합하며, RESTful API처럼 다양한 메서드를 활용하기 어려움.

예:

  • GET /api/members → 회원 목록 조회
  • POST /api/members → 회원가입
  • PUT /api/members/:id → 회원 정보 수정
  • DELETE /api/members/:id → 회원 삭제

이렇게 명확한 API 설계를 유지할 수 있음.


3️⃣ 캐싱 및 성능 최적화 가능

route.ts는 API 응답을 캐싱하거나 CDN을 활용하여 클라이언트에서 빠르게 로드할 수 있음.
서버 액션은 이런 최적화가 어려운 경우가 많음.

✅ 예: GET /api/products 요청을 캐싱하면 동일한 데이터를 빠르게 제공 가능.


4️⃣ Middleware 및 인증(Token-based, JWT 등) 적용 용이

라우트 API에서는 JWT, OAuth, 세션 인증 등의 보안 적용이 용이함.
반면, 서버 액션은 클라이언트에서 바로 실행되기 때문에 토큰을 활용한 인증이 어렵거나 제한적임.

✅ 예:

  • route.ts에서 Authorization: Bearer {token}을 검사하여 인증된 사용자만 요청 가능.
  • 서버 액션은 Next.js 내부에서만 동작하므로 이런 인증 방식과는 조금 다름.

5️⃣ CSRF 보안 문제 해결 가능

✅ API Routes(route.ts)는 외부에서 호출 가능하기 때문에 CSRF 방어 필요.
✅ 서버 액션은 Next.js 내부에서만 실행되므로 CSRF 위험이 없음.
하지만, API Routes는 CSRF 방어를 위해 CSRF 토큰, SameSite 쿠키 정책 등을 적용 가능.


🚀 결론: 언제 route.ts를 사용하고, 언제 서버 액션을 사용할까?

라우트 API(route.ts)가 적합한 경우

  • 외부 서비스(모바일 앱, 다른 웹사이트)와 API를 공유해야 할 때
  • JWT, OAuth 같은 인증 시스템을 적용해야 할 때
  • RESTful API 설계를 유지하고 싶을 때
  • HTTP 캐싱, CDN을 활용하여 성능을 최적화하고 싶을 때

서버 액션이 적합한 경우

  • Next.js 내부에서만 데이터를 처리하면 될 때
  • 클라이언트에서 서버 요청을 간단하게 처리하고 싶을 때
  • CSRF 공격이 걱정되지 않는 경우
  • 상태를 즉시 업데이트해야 할 때

👉 회원가입(register), 로그인(login), 사용자 프로필(profile) 조회 등의 API는 route.ts를 활용하는 것이 더 좋음.
👉 간단한 데이터 업데이트(Form 제출)라면 서버 액션(use server)을 활용하는 것이 편리함.


✅ 추천하는 구조 (회원가입 예제)

회원가입을 Next.js에서 구현할 때 이런 구조를 추천합니다.

1️⃣ route.ts를 사용한 API (회원가입)

📌 /app/api/register/route.ts

"use server";

import { NextResponse } from "next/server";
import mysql from "mysql2/promise";
import { hash } from "bcryptjs";

export async function POST(request: Request) {
  const { email, password, name } = await request.json();
  if (!email || !password) return NextResponse.json({ error: "필수값 누락" }, { status: 400 });

  const hashedPassword = await hash(password, 10);
  const connection = await mysql.createConnection({
    host: process.env.MYSQL_HOST!,
    user: process.env.MYSQL_USER!,
    password: process.env.MYSQL_PASSWORD!,
    database: process.env.MYSQL_DATABASE!,
  });

  await connection.execute("INSERT INTO members (email, password, name) VALUES (?, ?, ?)", [email, hashedPassword, name]);
  await connection.end();

  return NextResponse.json({ message: "회원가입 성공!" }, { status: 200 });
}

2️⃣ 클라이언트에서 API 호출

📌 /app/register/page.tsx

"use client";

import { useState } from "react";

export default function RegisterPage() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const res = await fetch("/api/register", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email, password }),
    });
    const data = await res.json();
    alert(data.message);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="이메일 입력" />
      <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="비밀번호 입력" />
      <button type="submit">회원가입</button>
    </form>
  );
}

🔥 결론: 실무에서는 route.ts와 server actions을 함께 활용!

  • 회원가입, 로그인 등은 route.ts로 API 엔드포인트를 만들어 사용
  • Form 전송과 같은 간단한 데이터 처리는 server actions을 활용
728x90
반응형