Next.js 공식문서 파헤치기-1

AeRi Lee·2020년 6월 14일
0

Create a Next.js App

리액트로 웹 애플리케이션을 빌드하기 위해서 고려해야 할 중요한 점들

  • code는 webpack과 같은 번들러를 사용함으로서 번들되어야 하고 babel같은 컴파일러를 쓰면서 변환되어야 한다.
  • code spliting같은 제품 최적화가 필요하다.
  • SEO (Search Engine Optimizaion, 검색 엔진 최적화) 와 퍼포먼스를 위해서 어떤 페이지들은 정적이게 pre-render를 원할 것이다.
  • data store와 react app과 연결하기 위해 서버사이드 code를 써야 할 수도 있다.

framework로는 이런 문제들을 해결할 수 없다. 그러나 이러한 프레임워크들은 올바른 추출?추상화의 수준이 있어야 한다. 그렇지 않으면 이것들은 쓸모 없을 것이다. 또한 수준급의 개발자 경험이 있어야 한다.

Next.js : The React Framework

Next.js는 위에 문제들 모두에 해결책을 제시한다.

  • 라우팅 시스템 베이스의 직관적인 페이지
  • pre-rendering, ssg(static site generation) 과 ssr(server side rendering)이 각 페이지의 기본적으로 지원해준다.
  • 빠른 페이지 로드를 위해서 자동적인 code spliting이 이루어진다.
  • 최적화 된 pre-fetch와 함께 클라이언트 측 라우팅
  • CSS와 SASS 포함. 그 어떤 CSS-in-JS 라이브러리도 지원
  • Hot Module Replacement를 지원하는 개발 환경
  • API endpoints를 build 하기 위한 API routes
  • 완전 확장 가능

이 튜토리얼을 통해 어떻게 Next.js를 시작할 지 배울 수 있다.

setup

먼저 개발환경을 준비하자.

  • 만약 node.js가 설치되어있지 않다면 설치하자. 10.13 버전 또는 그 이후 버전이 필요하다.
  • 각자의 text editor와 terminal app을 사용하면 된다.

Next.js app을 생성하기 위해서 우선 터미널을 열고 cd 치면서 이 프로젝트를 생성하고 싶은 폴더 내로 들어간다.

우선 블로그 만드는 예제로 보자.

npm init next-app nextjs-blog --example "주소"

run the development server

이제 새 디렉토리를 생성해서 cd 로 들어가자.

cd 디렉토리 이름

이제.

npm run dev

이것은 당신의 Next.js의 개발서버를 시작하는 것이다. localhost3000 을 들어가면

라는게 뜰 것이다.

페이지를 수정

이제 스타터 페이지를 수정해보자.

  • 개발서버가 아직 running 중인지 확실히 보자.
  • pages/index.js를 당신의 text editor로 열어라.
  • Welcome to 라고 적힌 h1태그에서 learn으로 바꿔보자.

파일을 저장하는대로 브라우저는 자동적으로 reload되고 업데이트 될 것이다.

Next.js 개발 서버는 Hot Reloading 의 특징을 가진다. 당신이 파일에서 무엇인가를 고치면 자동적으로 반영되어 브라우저에 변화가 생긴다.

Next Up: Creating Pages

자 이제 첫 번째 레슨이 끝났다.

다음은 더 많은 페이지를 만들고 페이지 사이를 이어주는 작업이다.

지금까지는 우리가 생성한 Next.js app은 오직 한 페이지를 가지고 있다. 일반적으로 웹사이트들과 웹 어플리케이션은 많은 다른 페이지들을 가질 수 있다.

이제 우리의 어플리케이션에 어떻게 더 많은 페이지를 더할 수 있을 지 탐구해보자.

What You'll Learn in this Lesson

  • 라우팅 특징을 가진 파일 시스템을 사용하면서 새 페이지를 생성
  • 페이지간에 클라이언트 사이드 네비게이션이 가능하기 위해서 Link컴포넌트를 어떻게 사용하는가
  • 코드 스플리팅과 prefetching을 위한 built-in 서포트에 대해 배우기
npm init next-app nextjs-blog --example "https://github.com/vercel/next-learn-starter/tree/master/navigate-between-pages-starter"

