Next.js 공식 튜토리얼 실습일지

Felix Yi·2020년 3월 19일
0
post-custom-banner

next 공식 튜토리얼 BASICS 와 EXCEL 실습 기록

BASICS

Getting Started

FileSystemRouting 이라서 별도의 라우트 매핑 정보를 작성할 할 필요가 없다니... 이게 좋은 건가 싶다.

<Link /> 는 서버요청이 아닌 client 요청을 한다.

이렇게 해본다음에 해보지 않으면 답변할 수 없는 질문을 넣어서 학습자의 주의를 환기시키는 점은 매우 좋다.

Using Shared Components

초반, 라우팅 된 컴포넌트마다 같은 코드를 넣어주면서 조금 깝깝했지만, with- 로시작하는 고차컴포넌트 사용하면서 속이 시원했다.

몰랐던 건, 함수형 컴포넌트 자체를 리턴해야해서 return (인자)=> (jsx) 여야 하는데, 무심코 return (jsx) 해버린 거.

const withLayout = Page => {
  // 함수형(인자를 받는 함수형태의) 컴포넌트를 리턴해야한다!
    return () => (
        <div style={layoutStyle}>
            <Header />
            <Page />
        </div>
    );
};

Create Dynamic Pages

뇌가 아직 파일 시스템 라우팅을 시뮬레이션 하지 못했다. 그래서 뇌가 놀랐다. 마법이 일어난 줄 알고.

아래와 같은 매핑 없이도

`/post` : Page

아래 컴포넌트의 링크가...

    const PostLink = (props) => (
        <li>
            <Link href={`/post?title=${props.title}`}>
                <a>{props.title}</a>
            </Link>
        </li>
    )

이 컴포넌트로 매핑이 된다는 게 이제까지 익숙한 것과는 전혀 다른, 그래서 생소한 매직.

const Page = () => {
    const router = useRouter();

    return (
        <Layout>
            <h1>{router.query.title}</h1>
            <p>this is the blog post content</p>
        </Layout>
    )
}

개발 뉴비일 때 FileSystemRouting 로 작동되면 좋겠다고 생각을 했다. 뉴비를 지나서, 웹서버는 무조건 경로와 경로에 따른 서빙할 자원이 아무 관계가 없으니 매핑시켜주는 게 당연하다고 받아들였다. 그런데 그게 아니라니.

Clean URLs with Dynamic Routing

헐, 마치 파일을 변수처럼 [뭥미?].js 대괄호로 가두고는 그게 마치 다이나믹 변수처럼 취급. 파일 이름에 불필요한 기호를 넣으면 안 된다(실제로는 위험하다)고 알고 있었는데. 자꾸만 금기가 깨진다.

작성: /pages/하위폴더/[객체필드명].js
접근: /하위폴더/입력Path값
결과: { 객체필드명: '입력Path값'}

이게 풀패쓰만 되고, 일부 입력은 안됨 /pages/하위폴더/어떤고정-[동적패스값].js 은 안 됨.

as 를 넣으면 브라우저 히스토리 작동. 왜냐면 브라우저 주소창을 조작해서. 아마도 push 를...

흠.. href 는 실제 이동할 주소, as 는 브라우저 주소창에 넣을 주소다. 이게 둘 다 형태가 맞아야 함. 다르면 오류가 난다.

    <Link href="/[id]" as={`/p/${props.id}`}>
      <a>{props.id}</a>
    </Link>
Uncaught (in promise) Error: The provided `as` value (/p/hello-넥스트) is incompatible with the `href` value (/[id]). Read more:

Fetching Data for Pages

TVAmazeAPI 서비스 좋네. 바로 직전 잡이 방송사 백오피스 만드는 거라서 별별 데이터 수신했었는데. 분산된 레거시 자료 스케쥴 돌리고 수집하고 보여주는 그런 행위 하던데... 그냥 이런 API 있으면 쓰면 될 거 같다. 여튼?


출처 : https://medium.com/capital-one-tech/why-everyone-is-talking-about-isomorphic-universal-javascript-and-why-it-matters-38c07c87905

isomorphic 개발 = 동형사상(map) 개발. 서버/클라가 서로의 코드를 재사용하는 개발 구조. Scala 와 Scala.js 를 보는 것 같다. 옜날 사람.

getInitialProps enables server-side rendering in a page and allows you to do initial data population, it means sending the page with the data already populated from the server. This is especially useful for SEO.

SSR 실습할 때 preloadContext 로 컴포넌트 렌더링 전 자료를 조작하는 부분을 getInitialProps 로 해주는 듯. 근데 문서를 보니 9.3 버전 이상은 아래처럼.

If you're using Next.js 9.3 or newer, you should use getStaticProps or getServerSideProps instead of getInitialProps.

둘의 차이점은 다음과 같다.

  • getStaticProps (Static Generation): 빌드 시에만 FetchData. (주. 아마 캐시 되겠지? static 이라니깐)
  • getServerSideProps (Server-side Rendering): 매 요청 시마다 자료 Fetch.

하긴 SSR 실습할 때, 매번 비동기 작업 실행된다 그랬던 게 기억난다.

아주 이상한 오류.1
getServerSideProps 작동 안함. latest 버전(현재 9.3.1)인데.

