All Articles

wecode 10주차_1일 TIL_공식문서와 함께하는 둘둘의 Next.js 도전기

image.png

Next.js를 한번 써보았다! 리액트랑 비슷한데.. 리액트만 쓰다가 이걸 써보니 진짜 신박하다!

내가 썼던 React가 Client Side Rendering(CSR) 방식 이었다면, Next는 Server Side Rendering(SSR)방식이다. 리액트에선 프론트부분을 작성하고 데이터는 백앤드 서버에서 받아오는 방식이었다. 클라이언트 따로, 서버 따로.. 각각 작성해야 했는데! Next.js는 이 과정을 따로 해줄 필요 없이 한방에 뙇!!! 하는거라고… 이해하면 되려나?

시작하기

mkdir hello-next // 아무 이름의 폴더 생성
cd hello-next // 만든 폴더로 이동고고
yarn init -y // 초기화 해주기
yarn add react react-dom next // next와 react 깔기
mkdir pages // pages 폴더 만들기

여튼… 내 프로젝트 안에 pages 폴더를 만들고 code .으로 vscode를 켜준다! 여기서 젤 중요한게 pages 폴더를 만드는 일이다. React는 모든 js파일을 src폴더 하에서 시작하는것처럼 Next.js는 pages에서 모든 것이 시작된다고 한다!

package.json에 추가

{
  "name": "hello-next",
  "version": "1.0.0",
  "license": "MIT",
  "scripts": {
     "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "^2.1.0",
    "react": "^15.4.2",
    "react-dom": "^15.4.2"
  }
}

이걸 추가해줌으로 우린 yarn run dev 명령어로 프로젝트를 시작할 수 있다.

어찌됐든 명령어를 입력하면..

image.png

터미널에 ready, event, wait 등의 메시지가 색깔색깔별로 뜬다. 명령어 입력 후 3000 port로 접속해 보자..!

image.png

404 error가 뜬다!

image.png

Next.js 공식 문서의 learn 페이지에 가면 퀴즈와 함께 설명이 있는데 에러가 날지 모르고 3번을 눌렀으나 답은 2번이였닼ㅋㅋ 왜 에러가 난거지 index.js 파일이 없어서 그런듯?? 만들어주자.

const Index = () => (
    <div>
        <p>Hello Next.js</p>
    </div>
)

export default Index;

신기하게 Next.js는 react를 import 안해와도 된다 ㅋㅋ 신기씐기!

About page 만들기

export default () => (
    <div>
        <p>This is the about page</p>
    </div>
);

image.png

터미널엔 이러한 글자들이 뜬다!!! react때랑은 다르게 페이지 하나 하나마다 build되고 compile되는 과정을 글자로 알려준다 ㅋㅋ

Link태그

컴포넌트를 만들고 나서 import를 안 해도 되는것도 신기했지만 더 신기했던건 Link. Next.js 안에 Router가 내장되어있기 때문이다 ㅋㅋ Link 기능을 쓰려면 import Link from 'next/link' 이거 한줄 써서 import 해야하긴 한다. router를 다운로드는 안 받아도 된다 ㅋㅋ

import Link from 'next/link'

const Index = () => (
    <div>
        <h1>
            안녕, Next.js
        </h1>
        <h2>
            <Link href="/about">
                <a>소개</a>
            </Link>
        </h2>
    </div>
);

export default Index;

리액트는 Link 안에 to를 썼지만, Next는 to 대신 href를 써준다. 그리고 Link Component 내부엔 또 다른 컴포넌트가 들어가거나 element가 들어가야 한다!!

공식문서에 따르면… We know that Next.js is all about pages. We can create a page by exporting a React component, and putting that component inside the pages directory. Then it will have a fixed URL based on the file name.

그니까 파일이름 그 자체가 걍 url의 이름이 되는 것..!! 리액트땐 Routes.js 들어가서 직접 이름을 설정해줬는데 Next는 걍 파일이름 자체가 url 경로

Header 만들기

component라는 폴더를 만들고 그 안에 Header.js 파일은 만들어놓은 상태다.

import Link from 'next/link';

const linkStyle = {
    marginRight: '1rem'
}
const Header = () => {
    return (
        <div>
            <Link href="/"><a style={linkStyle}>홈</a></Link>
            <Link href="/about"><a style={linkStyle}>소개</a></Link>
        </div>
    );
};

