[nextjs]앱라우트 설명/App route description

👉🏻 바로 이전 포스트의 앱 라우트 방식을 설명합니다.
This explains the app routing method from the previous post.

👉🏻 가장 최근에 도입된 라우트 방식입니다.
This is the most recently introduced routing method.

👉🏻디렉토리 구조
Directory Structure

myapp3/
└── app/                        # 1.앱라우트 / App Router
    ├── api/                    # 1)백엔드 API / BackEnd API
    │   └── guestbookapp/        
    │       └── route.js        # App Router API : /api/guestbookse
    └── guestbookapp/            # 2)프론트 앤드 / FrontEnd
        └── page.tsx            # App Router Front: /guestbookse

📁 모듈 및 데이터 정의(route.js)
Module and Data Definitions (route.js)

import { NextResponse } from 'next/server';

const guestbookData = [
  { id: 1, name: '2B', content: '니어오토마타 / Nier:Automata' },
  { id: 2, name: '9S', content: 'Next.js API App Routes.' },
];

1) next/server 모듈의 기능은 아래와 같습니다.
The functions of the next/server module are as follows.

- JSON 데이터 응답: 클라이언트 API 요청에 데이터 돌려주기 (.json())
JSON Data Response: Returning data for client API requests (.json())

- 쿠키/헤더 조작: 로그인 토큰을 심거나 보안 헤더 설정하기 (.cookies.set(), .headers.set())
Cookie/Header Manipulation: Injecting login tokens or setting security headers (.cookies.set(), .headers.set())

- 페이지 이동: 사용자를 다른 URL로 튕겨내기 (.redirect())
Page redirection: Redirecting the user to another URL (.redirect())

- 내부 경로 바꾸기: 주소창은 그대로 두고 서버 안에서만 화면 전환하기 (.rewrite())
Changing internal paths: Switching screens within the server while keeping the address bar unchanged (.rewrite())

2) 데이터베이스 대신에 배열을 사용합니다. 배포환경에서는 데이터베이스로 변경해야합니다.
An array is used instead of a database. You must switch to a database for the production environment.

📁 데이터 가져오기 / Import Data

— route.js

// GET 요청 처리 (데이터 조회)
// Handle GET requests (data retrieval)
export async function GET() {
  return NextResponse.json(guestbookData);
}

1)route.js는 Nextjs라는 서버에서 호출되어 사용하는 코드입니다. 즉 Nextjs 자체가 서버입니다.
route.js is code that is called and executed within a Next.js server environment; in other words, Next.js itself acts as the server.

2)처음에 브라우저에 접속시 guestbookData를 json형식으로 응답합니다.
When initially accessing the browser, it responds with guestbookData in JSON format.

— page.tsx

// 방명록 데이터의 타입 정의
// Define the type for guestbook data
interface GuestbookItem {
  id: number;
  name: string;
  content: string;
}
 
const [posts, setPosts] = useState<GuestbookItem[]>([]);

... 중략/Omitted ...  

const fetchPosts = async () => {
    try {
      const response = await fetch("/api/guestbookapp");
      if (!response.ok) throw new Error("데이터를 가져오는데 실패했습니다. / Failed to fetch data.");
      const data = await response.json();
      setPosts(data);
    } catch (error) {
      console.error(error);
    } finally {
      setIsLoading(false);
    }
  };

  // 페이지가 처음 켜질 때 API 호출하기
  // Call the API when the page first loads
  useEffect(() => {
    fetchPosts();
  }, []);

1) 처음 브라우저에 http://localhost:3000/guestabookapp 접속시 서버(route.js)에 GET방식으로 접속합니다.
When you first access http://localhost:3000/guestabookapp in your browser, you connect to the server (route.js) using the GET method.

2) 이때 route.js에서 응답된 guestbookData 배열의 데이터를 가져옵니다.
At this point, the data from the guestbookData array returned by route.js is retrieved.

3) setPosts함수에 데이터를 저장합니다.
Store the data in the setPosts function.

📁 방명록 데이터 출력하기
Displaying Guestbook Data

— page.tsx

      {/* 방명록 목록 출력 / Guestbook Entry List */}
      <h2 className="text-2xl font-bold text-gray-800">최근 방명록 목록 / Recent Guestbook Entries</h2>
      {isLoading ? (
        <p>로딩 중/Loading...</p>
      ) : posts.length === 0 ? (
        <p>작성된 방명록이 없습니다. 첫 글을 남겨보세요! / There are no guestbook entries yet. Be the first to leave a message!</p>
      ) : (
        <ul style={{ listStyle: "none", padding: 0 }}>
          {posts.map((post) => (
            <li key={post.id} style={{ borderBottom: "1px solid #eee", padding: "15px 0" }}>
              <strong>{post.name}</strong>
              <p style={{ margin: "5px 0 0 0", color: "#555" }}>{post.content}</p>
            </li>
          ))}
        </ul>
      )}

