[Next.js 탐험기] 5. Next.js + 티스토리 API 블로그 만들기 - 카테고리 페이지 만들기

서론

전 포스팅에 이어서 카테고리 페이지를 완성하겠다. 카테고리 페이지에서는 각 categoryId에 해당하는 글 목록을 보기 좋게 목록화 하여 표현해줄 것이다. 

 

데이터 읽어오기

전 포스팅에서 언급한 것과 같이, next 13 버전에서는 getStaticProps같은 함수들을 지원하지 않는다. Data Fetching이 궁금하다면 공식문서를 참고하도록 한다. 여기서는 비동기 통신을 하는 것이 아니므로 getData 함수나 json파일을 변환해줄 필요없이 가져오기만 하면 된다.

 

useSearchParams()을 통해 얻은 params는 get() 함수를 통해 필요한 파라미터를 선택하여 값을 받아올 수 있었고, 여기서는 categoryId 값을 받아 해당 위치에 존재하는 카테고리의 게시글 데이터를 가져온다.

const CategoryPage = (props) => {
    const pathname = decodeURI(usePathname());
    const params = useSearchParams();
    const data = require('../../data/categories/' + params.get('categoryId') + '.json')
    return (
        <>
        </>
    );
};

 

 

React에서 데이터 출력방법

React 컴포넌트가 객체를 직접 자식으로 렌더링하려고 시도하면 에러가 발생한다. React에서는 객체를 직접 렌더링할 수 없고, 대신 문자열, 숫자, JSX 요소, 배열 등을 렌더링해야 한다. 따라서 받아온 data 객체를 사용하려면 객체의 속성을 개별적으로 렌더링하거나, 객체를 적절한 방식으로 변환해야 한다. 예시로 아래와 같은 Json 형태의 data 객체가 있다고 가정한다.

const data = {
  id: 1,
  title: 'Hello World',
  postUrl: 'https://example.com',
  visibility: 'public',
  // ... 기타 속성
};

첫 번째 방법은 객체의 속성 개별 렌더링 하는 것이다. 방법은 "콤마 (.)" 구분자를 사용하여 객체의 키에 접근하면 해당하는 값을 불러올 수 있다.

const CategoryPage = () => {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>URL: {post.postUrl}</p>
      {/* 기타 속성을 개별적으로 렌더링 */}
    </div>
  );
};

두 번째 방법으로 객체를 배열로 변환하여 렌더링하는 방법이 있다. 단순하게 객체의 모든 값을 배열로 변환하여 렌더링 하는 방법인데 이 경우, Object.values나 Object.entries를 사용할 수 있다. 나는 두 번째 방법을 사용했다.

const CategoryPage = () => {
  return (
    <ul>
      {Object.entries(data).map(([key, value]) => (
        <li key={key}>{`${key}: ${value}`}</li>
      ))}
    </ul>
  );
};

 

 

카테고리 페이지 만들기

카테고리 데이터에는 포스팅 타이틀 이외에는 포스팅에 대한 내용이 직접적으로 없으므로, 현재는 포스팅 타이틀을 불러와서 Link태그를 사용하여 클릭할 때, 티스토리 본래의 포스팅 주소로 페이지 이동하는 방향으로 만들었다.

'use client'

import React from 'react';
import Link from 'next/link';
import {usePathname, useRouter, useSearchParams} from 'next/navigation';
import styles from './[subCategoryName]/page.module.css';

const CategoryPage = () => {
    const pathname = decodeURI(usePathname());
    const params = useSearchParams();
    const data = require('../../data/categories/' + params.get('categoryId') + '.json')
    return (
        <>
            <div className={styles.head}>여기는 {pathname.split("/").pop()} 카테고리 페이지입니다.</div>
            <div className={styles.container}>
                {Object.entries(data).map(([key, value]) => (
                    <div className={styles.list}>
                        <div className={styles.listHead}>
                            <Link href={value.postUrl} target={'_blank'}>${value.title}</Link>
                        </div>
                    </div>
                ))}
            </div>
        </>
    );
};

export default CategoryPage;

나는 css를 맨 처음부터 신경써서 작성하기 보다는, 틀을 먼저 구성하고 기능 구현이 완료된 이후에 작업하는 것이 맞다고 생각해서 최소한으로만 작성하였다.

/* './[subCategoryName]/page.module.css' */
.head{
    padding: 30px;
    display: flex;
    justify-content: center;
}

.container {
    padding: 0px 30px 0px 30px;
}

.list {
    margin: 20px;
    border: 2px solid whitesmoke;
    border-radius: 10px 10px 10px 10px;
}

.listHead {
    margin: 20px;
    display: flex;
    justify-content: center;
}

 

 

결과물