export default Header;

이렇게 하면 Header라는 파일에 home과 about으로 가는 경로가 써 있으니깐 이걸 또 import 해서 모든 페이지에 붙이면 되겠지! 근데 이것보다 더 간편한 방법이 있다..

Layout 만들기

import Header from "./Header"

const layoutStyle = {
    margin: 20,
    padding: 20,
    border: `1px solid #DDD`
};


const Layout = props => (
    <div style={layoutStyle}>
        <Header />
        {props.children}
    </div>
);

export default Layout;

Header Component를 불러오고 그 밑엔 props의 자식 컴포넌트가 들어오도록 props로 넘겨주는 방식..! 오.. 신박해!

이렇게 해줬으면 인제 각 페이지에서 Header 컴포넌트를 제거하고 가장 바깥쪽 div를 Layout Component로 감싸주면 된다.

import MyLayout from "../comp/MyLayout"

export default function About() {
  return (
    <div>
      <MyLayout />
      <p>This is the about page</p>
    </div>
  )
}

요런식으로! ㅋㅋㅋㅋㅋ 그럼 이렇게 뙇!

image.png

근데… 암만 봐도 난 이 과정들이 넘 비효율적인것 같다 ㅠㅠ

리액트에선 NavBar 컴포넌트 만든걸 그냥 Routes.js파일 안에 넣으면 끝이었는데 뭐가 이렇게 번거로운지… 내가 아직 잘 몰라서 그런건가! 분명 더 간편한 방법이 있을것 같은데.. 지금으로썬 모르겠다 ㅠㅠ

image.png

공식문서 퀴즈에서.. props.children 지워보래서 지워봤는데 아무일도 일어나지 않았고 그래서 1번을 골랐을 뿐인데 틀렸댄다 ㅠㅠㅠ

그래서 정말 파일 토씨 하나 틀리지 않게 하려고 완전한 복붙 후 다시 props.children을 지워보았다. Like this!

import Header from './Header'

const layoutStyle = {
  margin: 20,
  padding: 20,
  border: '1px solid #DDD'
}

export default function Layout(props) {
  return (
    <div style={layoutStyle}>
      <Header />
      {/* {props.children} */}
    </div>
  )
}

그랬더니…!!!

image.png

드디어 아무 내용도 뜨지 않았다!!! 역시 공식문서의 말을 잘 들어야 한다…ㅋㅋㅋ 여튼… 위와 같은 Layout 파일을 만들거면 인자로 props를.. 그 아래엔 props.children을 꼭 써주자.

HOC 방식으로 해보기

import Header from './Header';

const layoutStyle = {
  margin: 20,
  padding: 20,
  border: '1px solid #DDD'
};

const withLayout = Page => {
  return () => (
    <div style={layoutStyle}>
      <Header />
      <Page />
    </div>
  );
};

export default withLayout;

withLayout을 정의해주고… 각각의 컴포넌트에 withLayout을 export 해준다 이렇게!

import withLayout from '../components/MyLayout';

const Page = () => <p>Hello Next.js</p>;

export default withLayout(Page);

넘나 신기한것… 아직 HOC 방식으로 코드를 쳐보지 않았는데 대충 이런 느낌이었군!

props로 넘겨주는 방법쓰

import Header from './Header';

const layoutStyle = {
  margin: 20,
  padding: 20,
  border: '1px solid #DDD'
};

const Layout = props => (
  <div style={layoutStyle}>
    <Header />
    {props.content}
  </div>
);

export default Layout;

같은 방식이긴 한데.. 인자로 props가 들어가고 아래엔 props.content를 써준다.
이 Layout을 적용할 각각의 폴더에는..!

import Layout from '../components/MyLayout.js';

const indexPageContent = <p>Hello Next.js</p>;

export default function Index() {
  return <Layout content={indexPageContent} />;
}

props의 content에 들어갈 부분을 변수로 정의해주고 return 값에는 Layout Component를 불러주고 그 요소로 contetn={위에서 선언한 변수}를 넣어준다. 아… 이건 진짜 핵 귀찮은 방법인거 같다 ㅠㅠㅠㅠ

일단은 글이 길어질것 같으니 다음 포스팅에 이어서…☆