๐Ÿ’ป์›น(Web)/NextJS

NextJS: page router์™€ app router(1)

stonesy 2024. 11. 10. 13:41
728x90

Page Router์™€ App Router์˜ ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์€ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

 

์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋ž€?

์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ์„œ๋ฒ„์—์„œ๋งŒ ์‹คํ–‰๋˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ์— JavaScript๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๋Š”๋‹ค. JavaScript ๋ฒˆ๋“ค ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ณ  ์ดˆ๊ธฐ ๋กœ๋”ฉ ์†๋„๋ฅผ ๊ฐœ์„ ํ•˜๋Š”๋ฐ ๋„์›€์ด ๋œ๋‹ค. ๋‹จ, ํด๋ผ์ด์–ธํŠธ์—์„œ ์ง์ ‘ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ณ , ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋œ HTML๋งŒ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „๋‹ฌํ•œ๋‹ค.

 

page router์—์„œ๋Š” ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ SSR๋กœ ์ฒ˜๋ฆฌํ• ์ง€, SSG๋กœ ์ฒ˜๋ฆฌํ• ์ง€, ํ˜น์€ CSR์œผ๋กœ ์ฒ˜๋ฆฌํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ app router์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์™€ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค.

 

๋งŒ์•ฝ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ์ž์‹์œผ๋กœ ์žˆ๋‹ค๋ฉด ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ RSC๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๊ฐ€ ์ƒ์‹ค๋œ๋‹ค.์ฆ‰, ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์˜ ์ค‘์š”ํ•œ ํŠน์„ฑ ์ค‘ ํ•œ ๊ฐ€์ง€๊ฐ€ ์ƒ์‹ค๋˜๋Š” ๊ฒƒ์ด๋‹ค.

- ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋จ: ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋˜์–ด ํด๋ผ์ด์–ธํŠธ๋กœ ์ „๋‹ฌ๋˜๋Š” HTML์„ ์ƒ์„ฑํ•œ๋‹ค.

- ์ƒํƒœ ๊ด€๋ฆฌ ์—†์Œ: ํด๋ผ์ด์–ธํŠธ ์ธก ์ƒํƒœ ๊ด€๋ฆฌ์™€ ์ƒํ˜ธ๊ด€๋ฆฌ ๋กœ์ง์ด ํฌํ•จ๋˜์ง€ ์•Š๋Š”๋‹ค.

- ๋ฐ์ดํ„ฐ ํŽ˜์นญ: ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ๋ Œ๋”๋งํ•œ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  app router๋Š” SSR, SSG ๋“ฑ์„ ์ง€์ •ํ•ด์ค„ ํ•„์š” ์—†์ด ๋‚ด๋ถ€์ ์œผ๋กœ ์ž๋™์œผ๋กœ ๊ฒฐ์ •๋œ๋‹ค.

 

ex) ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ํŽ˜์ด์ง€์—์„œ ํŒ”๋กœ์šฐ ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์˜ˆ๋ฅผ ๋“ค์–ด ์ƒ๊ฐํ•ด๋ณด์ž.

*์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ

// app/profile/page.js - ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ
import React from 'react';
import FollowButton from './FollowButton';

// ์„œ๋ฒ„์—์„œ ํ”„๋กœํ•„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
async function fetchProfileData() {
  const response = await fetch('https://api.example.com/profile', {
    cache: 'no-store', // ์ตœ์‹  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด no-store ์„ค์ •
  });
  if (!response.ok) throw new Error('Failed to fetch profile data');
  return response.json();
}

// ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ”„๋กœํ•„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ Œ๋”๋ง
export default async function ProfilePage() {
  const profileData = await fetchProfileData();

  return (
    <div>
      <h1>{profileData.name}'s Profile</h1>
      <p>Email: {profileData.email}</p>
      
      {/* ํ•˜์œ„์— ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํฌํ•จ */}
      <FollowButton userId={profileData.id} />
    </div>
  );
}

*ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ

// app/profile/FollowButton.js
'use client'; // ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์ž„์„ ๋ช…์‹œ

import React, { useState } from 'react';

export default function FollowButton({ userId }) {
  const [isFollowing, setIsFollowing] = useState(false);

  // ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํŒ”๋กœ์šฐ ์ƒํƒœ๋ฅผ ์ „ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
  const handleFollow = async () => {
    const response = await fetch(`/api/follow/${userId}`, {
      method: isFollowing ? 'DELETE' : 'POST',
    });
    if (response.ok) {
      setIsFollowing(!isFollowing);
    }
  };

  return (
    <button onClick={handleFollow}>
      {isFollowing ? 'Unfollow' : 'Follow'}
    </button>
  );
}

 

 

์ฐธ๊ณ 

https://velog.io/@ubin_ing/nextjs-app-router

 

 

728x90