1)setPosts로 저장된 값을 posts.map으로 데이터를 화면에 출력합니다.
The data stored via setPosts is rendered to the screen using posts.map.

2)post는 매개변수입니다.
‘post’ is a parameter.

3)posts의 배열 값을 post라는 객체 형식으로 저정되어 post.id,post.name등으로 출력할 수 있습니다.
The values ​​in the posts array are stored as post objects, allowing you to output them using properties such as post.id and post.name.


📁 데이터 저장하기
Saving data

— page.tsx

      {/* 방명록 입력 폼 / Guestbook Entry Form */}
      <form onSubmit={handleSubmit} style={{ display: "flex", flexDirection: "column", gap: "10px", margin: "20px 0" }}>
        <input
          type="text"
          placeholder="이름/Name"
          value={name}
          onChange={(e) => setName(e.target.value)}
          style={{ padding: "8px", border: "1px solid #ccc", borderRadius: "4px" }}
        />
        <textarea
          placeholder="내용을 입력하세요/Please enter your message"
          value={content}
          onChange={(e) => setContent(e.target.value)}
          style={{ padding: "8px", border: "1px solid #ccc", borderRadius: "4px", minHeight: "8px" }}
        />
        <button type="submit" style={{ padding: "10px", backgroundColor: "#dcd809", color: "white", border: "none", borderRadius: "4px", cursor: "pointer" }}>
          등록하기/Submit
        </button>
      </form>

1) submit버튼을 누르면 handleSubmit 함수가 실행됩니다.
When the submit button is clicked, the handleSubmit function is executed.

2)Input과 textarea에 입력된 값이 바뀌면 입력된 전체 데이터를 setName과 setContent함수로 업데이트합니다.
When the values ​​entered into the input and textarea change, the entire input data is updated using the setName and setContent functions.

3)setName과 setContent로 값이 바뀌면 화면의 UI를 다시 그립니다.
When the values ​​are changed via setName and setContent, the screen’s UI is redrawn.

— page.tsx

  // 새 방명록 등록하는 함수 (POST)
  // Function to register a new guestbook entry (POST)
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault(); // 새로고침 방지 / Prevent page refresh

    if (!name.trim() || !content.trim()) {
      alert("이름과 내용을 모두 입력해 주세요./Please enter both name and content.");
      return;
    }

    try {
      const response = await fetch("/api/guestbookapp", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name, content }),
      });

      if (response.ok) {
        // -- 백엔드에서 돌려준 데이터를 활용할 경우-- 
        // If you want to use the data returned from the backend
        // const newPost = await response.json();
        // setPosts((prevPosts) => [newPost, ...prevPosts]); // 새 글을 목록에 추가 / Add the new entry to the list
        // --

        // -- 백엔드에서 돌려준 데이터를 활용하지 않고 데이터를 갱신하는 경우 --
        // If you don't want to use the data returned from the backend and just update the data
        // 등록 성공 시 입력창을 비우고 목록 새로고침
        // If registration is successful, clear the input fields and refresh the list
        setName("");
        setContent("");
        fetchPosts();
      } else {
        alert("등록에 실패했습니다./Failed to register the entry.");
      }
    } catch (error) {
      console.error(error);
    }
  };

1)/api/guestbookapp 이 API(router.js)에 POST방식으로 name,content 값을 전송합니다.
Send name and content values ​​via a POST request to the /api/guestbookapp API (router.js).

2) 데이터 등록이 성공하면 fetchPosts()로 갱신된 데이터를 불러옵니다.
If the data registration is successful, the updated data is fetched using fetchPosts().

— route.js

// POST 요청 처리 (데이터 등록)
// Handle POST requests (data registration)
export async function POST(request) {
  const body = await request.json();
  const { name, content } = body;

  if (!name || !content) {
    return NextResponse.json({ message: '이름과 내용을 입력해주세요. / Please enter both name and content.' }, { status: 400 });
  }

  const newPost = {
    id: Date.now(),
    name,
    content,
  };

  guestbookData.push(newPost);
  return NextResponse.json(newPost, { status: 201 });
}

1)page.tsx폼을 통해서 POST방식으로 전송된 갑을 처리합니다.
It processes the data sent via the POST method from the page.tsx form.

2)guestbookData배열에 폼에서전송된 데이터와 지금날짜를 더해서 newPost를 만듭니다.
Create newPost by combining the data submitted from the form with the current date and adding it to the guestbookData array.

3)만들어진 newPost를 guestbookData에 저장하고 json데이터로 성공메세지(status:201)를 전송합니다.
Save the created newPost to guestbookData and send a success message (status: 201) as JSON data.


📁 페이지 라우터 부분은 따로 설명하지 않겠습니다.
I will not go into detail about the page router.

📁 앱라우트를 이해하시면 페이지 라우트는 쉽게 이해 할 수 있습니다.
If you understand app routes, page routes are easy to grasp.

Leave a Reply