728x90
반응형

이번 포스트는 주로 pages폴더를 분석할 것이다. 차근차근 _app.tsx 파일부터 보자.

 

app.tsx

import { FC } from 'react';
import type { AppProps /*, AppContext */ } from 'next/app';
import Sidebar from '../components/sidebar';

const MyApp: FC<AppProps> = ({ Component, pageProps }) => {
  console.log(Component)
  console.log(pageProps)
  return (
    <div style={{ display: 'flex', maxWidth: 1100 }}>
      <div style={{ flexBasis: '30%', margin: 25 }}>
        <Sidebar />
      </div>
      <div style={{ flexBasis: '70%', margin: 25 }}>
        <Component {...pageProps} />
      </div>
    </div>
  );
};

export default MyApp;

 

FCAppProps는 타입스크립트를 위한 모듈이다.

Sidebar 컴포넌트를 import하고 최상위인 MyAppSidebarComponent를 사용하였다.

파라미터인 ComponentpageProps를 로그로 확인해보면

 

Component는 리액트 Myapp에서도 쓰이는 함수이고, Nest에서 '/'경로에 home 을 렌더링 해주었기 때문에 home.tsx가 들어온다. pageProps는 Nest에서 넘겨주었던 name 파라미터가 null로 담겨있는것을 확인할 수 있다.

 


FC의 사용법은 아래 링크로 자세히 볼 수 있다.

https://react.vlpt.us/using-typescript/02-ts-react-basic.html

 

2. 리액트 컴포넌트 타입스크립트로 작성하기 · GitBook

2. 리액트 컴포넌트 타입스크립트로 작성하기 이번 섹션에서는 리액트 컴포넌트를 타입스크립트로 작성하는 방법을 알아보도록 하겠습니다. 프로젝트 생성 우선, 타입스크립트를 사용하는 리

react.vlpt.us


 

home.tsx

import * as React from 'react';
import { NextPage, NextPageContext } from 'next';

interface Props {
  query: { name?: string };
}

const Home: NextPage<Props> = ({ query }) => {
  const greetName = query.name ? query.name : 'World';

  return (
    <div>
      <div>Hello, {greetName}!</div>
    </div>
  );
};

export async function getServerSideProps(ctx: NextPageContext) {
  const query = {
    name: ctx.query.name || null,
  };
  return { props: { query } };
}

export default Home;

next에서 NextPage,NextPageContext를 import해서 Home과 getServerSideProps 에서 사용하였다.

서버사이드렌더링으로 Nest로부터 name 값을 query로 가져왔고 Home 에 props로 넘겨주었다.

 

이 때 Home은 next에서 import되었던 NextPage의 타입을 따르며 파라미터는 interface로 선언했던 Props를 따른다.

 

 

about.tsx 파일은 나중에 클라이언트 측 API요청을 할 때 설명하겠다.

 

 

pages/views/blog/index.tsx

import * as React from 'react';
import { NextPage, NextPageContext } from 'next';
import { IPost } from '../../../types';
import PostPreview from '../../../components/post-preview';
import { BlogService } from '../../../src/blog/blog.service';

interface Props {
  posts: IPost[];
  source: string;
}

const Blog: NextPage<Props> = ({ posts, source }) => {
  return (
    <div>
      <h1>blog</h1>
      <div>
        {posts.map((post) => (
          <PostPreview key={post.slug} post={post} />
        ))}
      </div>
      <div style={{ fontStyle: 'italic', fontSize: 14 }}>
        this page was rendered on the {source}
      </div>
    </div>
  );
};

export async function getServerSideProps(ctx: NextPageContext) {
  const props: Props = {
    source: 'server',
    posts: ctx.query.posts as any,
  };

  if (!Array.isArray(props.posts)) {
    const service = new BlogService();
    props.posts = service.all();
    props.source = 'client';
  }

  return { props };
}

export default Blog;

 

Nest에서 우린 '/blog'에 'blog'를 렌더링해주었다. 때문에 '/blog'경로로 접속하면 blog/index.tsx 파일이 반환된다.

 

 

아까 _app.tsx에서 확인했었던 log를 보면,

 

 

이렇게 Blog 컴포넌트가 잘 들어왔고, pageProps에 Nest에서 준 데이터와 getServerSideProps에서 넘겨준

데이터가 잘 들어온 것을 확인할 수 있다.

 

 

interface Props {
  posts: IPost[];
  source: string;
}

Props 인터페이스를 만들어 타입을 지정했다. 

 

 

export async function getServerSideProps(ctx: NextPageContext) {
  const props: Props = {
    source: 'server',
    posts: ctx.query.posts as any,
  };

  if (!Array.isArray(props.posts)) {
    const service = new BlogService();
    props.posts = service.all();
    props.source = 'client';
  }

  return { props };
}

props 변수를 선언하고, source에는 임의로 'server'를 넣고, posts 쪽에 Nest에서 받은 데이터를 넣어주었다.

 

확인해보니 이 코드에선 Nest에서 보내준 데이터라 getServerSideProps 에 ctx로 잘 못들어오는 것을 확인했다.

if 구문에서 쓰고있는 Service는 Nest의 Service클래스라 사실 쓰지 않는것이 좋다. 

 

굳이 NestJS와 NextJS를 섞어서 개발을 한다면 쓸 수는 있겠지만 서버 인프라를 구축할 때 프론트와 백엔드를 나눠야 할 때를 생각하면 각각 쓰는 메소드가 분리되어야 무조건 좋다. 이런 방법이 있구나 정도만 알고 이렇게 쓰는것보단 axios로 ServerSideProps에서 값을 받아오도록 하자.

 

 

 

 

 

728x90
반응형

+ Recent posts