Next.js란?
지금까지는 리액트를 사용하여 CSR로 애플리케이션을 구성했다면 지금부터는 next.js라는 프레임워크에 대해 공부한 것을 정리해보려고 한다. 기본적으로 리액트는 SPA이기 때문에 CSR을 기반으로 운영되어지지만 next.js를 이용하면 서버 사이드 렌더링을 간편하게 적용할 수 있게 된다. 클라이언트 사이드 렌더링의 경우 html 파일이 하나이며 나머지가 모두 js 파일로 이루어져 처음에는 흰색 화면을 가지고 온 후, 자바스크립트 번들을 다운 받고 나서 화면을 렌더링하게 된다. 반면에 next.js를 이용하여 SSR로 작동시키면 pre-rendering을 하기 때문에 기본적으로 html을 먼저 불러와 사용자에게 보여주고 그 후에 리액트에 연결해 어플리케이션을 보여주는 식으로 작동된다.
여기서 한가지, 새롭게 알게된 사실이 있었는데 바로 라이브러리와 프레임워크의 차이이다. 항상 이 부분이 헷갈렸었는데 노마트 코더 Next.js 강의를 들으며 어떤 차이가 있는지를 좀 더 명확하게 알게 되었다.
라이브러리와 프레임워크의 차이
라이브러리라는 것은 특정 기능에 대한 도구나 함수의 집합이라고 할 수 있는데 개발자가 어떠한 기능을 수행하기 위해 도움을 줄 수 있고 원하는대로 코드를 짤 수 있기에 자유도가 높은 것이 특징이다. 반면에 프레임워크는 뼈대나 기반구조를 말하며 프레임워크 내의 규칙에 따라 코드를 적절한 위치에 잘 적어나가면 되는 것이다.
즉, 프레임워크와 라이브러리의 차이를 한마디로 정리하자면 프레임워크는 전체적인 흐름을 가지고 있기 때문에 개발자가 그 안에서 필요한 코드를 작성하면 되는 것이고, 라이브러리는 개발자가 흐름을 가지고 있어 자신이 원하는 기능에 맞춰 원하는 코드를 작성하고, 필요할 때 가져다 쓸 수 있다는 특징을 가진다.
Next.js가 동작하는 방식
Next.js는 기본적으로 백엔드에서 React를 실행시키고 pre-rendering을 하여 html을 생성하고 이를 브라우저에 보내준다. 그 후에 브라우저에서 React를 사용하여 웹페이지를 그려준다.
Next.js의 장점과 단점
pre-rendering을 통해 초기 로딩 속도가 빠르며, 검색엔진 최적화(SEO)가 가능하다. 반면에 서버에 매번 요청을 해야하기 때문에 속도가 느리고 서버에 부하가 올 수 있다.
Next.js 시작하기
1. 먼저 리액트 앱을 실행시켰던 것과 같이 next.js 애플리케이션을 설치해준다.
// 기본 자바스크립트를 사용하는경우
yarn create next-app --typescript
// 타입스크립트를 사용하는 경우
yarn create next-app --typescript
2. 설치가 완료되면 프로젝트 폴더로 들어가서 서버를 실행시킨다.
yarn run dev
3. 서버가 실행되면 로컬호스트 3000으로 접속하면 되는데 이 때 리액트 앱과 비슷하게 이런 시작 화면이 나온다.
4. 기본적인 폴더는 이렇게 생성이 되는데
5. pages 안에 있는 모든 파일을 지우고 index.js 와 about.js라는 파일을 생성해준 후 components 폴더를 만들어 NavBar.js를 만들어주었다. 이때, next.js에서 적용할 수 있는 라우팅 방식을 처음 경험했는데 리액트에서 사용했던 방법에 비해 너무 편하고 간결했던 것 같다.
// index.js -> 기본적으로 index.js는 홈화면이라고 생각하면 된다.
import { useState } from "react";
import NavBar from "../components/NavBar";
export default function Home() {
const [counter, setCounter] = useState(0);
return (
<div>
<NavBar/>
<h1>Hello! {counter}</h1>
</div>
);
}
// NavBar.js
import Link from 'next/link';
import { useRouter } from 'next/router';
export default function NavBar() {
const router = useRouter();
return (
<nav>
<Link href='/'>
<a style={{color: router.pathname === "/" ? "red" : "blue"}}>Home</a>
</Link>
<Link href='/about'>
<a style={{color: router.pathname === "/about" ? "red" : "blue"}}>About</a>
</Link>
</nav>
);
}
// about.js
import NavBar from "../components/NavBar";
export default function Potato() {
return (
<div>
<NavBar/>
<h1>ABOUT!</h1>
</div>
)
}
Next.js 에 대해 새롭게 알게된 점
리액트에서 라우터를 설치하여 라우팅 시켜줬던 방식과는 다르게 각각의 컴포넌트 이름이 중요하지 않고 기본적으로 Pages 안에 있는 파일의 이름이 url의 이름이 된다는 것이 신기했다. 리액트처럼 복잡한 방식으로 처리하지 않아도 되니 간편하게 적용해볼 수 있었고 next.js에서 지원하는 <Link>와 <a>태그를 이용해 손쉽게 라우팅을 시도할 수 있었다.
// NavBar.js
import Link from 'next/link';
import { useRouter } from 'next/router';
export default function NavBar() {
const router = useRouter();
return (
<nav>
<Link href='/'>
<a style={{color: router.pathname === "/" ? "red" : "blue"}}>Home</a>
</Link>
<Link href='/about'>
<a style={{color: router.pathname === "/about" ? "red" : "blue"}}>About</a>
</Link>
</nav>
);
}
하지만 여기에서 <a>태그만을 이용해 라우팅을 시키는 방법은 적절하지 않다고 하는데 그 이유가 <a>태그로 이동을 시킬 경우 매번 누를 때마다 페이지가 새로고침되는 것을 알 수 있었다. 그래서 next.js에서는 링크 태그 안에 <a>태그를 넣어 라우팅하도록 하는데 <Link>태그를 적용할 경우 이전에 받아온 데이터를 다시 요청하기 않기 때문에 보다 더 빠른 속도로 페이지가 넘어가는 것을 알 수 있다. 이 때, <a>태그를 제거해도 작동은 잘 되지만 스타일을 적용하기 위해서는 <Link>태그가 아닌 <a>태그에 적용해야하기 때문에 기본적으로 <Link>안에 <a>태그를 넣어주는 것이 좋은 것 같다.