터미널에서 원하는 폴더 안에서 이걸 쳐주면 해당하는 폴더가 생긴다.

cd nextjs-blog를 해준다.

시작은 npm run dev

Pages in Next.js

Next.js에서 page는 pages 라는 디렉토리에서 내보낸 리액트 구성요소이다.
페이지들은 파일 이름을 기준으로 경로와 연결된다.

pages 내에 posts라는 폴더를 만들고 first-post.js라는 파일을 만들어서

export default function FirstPost() {
  return(
    <h1>First Post</h1>
  )
}

를 적고 localhost:3000/posts/first-post 로 들어가면


빈 화면에 이렇게 뜨는것을 볼 수 있다.
컴포넌트는 어떤 이름도 가질 수 있지만 내보낼 때 default로 내보내야 한다.

pages 폴더 내에 JS 파일 손쉽게 생성하고 url path가 어떻게 되는지 보았다. 어떤면에서는 이것은 html 또는 php파일을 사용하여 웹 사이트를 구축하는 것과 유사하다. html를 작성하는 대신 jsx를 작성하고 React Components를 사용한다.

페이지들을 연결할 때 우리는 대부분 html의<a>태그를 사용했다.
Next.js에서는 우리는 <Link>를 사용할 것이다. 이 태그는 <a> 태그를 감싸는 형태이고 이 태그는 응용 프로그램의 다른 페이지로 클라이언트 쪽 탐색을 수행할 수 있다.

첫번째로 pages/index.js에 Link 를 import해야 한다.

import Link from 'next/Link
그리고 h1 태그를 사용해준 뒤 그 밖에 Link 태그를 넣어준다.

원래 a태그 쓰면
<a href="">hallo</a>
Link 쓰면
<Link href=""><a>hallo</a></Link>
이렇게 href위치가 되어야 한다.

이제 우리가 전에 만들었던 first-post.js를 연결해주자.

<Link href="/posts/first-post"><a>this page!</a></Link>
import Link from 'next/link'

export default function FirstPost() {
  return(
    <>
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>back to home</a>
        </Link>
      </h2>
    </>
  )
}

아예 다른 페이지로 이동하는거라면 Link 말고 a태그만 이용하자.
그리고 만약 className같은 속성이 필요하다면 a태그에 넣자. Link태그 말고!

스타일링

Next.js는 기본적으로 CSS와 SASS를 지원하고 있다.
이 튜토리얼에서는 CSS를 쓰게된다.
이번 단원에서는 Next.js가 이미지와 같은 정적 assets와 title 태그와 같은 페이지 메타 데이터를 처리하는 방법에 대해서 설명한다.

  • Next.js에서 어떻게 정적인 파일(이미지)를 추가할 것인가
  • 각 페이지의 <head>안에 있는 것을 어떻게 customize할 것인가.
  • css 모듈을 사용한 스타일된 React Component를 어떻게 재사용성 있게 생성할 것인가
  • pages/_app.js에 어떻게 global CSS를 넣을 것인가
  • Next.js에서의 스타일링에 대한 꿀팁

Assets

먼저, Next.js가 이미지 같은 정적인 assets를 어떻게 handle하는지 얘기해보자.

Next.js는 이런 정적인 파일들을 제일 상위 레벨에 있는 public디렉토리 밑에서 받을 수 있다. public안에 있는 파일들은 pages와 같이 어플리케이션의 root에서부터 참조될 수 있다.

만약 당신이 당신의 어플리케이션에서 pages/index.js를 연다면 <footer>부분을 살펴보아라. 우리는 이렇게 넣을 것이다.

<img src="/vercer.svg" alt="Vercel Logo" className="logo">

logo 이미지는 public 디렉토리 안에 있다.

public는 또한 robots.txt, Google Site Verification 또는 그 어떤 정적인 assets도 유용하게 사용할 수 있다.

만약 우리가 <title>HTML 태그와 같은 페이지의 metadata를 수정하고 싶다면 어떻게 해야 할까?
<title><head>태그의 부분인데 이제 우리는 Next.js페이지에서 어떻게 <head>태그를 수정할 수 있는지 알아볼 것이다.

<Head>
  <title>Create Next App</title>
  <link rel="icon" href="/favicon.ico" />
</Head>

