완성형 어플리케이션 : 블로그 구축하기 - 1

·2024년 4월 17일
0

NextJS

목록 보기
15/26
post-thumbnail

🔗 레파지토리에서 보기

📌 주요 페이지 설정하기

  1. pages/index.js : 홈페이지
  2. pages/contact.js : 콘택트 페이지
  3. pages/posts/index.js : 전체 블로그 포스트들을 나타낼 페이지
  4. pages/posts/[slug].js : 세부적인 블로그 포스트 페이지로 /posts/getting-start-with-nextjs 와 같이 읽기 쉽고 검색 엔진에 노출되기에도 쉬운 slug로 작성하였다.

📌 홈 화면 설정하기

📖 posts/index.js 작성하기

import Hero from "@/components/home-page/hero";
import FeaturedPosts from "@/components/home-page/featured-posts";
export default function HomePage() {
  return (
    <>
      <Hero />
      <FeaturedPosts />
    </>
  );
}

// 1) Hero : 환영 섹션, 주요 상품을 소개. => 자기소개
// 2) Featured Posts: 더미 포스트 표시, 나중에 실제 게시물로 교체.

📖 components/home-page/hero.js

import Image from "next/image";
import classes from "./hero.module.css";
export default function Hero() {
  return (
    <section className={classes.hero}>
      <div className={classes.image}>
        <Image
          src="/images/site/rui.png"
          alt="An image showing Zoe"
          width={300}
          height={300}
        />
      </div>
      <h1>Hi, I'm Zoe</h1>
      <p>
        I blog about web development - especially frontend frameworkes like
        React.
      </p>
    </section>
  );
}

<Image/> 컴포넌트는 표시하는 스크린의 크기 등에 따라 크기가 다른 이미지를 표시할 수 없다면, 해당 문서를 참고하여 이미지에 대한 여러 구성 방법을 알아볼 수 있다.


📌 레이아웃 & 네비게이션 추가하기

📖 components/layout/layout.js

import MainNavigation from "./main-navigation";
export default function Layout({ children }) {
  return (
    <>
      <MainNavigation />
      <main>{children}</main>
    </>
  );
}

📖 pages/_app.js

import "../styles/globals.css";
import Layout from "@/components/layout/layout";

