개발/React

NextJS 시작하기

TTOLBE 2023. 1. 2. 16:43

Framework overview

이 글은 노마드 코더의 NextJS 시작하기라는 무료 강의를 듣고 작성되었습니다.

강의링크

1.0 Library vs Framework

1.1 Pages

Next.js에는 기본적으로 pages라는 폴더가 있는데, 그 폴더는 라우터 역할을 한다. 안에 index.js를 만들면 로컬호스트의 메인페이지에 자동으로 렌더링 된다. 만약 about.js를 만들면 /about 페이지에 해당 내용이 렌더링 되는 방식이다. 즉 파일의 이름이 url이 된다. 하지만 그 안의 컴포넌트의 이름은 상관이 없다. 하지만 그안에 렌더링 될 컴포넌트는 default export가 되어야 한다. 또한 next.js는 자동으로 404페이지를 제공해준다. pages 폴더 안에는 반드시 index.js가 들어가야한다. jsx를 사용해도 따로 리액트를 임포트 해올 필요가 없는 점도 장점이다.

1.2 Static Pre Rendering

next.js의 최대 장점은 앱의 페이지들이 미리 렌더링 된다는 점이다. create react app 은 크라이언트 사이드 렌더링을 하는 앱을 만들고, 이 앱안에는 div 하나 뿐이다. 그리고 client-side 자바스크립트가 모든 ui를 만든다. 만약 자바스크립트가 비활성화 된다면 noscript를 보게 된다. 또한 로딩이 느리다면 그냥 흰 화면만 보게 된다. 하지만 next.js에서는 html을 볼 수 있다. 또한 next에서는 state을 사용하면 초기 상태로 html에 prerendering을 한다. 이렇게 react를 프론트엔드 안에서 실행하는 걸 hydration이라고 부른다.

1.3 Routing (08:04)

이번에는 Navbar를 components 폴더안에 만들어보자. Navbar에서 이동에 a 태그를 쓰면 es lint 에서 a tag를 라우팅에 사용하지 말라고 한다. a 태그를 사용하면 브라우저가 다른페이지로 이동할때 완전히 새로고침 되기 때문이다. a 태그 대신 next 자체의 Link 태그를 사용해야 한다.

(강의에서는 a 태그로 텍스트를 감싸주지만 버전이 바뀌면서 에러가 난다. 또한 이젠 Link 태그에 클래스 명을 정해주거나 인라인 스타일을 사용할수 있다. )

import Link from 'next/link';

export default function Navbar() {
  return (
    <nav>
      <Link href="/" >
        home
      </Link>
      <Link href="/about">
        about
      </Link>
    </nav>
  );
}

위와 같은 방식으로 링크태그를 사용해주면 된다. 그러면 웹이 리프레시 되지 않는다.

useRouter 훅에대해 살펴보자.

import Link from 'next/link';
import { useRouter } from 'next/router';

export default function Navbar() {
  const router = useRouter();
  return (
    <nav>
      <Link href="/" className="dd" style={{ color: 'red' }}>
        home
      </Link>
      <Link href="/about">about</Link>
    </nav>
  );
}

router를 콘솔에 찍어보면 router에서 location 정보를 얻을 수 있단 걸 알수 있다. useRouter를 통해 현재 페이지에 따른 내비게이션 색을 바꿔보자.

import Link from 'next/link';
import { useRouter } from 'next/router';

export default function Navbar() {
  const router = useRouter();
  return (
    <nav>
      <Link
        href="/"
        className="dd"
        style={{ color: router.pathname === '/' ? 'red' : '#000' }}
      >
        home
      </Link>
      <Link
        href="/about"
        style={{ color: router.pathname === '/about' ? 'red' : '#000' }}
      >
        about
      </Link>
    </nav>
  );
}

1.4 CSS Modules

Navbar에 css 모듈을 적용해보자. NavBar.module.css 라는 파일을 만들고, 그안에 nav 라는 클래스를 하나 생성하자. 그리고 그안에 원하는 스타일 요소들을 넣는다. 다시 NavBar.js 파일로 와서 임포트해주자.

import styles from './NavBar.module.css';

그리고는 jsx에 클래스 명을 className={styles.nav} 라고 적으면, 스타일이 적용된다.
css 모듈의 장점은 클래스 이름 충돌이 일어나지 않는다는 점이다.

1.5 Styles JSX (06:56)

Styles jsx는 NextJS 고유의 스타일링 방법이라고도 할 수 있다. 우선 컴포넌트안에 style 태그를 열고, jsx attribute를 추가해준다. 그 다음 그안에 중괄호를 연다. 중괄호 안에 백틱도 넣는다.

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

아래처럼 작성하면 스타일이 적용 된다.

import Link from 'next/link';
import { useRouter } from 'next/router';

export default function Navbar() {
 const router = useRouter();
 return (
   <nav>
     <Link
       href="/"
       legacyBehavior
       style={{ color: router.pathname === '/' ? 'red' : '#000' }}
     >
       <a>home</a>
     </Link>
     <Link
       href="/about"
       legacyBehavior
       style={{ color: router.pathname === '/about' ? 'red' : '#000' }}
     >
       <a>about</a>
     </Link>
     <style jsx>{`
       nav {
         background-color: tomato;
       }
       a {
         font-size: 24px;
       }
     `}</style>
   </nav>
 );
}

1.6 Custom App

우선 Global Style을 설정하는 방법을 알아보자.

style jsx 태그에 global attribute만 추가해주면 된다. 그런데 이렇게 할 경우에는 그 해당 페이지에만 적용된다. 전체적으로 적용하기 위해선 어떻게 해야할까. 이럴 땐 모든 페이지의 청사진이 되는 App component 가 필요하다. pages 파일에 _app.js 라는 파일을 만들어주면 된다. NEXT.js는 전부 렌더링 하기 전에 _app.js 파일을 참고 할 것이다. 이 파일은 두개의 props를 불러온다.

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

이렇게 하고 앱을 실행하면 여전히 동일하다. 이번에는 이 안에 다른 요소를 넣어보자.

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

이렇게 하면 모든 페이지에 hello 가 출력되는 모습을 볼수 있다. 그리고 이 _app.js 파일에 global style을 추가해주면 전체적으로 먹힌다.