방금 위에서 <head>가 아닌 <Head>를 썼다. 이 <Head>는 Next.js 안에 내장된 React Component로 <head>를 수정하게 허락해준다.

Head 는 'next/head'모듈로 import 해 올 수 있다.
만약 http://localhost:3000/posts/first-post 의 title을 바꾸고 싶다면

import Head from 'next/head'

export default function FirstPost() {
  return(
    <>
      <Head>
        <title>First Post</title>
      </Head>
    </>
  )
}

이렇게 하면 된다.

CSS Styling

pages/index.js를 보면

<style jsx>{`
...
`}</style>

라고 되어있는 styled-jsx라는 라이브러리를 볼 수 있다. 이 라이브러리는 "CSS-in-JS"라이브러리로 React component안에 CSS를 쓸 수 있다. 그리고 CSS 스타일들은 해당 component안에 scoped될 것이다.(다른 컴포넌트에 영향을 주지 않을 것이다.)

Next.js에 styled-jsx가 내장되어있다. 그러나 styled-components나 다른 라이브러리를 사용할 수 있기도 하다.

Layout Component

먼저, 모든 페이지에서 공통적인 layout 구성요소를 만들어보자.

  • components 라고 불리는 상위 디렉토리를 생성하자
  • 그 안에, layout.js 라고 불리는 파일을 생성하자.
function Layout({children}) {
  return <div>{children}</div>
}

export default Layout

그리고 나서 pages/posts/first-post.js 안에 Layout을 import해서 가장 바깥쪽에 두르자.

import Head from 'next/head'
import Link from 'next/link'
import Layout from '../../components/layout'

export default function FirstPost() {
  return (
    <Layout>
      <Head>
        <title>First Post</title>
      </Head>
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>Back to home</a>
        </Link>
      </h2>
    </Layout>
  )
}

Adding CSS

자 이제 Layout을 위한 스타일을 할 것이다. 그러기 위해서, 우리는 CSS Modules를 사용할것이다.

layout.module.css 라는 파일을 components디렉토리 안에 만들자

.container {
  max-width: 36rem;
  padding: 0 1rem;
  margin: 3rem auto 6rem;
}

CSS Modules를 사용하기 위해서 CSS 파일의 이름은 .module.css가 되어야 한다.

Layout 을 사용하기 위해서는

  • styles 를 import 해준다.
  • styles.<class-name>을 className처럼 쓴다.
  • 이 경우에 class name은 container이고 우리는 styles.container를 사용할 것이다.
import styles from './layout.module.css'

export default function Layout({ children }) {
  return <div className={styles.container}>{children}</div>
}

Global Styles

만약 모든 페이지에 어떤 CSS를 로드하고 싶다면 pages 밑에 _app.js 라는 파일을 만들어서 이렇게 적어야 한다.

export default function App({ Component, pageProps}) {
  return <Componnent {...pageProps} />
}

App컴포넌트는 모든 다른 페이지들 사이에 공통적으로 있을 상위 레벨의 컴포넌트이다. App컴포넌트는 또한 페이지 사이에서 state를 유지시키고 싶을 때 사용할 수 있다.

Restart the Development Server

_app.js를 더했다면 develpment server를 다시 시작해줘야 한다. Ctrl + c 를 눌러 server 를 멈추고

npm run dev

Adding Global CSS

Nest.js에서 _app.js에서 import하면 가능하지만 아무데서나 global CSS를 import 할 수는 없다.

_app.js가 아닌 다른 곳에서 import 하게 되면 모든 요소들에게 영향을 끼친다.

그러면 어떻게 해아할까.

  • 가장 상위에 styles디렉토리를 생성하고 그 안에 global.css라는 파일을 만든다.
  • reset css를 넣어보자면
html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  line-height: 1.6;
  font-size: 18px;
}

* {
  box-sizing: border-box;
}

