본문 바로가기
Web Study/Next.js

Next.js로 SNS x.com 클론코딩하기 - 13

by 쿠리의일상 2024. 2. 19.

메타데이터

https://nextjs.org/docs/app/building-your-application/optimizing/metadata#merging

 

Optimizing: Metadata | Next.js

Use the Metadata API to define metadata in any layout or page.

nextjs.org

각 page.jsx / page.tsx 에서 export const metadata 를 통해 메타데이터를 직접 입력해줄 수 있습니다. 물론 layout 파일 또한 동일한 방법으로 메타데이터를 지정해줄 수 있으나 layout 과 page 동일 계층이라면 page 내용의 메타데이터로 보여지게 됩니다.

export const metadata = {
  title: "홈 / Z",
  description: "X.com 클론 코딩",
};

기존에는 create next app 또는 주소창의 path가 타이틀에 보였겠지만 위처럼 지정해주면 타이틀에 보이는 내용이 변경됩니다. 

간단한 메타데이터는 위처럼 나타내주면 되지만 내 정보를 읽어와서 보여줘야 하는 경우(프로필이나 검색 등)는 아래처럼 generateMetadata() 을 사용하여 정보를 가져오고 활용해줄 수 있습니다.

export async function generateMetadata({
  searchParams,
}: Props): Promise<Metadata> {
  return {
    title: `${searchParams.q} - 검색 / Z`,
    description: `${searchParams.q} 검색`,
  };
}

매개변수로 들어갈 수 있는 값에는 params 와 searchParams가 존재하는데, params 는 동적 주소에 해당하는 값이 들어가며 searchParams 는 쿼리스트링의 키/값이 들어가게됩니다.

다만 주의할 점은 generatorMetadata() 함수도 서버에서 실행되는 것이므로 서버에서 정보를 동적으로 가져오고 싶다면 fetch 해줘야 하며 당연히 서버 컴포넌트에서 작동합니다.

콘솔창에서 메타데이터를 확인해 보면 아래와 같습니다.

meta 태그의 name에 키값으로 지정해준 description 이 들어가고, content 안에 값이 들어가게 됩니다. 특정값을 임의로 지정해줄 순 없으며 지정된 값을 사용해줘야 합니다. 아래의 링크 내 자세히 설명되어 있습니다.

https://nextjs.org/docs/app/api-reference/functions/generate-metadata#metadata-fields

 

Functions: generateMetadata | Next.js

Learn how to add Metadata to your Next.js application for improved search engine optimization (SEO) and web shareability.

nextjs.org

 

e.stopPropagation() / e.preventDefault()

이벤트를 다룰 때 곧잘 등장하는 함수들인데, 어떤 점이 다른지 정리합니다.

e.preventDefault() 메서드는 a, submit 등의 태그에서 고유한 동작(페이지 이동, form 정보 전송 등)을 수행하게 됩니다. 이때 이러한 동작을 중단시키는 역할을 합니다.

e.stopPropagation() 메서드는 상위 엘리먼트에 이벤트의 버블링을 막는 역할을 해줍니다. 버블링이란 하위 자식 엘리먼트에서 이벤트가 발생하면 순차적으로 부모를 거쳐 상위 요소까지 이벤트가 전달되는 현상을 의미하는데, 이러한 행위를 막아줄 수 있는 메서드가 stopPropagation() 입니다.  

 

 

zustand

일전의 게시글에서도 말했다시피 리액트 쿼리와 저스탠드를 사용하여 클론코딩을 진행한다고 했습니다. 리액트 쿼리로도 쿼리키를 주어 상태 관리가 가능하지만 기본적으로 리액트 쿼리는 데이터 패칭이 주 사용 목적이므로 저스탠드를 사용하여 전역 상태를 관리하도록 하겠습니다. 대상은 답글과 재게시 부분입니다.

 

사용법은 리덕스와 달리 매우 간단합니다.

import {create} from 'zustand';

export const useCustom = create((set) => ({
// 로직 구현
})

create 함수를 사용하여 사용자 정의 스토어를 만들어줍니다. 이때 create 안에는 set을 매개변수로 받고 객체 형태를 리턴해주는 콜백함수가 들어가게 됩니다.

반환해주는 객체 안에는 자유롭게 변수 및 함수를 지정해주면 됩니다. 답글 기능을 저스탠드와 함께 사용하고자 한다면,  아래와 같은 모달스토어를 만들어줄 수 있습니다.

interface ModalState {
  mode: "new" | "comment";
  data: Post | null;
  setMode(mode: "new" | "comment"): void;
  setData(data: Post): void;
  reset(): void;
}

export const useModalStore = create<ModalState>((set) => ({
  mode: "new",
  data: null,
  setMode(mode) {
    set({ mode });
  },
  setData(data) {
    set({ data });
  },
  reset() {
    set({
      mode: "new",
      data: null,
    });
  },
}));

mode 와 data 변수를 다루는 스토어로 각각 setMode(), setData() 로 해당 변수값을 변경해주며 reset()은 두 변수를 초기화 해주는 함수로 지정해줍니다. 이때 매개변수로 받아주었던 set 으로 변수를 직접 변경해주는 것이 아닌(불변성 때문에), 객체 형태로 받아서 변수를 변경해주도록 처리해줍니다. 

해당 상태를 가져와서 사용하는 방법은 아래와 같습니다.

import { useModalStore } from "@/store/modal";

const modalStore = useModalStore();

// ...

const data = modalStore.data;

이렇게 모든 컴포넌트에서 하나의 상태에 관해 접근하여 공유할 수 있게 되었습니다.

 

동일한 방식으로 재게시 또한 완료해줍니다.

Context API와 Zustand 의 사용법은 비슷하긴 하지만 컨텍스트의 경우 최적화를 직접 해줘야하는 단점이 존재하여 빠르고 간단하게 전역 상태 관리가 필요하다면 저스탠드를 쓰는것을 추천하고 있습니다. 

 

제로초님께서 직접 만드신 페이지를 보려면 아래의 링크를 확인하시면 됩니다.

https://z.nodebird.com/

 

Z. 무슨 일이 일어나고 있나요? / Z

 

z.nodebird.com

강의 전용 깃헙

https://github.com/ZeroCho/next-app-router-z

 

GitHub - ZeroCho/next-app-router-z

Contribute to ZeroCho/next-app-router-z development by creating an account on GitHub.

github.com

실제 z.com 을 만드는데 사용된 깃헙 (최신 업데이트가 진행된다고 함)

https://github.com/ZeroCho/z-com

 

GitHub - ZeroCho/z-com

Contribute to ZeroCho/z-com development by creating an account on GitHub.

github.com

 

이렇게 API 문서를 기반으로 섹션4가 마무리 됐습니다. 나머지 한 섹션만 남았는데, 해당 섹션은 전부 수강하기 보단 꼭 필요한 부분만 취하고 강의 정리를 마무리하려고 합니다.