아주 이상한 오류.2
컴포넌트 렌더링 오류나면 밑에 fetch 에서 CORS 오류남.
정말 CORS 오류인 줄 알고 삽질함.

음.. getInitialProps 부분이.. Link 타고 들어가면 클라이언트쪽에서 실행되고, 해당 주소에서 새로고침하면 서버에서 실행된다.

getInitialProps 는 서버에서만 실행되는 것 아냐? X -> 페이지에서만 실행 + SSR 일 때도 가능하게.

Styling Components

음. 스타일이라면, SSR 내용에서 빌드된 파일에서 chunk 를 추출해서 그걸 클라에 내려보내고 index 페이지에 내려보낸 스타일을 사용하도록 했던 거 같다. 복잡했던 기억.

여기서는 styled-jsx 를 사용한다. 음.. 배울 때는 styled-compoents 를 사용했는데.. 같은 걸 하는 너무나 다양한 컴포넌트가 있어서 햄 볶고 싶은데 지친다.

오 편하네.

<style jsx>
  {`
    h1, a { font-family: 'Arial'}
    ul { padding: 0;}
    li { list-style: none; margin: 5px 0;}
    a { text-decoration: none; color: blue;}
    a:hover { opacity: 0.6;}
  `}
</style>

Styles should go inside template strings 라니까 조심.

아래처럼 렌더링 됨. jsx-뒤에 붙은 id 는 숫자가 똑같은 거 보니까. 현재 컴포넌트에서 생성된 style 만 의미하는 듯.(청크파일 이름일 수도 있어 ㅎㅎ)

오.. nested 에는 스타일이 적용 안 되네. 보통의 CSS 는 내부 요소에 모두 적용되는디. 그건 뷰도 마찬가지.

global selector 쓰면 현재 화면에 사용된 자식 컴포넌트 내부에도 스타일을 적용할 수 있다.

<div className="markdown">
   <Markdown source={`내용`}/>
</div>
<style jsx global>{`
  .markdown {
  	font-family: 'Arial';
  }

  .markdown a {
    text-decoration: none;
    color: blue;
  }
`}

API Routes

api 요청은 api 폴더에 넣으면 됨. 일반 컴포넌트랑 구분되게.

생성: /api/컴포넌트
접근: /컴포넌트

/api/컴포넌트.js

export default (req, res) => {
  res.status(200).json(Json형태의무엇!?)
}

swr 아주아주 편리하다.
클라-> 서버-> 다른 원격 데이터 fetch 를 처리.

아래는 /api/user 데이터 fetch 해서 그 결과를 data, error 로 받아서 분기타고 돌려주는 것. 아주아주편함

어따 쓰냐면, OAUTH 를 할 때 클라에 노출하기 싫은 key 등이 있는데 서버가 대신 인증을 받아오는 걸 처리해야할 경우.

function Profile () {
  const { data, error } = useSWR('/api/user', fetch)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

아래처럼 받은 query.param 를 통해 추가 작업하기.

export default function Index() {
    const { query } = useRouter();
    const {data, error} = useSWR(`/api/randomQuote${query.author ? '?author=' + query.author : ''}`, fetcher)
export default (req, res) =>{
    const {author} = req.query;
    let quotes = allQuotes

    if(author) {
        quotes = quotes.filter(quote => quote.author.toLowerCase().includes(author.toLowerCase()))
    }

Deploying a Next.js App

건너뜀.

EXCEL

Export into a Static HTML App

다이나믹 페이지 생성할 경우가 아닌, 정적인 페이지만 있다면 html 로 내보낼 수 있다.

  "scripts": {
    "dev": "next",
    "build": "next build",
    "export": "next export"
  },

out 폴더에 나온 걸 serve 로 돌리면 된다.

근데 getInitialProps 가 클라이언트에서만 계속 나온다. SSR 이 아닌 CSR 상태.

아래처럼 하면 루트 경로로 들어가서 링크를 누르면 작동하나. 하위 경로를 직접 가면 작동 안한다. 각각의 페이지에 필요한 것들이 생성 안 되어있어서.

next.config.js

module.exports = {
    exportTrailingSlash: true,
    exportPathMap: function() {
        return {
            '/': {page: '/'}
        }
    }
}

이런식으로 필요한 path 를 다 생성해줘도 된다.

    exportPathMap: async function () {

        const paths = {
            '/': {page: '/'},
            '/about': {page: '/about'}
        }

        const res = await fetch('https://api.tvmaze.com/search/shows?q=batman');
        const data = await res.json();
        const shows = data.map(entry => entry.show);

        shows.forEach(show => {
            paths[`/show/${show.id}`] = {page: '/show/[id]', query: {id: show.id}};
        });

        return paths
    }

아 너무 졸립다. 2~4시 사이 마의 구간.

TypeScript

패스~

Create AMP Pages

Accelerated Mobile Pages 패스~

Automatic Static Optimization

https://nextjs.org/docs/advanced-features/automatic-static-optimization

정적 파일 최적화관련 이야기인데. getInitialProps 이 있으면 요청/응답을 per page로 처리. 즉, SSR 한다.

근데 이걸.. 이걸 내가 작업할 페이지는 정적인 페이지 없다.

profile
다른 누구와도 같은 시장 육체 노동자
post-custom-banner

0개의 댓글