a {
  color: #0070f3;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

img {
  max-width: 100%;
  display: block;

를 써서 _app.js에 import 해준다.

import '../styles/global.css'

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}

만약 안된다면 _app.js를 더했을 때 development server를 재시작 해줬는지 다시 확인해라.

이번 단원 정리

  • css 모듈을 위해서는 *.mocule.css를 써서 어떤 컴포넌트에도 import해서 사용할 수 있다.
  • global CSS는 pages/_app.js 안에 css 파일을 import 해준다.

Polishing Layout

프로필 사진 다운

먼저, 우리는 마지막 디자인을 위해서 프로필 사진을 더해줄 것이다.

  • 프로필 사진 다운
  • public디렉토리 안에 images 디렉토리 생성.
  • images에 이미지 저장

components/layout.module.css업데이트

.container {
 max-width: 36rem;
 padding: 0 1rem;
 margin: 3rem auto 6rem;
}

.header {
 display: flex;
 flex-direction: column;
 align-items: center;
}

.headerImage {
 width: 6rem;
 height: 6rem;
}

.headerHomeImage {
 width: 8rem;
 height: 8rem;
}

.backToHome {
 margin: 3rem 0 0;
}

styles/utils.module.css생성

.heading2Xl {
 font-size: 2.5rem;
 line-height: 1.2;
 font-weight: 800;
 letter-spacing: -0.05rem;
 margin: 1rem 0;
}

.headingXl {
 font-size: 2rem;
 line-height: 1.3;
 font-weight: 800;
 letter-spacing: -0.05rem;
 margin: 1rem 0;
}

.headingLg {
 font-size: 1.5rem;
 line-height: 1.4;
 margin: 1rem 0;
}

.headingMd {
 font-size: 1.2rem;
 line-height: 1.5;
}

.borderCircle {
 border-radius: 9999px;
}

.colorInherit {
 color: inherit;
}

.padding1px {
 padding-top: 1px;
}

.list {
 list-style: none;
 padding: 0;
 margin: 0;
}

.listItem {
 margin: 0 0 1.25rem;
}

.lightText {
 color: #999;
}

components/layout.js 업데이트

import Head from 'next/head'
import styles from './layout.module.css'
import utilStyles from '../styles/utils.module.css'
import Link from 'next/link'

const name = 'Your Name'
export const siteTitle = 'Next.js Sample Website'

export default function Layout({ children, home }) {
 return (
   <div className={styles.container}>
     <Head>
       <link rel="icon" href="/favicon.ico" />
       <meta
         name="description"
         content="Learn how to build a personal website using Next.js"
       />
       <meta
         property="og:image"
         content={`https://og-image.now.sh/${encodeURI(
           siteTitle
         )}.png?theme=light&md=0&fontSize=75px&images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fnextjs-black-logo.svg`}
       />
       <meta name="og:title" content={siteTitle} />
       <meta name="twitter:card" content="summary_large_image" />
     </Head>
     <header className={styles.header}>
       {home ? (
         <>
           <img
             src="/images/profile.jpg"
             className={`${styles.headerHomeImage} ${utilStyles.borderCircle}`}
             alt={name}
           />
           <h1 className={utilStyles.heading2Xl}>{name}</h1>
         </>
       ) : (
         <>
           <Link href="/">
             <a>
               <img
                 src="/images/profile.jpg"
                 className={`${styles.headerImage} ${utilStyles.borderCircle}`}
                 alt={name}
               />
             </a>
           </Link>
           <h2 className={utilStyles.headingLg}>
             <Link href="/">
               <a className={utilStyles.colorInherit}>{name}</a>
             </Link>
           </h2>
         </>
       )}
     </header>
     <main>{children}</main>
     {!home && (
       <div className={styles.backToHome}>
         <Link href="/">
           <a>← Back to home</a>
         </Link>
       </div>
     )}
   </div>
 )
}

pages/index.js 업데이트

import Head from 'next/head'
import Layout, { siteTitle } from '../components/layout'
import utilStyles from '../styles/utils.module.css'

export default function Home() {
 return (
   <Layout home>
     <Head>
       <title>{siteTitle}</title>
     </Head>
     <section className={utilStyles.headingMd}>
       <p>[Your Self Introduction]</p>
       <p>
         (This is a sample website - you’ll be building a site like this on{' '}
         <a href="https://nextjs.org/learn">our Next.js tutorial</a>.)
       </p>
     </section>
   </Layout>
 )
}

까지 4단계를 거치면

완성.

이제 data fetching lesson으로 가자.

profile
👩🏻‍💻 Junior Web Frontend Developer

0개의 댓글