NextJS는 ReactJS를 바탕으로 만들어진 웹 Front-End 프레임워크이다.
프레임워크다보니, ReactJS에 비해 자유도는 낮지만, 그만큼 정형화/규격화 되어 있어서 협업이 편하고 생산성이 높다.
NextJS는 ReactJS의 SEO문제를 해결하고자 등장했다.
대표적인 CSR 라이브러리인 ReactJS는 Request에 대해 Javascript 코드만을 Response하는데, 이 JS 코드가 최종적인 HTML을 만드는 구조라, JS를 돌릴 줄 모르는 검색엔진이 사이트를 크롤링하면 텅 빈 HTML만 인식하게 되어 검색친화적이지 못하다.
반면, NextJS는 Request가 오면, 서버측에서 먼저 Rendering을 거친 후 HTML과 JS를 따로 Response한다. 따라서, 사용자는 HTML코드를 먼저 받아보게 되고, 그 이후 상호작용에 필요한 JS코드를 받아오기 때문에 사용자 측에서 느린 네트워크 혹은 네트워크 끊김, 모종의 이유로 인한 JS의 미실행 등의 환경에서도 대략적인 페이지의 내용을 마주할 수 있다. 이는 사용자 경험에서 큰 차이다. 또한, HTML 코드를 검색엔진이 바로 받아볼 수 있기에 관련 키워드 검색시 사이트가 검색결과에 노출될 가능성이 커진다.
NextJS 기초 문법
1. 시작하기
npx create-react-app --typescript에 대응되는 코드는 아래와 같다.
npx create-next-app --typescript
2. Pages 폴더
Pages에 들어 있는 파일명으로 라우터가 생성된다. 다시 말해, Pages 폴더 안에 Hello라는 이름의 파일이 존재한다면, 해당 웹앱은 '/hello' 라우터를 갖게 된다. 또한, NextJS는 그 파일 안에 들어 있는 컴포넌트를 작동시킨다.
3. Link
ReactJS의 경우 react-router-dom으로부터 Link를 가져와 <a>를 대신하여 사용한다.
반면, NextJS의 경우 next/link 로부터 Link를 가져와 Link 컴포넌트 안에 <a>태그를 작성하여 사용한다.
즉, ReactJS는 anchor 태그를 대체하여 Link 컴포넌트를 쓰지만, NextJS는 Link 컴포넌트 안에 <a>를 사용한다!
이 차이는 해당 컴포넌트의 속성을 지정해줄 때 큰 차이를 낳는다. React의 경우 Link 태그 안에 className 등의 속성을 지정해주지만, Next는 anchor 태그 안에 className 등의 속성을 지정해줘야한다.
//ReactJS로 구현하는 경우
import { Link } from "react-router-dom";
function Nav() {
return (
<nav>
<Link className="HomeNav" to="/">Home</Link>
<Link to="/login">Login</Link>
</nav>
);
}
export default Nav;
//NextJS로 구현하는 경우
import Link from "next/link";
function Nav() {
return (
<nav>
<Link href="/">
<a className="HomeNav">Home</a>
</Link>
<Link href="/login">
<a>Login</a>
</Link>
</nav>
);
}
export default Nav;
4. CSS 입히기
Styled JSX를 통해 Scope CSS 설정하기
<style jsx>라는 태그 안에 CSS코드를 작성해주면 된다. 이렇게 작성하면 '현재 파일 내'라는 Scope에서만 CSS가 적용된다.
import Link from "next/link";
import { useRouter } from "next/router";
export default function Nav() {
const router = useRouter();
return (
<nav>
<Link href="/">
<a className={router.pathname === "/" ? "user_here" : ""}>Home</a>
</Link>
<Link href="/login">
<a className={router.pathname === "/login" ? "user_here" : ""}>Login</a>
</Link>
<style jsx>{`
nav {
background-color: teal;
}
a {
text-decoration: none;
}
.user_here {
color: blue;
}
`}</style>
</nav>
);
}
위와 같은 코드의 components를 pages 폴더 하위의 index.tsx와 login.tsx에 가져다 넣으면 아래와 같은 결과물이 나온다.
한가지 주의할 점은 style 태그를 <nav> 하위에 집어넣어야 한다는 점이다. 그러지 않을 경우 TS의 경고 메세지를 볼 수 있다.
말 그대로 JSX 문법상 반드시 HTML 요소가 최상위에 존재해야만 한다.
Styled JSX를 통해 Global CSS 설정하기
<style jsx global> 이라는 태그 안에 CSS 코드를 작성해주면 된다. 이렇게 작성하면 현재 파일 내의 코드 뿐만 아니라 그 하위 요소로까지 Scope가 넓어진다. 하지만 이 경우 page 단위로 렌더링 되는 Next 특성상 결국 같은 코드를 여러 번 반복하여 작성하게 되는데, 이를 피하기 위해서는 _app 파일에 대해 알아야한다.
5. _app.js(혹은 _app.tsx) 파일을 통한 page의 전역 설정
_app파일은 pages 폴더 내의 각 페이지가 렌더링 되기 이전, Next가 먼저 확인하는 설정값들이라고 이해하면 된다. 따라서 전역 설정에 관련된 사항들은 이 곳에 모아두면 설정하기도 편할 뿐더러, 관리하기도 편하다.
하지만 위 설명은 엄밀히 말하면 틀린 설명이다. Next.js의 로직에 따르면 각 페이지는 _app파일을 통해 렌더링 되는 것이기 때문이다. 즉 pages 폴더 내의 각 파일을 불러와서 실행시키는 상위 컴포넌트가 바로 _app 파일 내의 함수인 셈.
npx CNA를 통해 Next.js 앱을 만들면 _app.tsx 파일이 자동생성되는데 이 파일을 뜯어보면 위의 코드처럼 나온다.
여기서 Component부분은 우리가 pages 폴더 하위에 작성하여 export defalut 시키고 있는 각 component가 자동으로 들어가게 된다!
앞서 살펴본 예제 코드를 통해 설명하자면, index.tsx 파일 내의 Home, login.tsx 파일 내의 Login 함수가 각 페이지 렌더링시 Component 부분에 들어가게 되는 것이다.
현재 코드를 보면, 결과적으로 _app.tsx의 MyApp 함수는 그렇게 전달 받은 Components를 pageProps와 함께 return 하게 되는데, 우리는 이 코드에 전역설정 하고 싶은 내용을 함께 작성하여 return 해버리면 사실상 전역설정이 되어버린다!
import "../styles/globals.css";
import type { AppProps } from "next/app";
import Nav from "../components/nav";
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Nav />
<Component {...pageProps} />
<div>전역설정입니다. 항상 보여야 해요.</div>
</>
);
}
export default MyApp;
만약 전역 CSS 설정을 하고 싶다면 _app 파일에서 <style jsx>를 통해 설정하면 된다.
더 나아가, 원래 Next.js의 개별 page에서는 커스텀 컴포넌트 외의 다른 파일을 import할 수 없지만, _app 파일에서는 import에 제약이 없으므로, css파일을 _app 파일에서 직접적으로 import 해오는 방법도 가능하다.
'Learning-Log > Computer Science' 카테고리의 다른 글
[아키텍쳐] ARM vs AMD... 어라 그럼 Intel은 어디로..? (0) | 2022.08.22 |
---|---|
[ReactJS] React hook form, 모던 Form을 위한 치트키 (0) | 2022.08.17 |
[도서/AI] '구글 브레인 팀에게 배우는 딥러닝 with TensorFlow.js' 개발자 리뷰 (0) | 2022.08.07 |
[TS] Typescript의 enum, const enum, as const 에 대해 알아보자 (0) | 2022.07.18 |
[WSL2] Vmmem의 RAM 점유율 해결 방법 (0) | 2022.07.17 |