function MyApp({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

export default MyApp;

📖 components/layout/main-navigation.js

import Logo from "./logo";
import Link from "next/link";
import classes from "./main-navigation.module.css";

export default function MainNavigation() {
  return (
    <header className={classes.header}>
      <Link href="/">
        <Logo />
      </Link>
      <nav>
        <ul>
          <li>
            <Link href="/posts">Posts</Link>
          </li>
          <li>
            <Link href="/contact">Contact</Link>
          </li>
        </ul>
      </nav>
    </header>
  );
}

📖 components/layout/logo.js

import classes from "./logo.module.css";

export default function Logo() {
  return <div className={classes.logo}>Zoe's Next Blog</div>;
}

📖 pages/index.js

import Hero from "@/components/home-page/hero";
import FeaturedPosts from "@/components/home-page/featured-posts";

const DUMMY_POSTS = [
  {
    title: "Getting Started With NextJS",
    image: "getting-started-nextjs.png",
    slug: "getting-started-with-nextjs",
    excerpt: "NextJS is a the React framework for production.",
    date: "2024-04-15",
  },
  {
    title: "Getting Started With NextJS",
    image: "getting-started-nextjs.png",
    slug: "getting-started-with-nextjs2",
    excerpt: "NextJS is a the React framework for production.",
    date: "2024-04-15",
  },
  {
    title: "Getting Started With NextJS",
    image: "getting-started-nextjs.png",
    slug: "getting-started-with-nextjs3",
    excerpt: "NextJS is a the React framework for production.",
    date: "2024-04-15",
  },
  {
    title: "Getting Started With NextJS",
    image: "getting-started-nextjs.png",
    slug: "getting-started-with-nextjs4",
    excerpt: "NextJS is a the React framework for production.",
    date: "2024-04-15",
  },
];

export default function HomePage() {
  return (
    <>
      <Hero />
      <FeaturedPosts posts={DUMMY_POSTS} />
    </>
  );
}

DUMMY_POSTS 데이터 추가


📖 components/home-page/featured-posts.js

import classes from "./featured-posts.module.css";
import PostsGrid from "../posts/posts-grid";

export default function FeaturedPosts({ posts }) {
  return (
    <section className={classes.latest}>
      <h2>Featured Posts</h2>
      <PostsGrid posts={posts} />
    </section>
  );
}

📖 components/posts/posts-grid.js

import PostItem from "./post-item";
import classes from "./posts-grid.module.css";

export default function PostsGrid({ posts }) {
  return (
    <ul className={classes.grid}>
      {posts.map((post) => (
        <PostItem key={post.slug} post={post} />
      ))}
    </ul>
  );
}

📖 components/posts/post-item.js

import classes from "./post-item.module.css";
import Link from "next/link";
import Image from "next/image";

export default function PostItem({ post }) {
  const { title, image, excerpt, date, slug } = post;
  const formatted_date = new Date(date).toLocaleDateString("ko-KR", {
    day: "numeric",
    month: "long",
    year: "numeric",
  });

  return (
    <li className={classes.post}>
      <Link href={`/posts/${slug}`}>
        <div className={classes.image}>
          <Image
            src={`/images/posts/${slug}/${image}`}
            alt={title}
            width={300}
            height={200}
          />
        </div>
        <div className={classes.content}>
          <h3>{title}</h3>
          <time>{formatted_date}</time>
          <p>{excerpt}</p>
        </div>
      </Link>
    </li>
  );
}
  • <Image/>layout은 기본적으로 intrisic으로 설정되어 있다. 이를 responsive로 설정하여 이미지가 더 보기 좋게 설정한다.


📌 Post 관련 페이지 작업하기

📖 All Posts 페이지 작업하기

// components/posts/all-posts.js
import classes from "./all-posts.module.css";
import PostsGrid from "./posts-grid";

export default function AllPosts({ posts }) {
  return (
    <section className={classes.posts}>
      <h1>All Posts</h1>
      <PostsGrid posts={posts} />
    </section>
  );
}


// pages/posts/index.js
import AllPosts from "@/components/posts/all-posts";

const DUMMY_POSTS = [
  {
    title: "Getting Started With NextJS",
    image: "getting-started-nextjs.png",
    slug: "getting-started-with-nextjs",
    excerpt: "NextJS is a the React framework for production.",
    date: "2024-04-15",
  },
  {
    title: "Getting Started With NextJS",
    image: "getting-started-nextjs.png",
    slug: "getting-started-with-nextjs2",
    excerpt: "NextJS is a the React framework for production.",
    date: "2024-04-15",
  },
  {
    title: "Getting Started With NextJS",
    image: "getting-started-nextjs.png",
    slug: "getting-started-with-nextjs3",
    excerpt: "NextJS is a the React framework for production.",
    date: "2024-04-15",
  },
  {
    title: "Getting Started With NextJS",
    image: "getting-started-nextjs.png",
    slug: "getting-started-with-nextjs4",
    excerpt: "NextJS is a the React framework for production.",
    date: "2024-04-15",
  },
];

export default function AllPostsPage() {
  return <AllPosts posts={DUMMY_POSTS} />;
}


📖 Post Detail 페이지 작업하기

// components/posts/post-detail/post-header.js
import classes from "./post-header.module.css";
import Image from "next/image";
export default function PostHeader({ title, image }) {
  return (
    <header className={classes.header}>
      <h1>{title}</h1>
      <Image src={image} alt={title} width={200} height={150} />
    </header>
  );
}


// components/posts/post-detail/post-content.js
import classes from "./post-content.module.css";
import PostHeader from "./post-header";

const DUMMY_POST = {
  title: "Getting Started With NextJS",
  image: "getting-started-nextjs.png",
  slug: "getting-started-with-nextjs",
  content: "# This is a first post.",
  date: "2024-04-15",
};

export default function PostContent() {
  return (
    <article className={classes.content}>
      <PostHeader
        title={DUMMY_POST.title}
        image={`/images/posts/${DUMMY_POST.slug}/${DUMMY_POST.image}`}
      />
      {DUMMY_POST.content}
    </article>
  );
}


// pages/posts/[slug].js
import PostContent from "@/components/posts/post-detail/post-content";

export default function PostDetailPage() {
  return <PostContent />;
}

0개의 댓글

관련 채용 정보