목차
Next.JS
Next.js는 서버 사이드 렌더링(SSR), 정적 웹 페이지 생성 등 React.js 기반 웹 애플리케이션 기능들을 가능하게 하는 Node.js 위에서 빌드된 오픈 소스 웹 개발 프레임워크입니다.
Creating a Next.JS Project
Next.JS 프로젝트를 생성 하기 위해선 선행 조건은 Node.js를 설치 해야합니다. 설치 주소 : DownloadSite 보편적으로 추천 하는 버전은 *LTS(Long Term Support)입니다.
설치 이후 cmd(명령 프롬프트[터미널])에서
npx create-next-app@latest
(js,jsx)
or
npx create-next-app@latest --ts
(ts,tsx)
입력하고 실행하면, 프로젝트 이름 설정 내용이 나오고
? What is your project named? » {my-app}
이름 설정 후 진행하면 프로젝트 이름으로 된 폴더 안에 프로젝트 파일 받고 생성시켜 줍니다.
그 후 프로젝트가 생성 된 폴더 안에서 npm run dev
를 실행하고 컴파일과 서버가 성공 된 메세지 출력 후 알려준 주소로 브라우저에 접속하면 동작 중인 웹페이지를 볼 수 있습니다.
*LTS(Long Term Support) : 일반적인 경우보다 장기간에 걸쳐 지원하도록 특별히 고안된 소프트웨어의 버전 또는 에디션. 안정성에 중점을 둔 버전으로 생각하면 됩니다.
Framework vs Library
1. Framework
Framework는 어떠한 목적을 달성하기 위해 페이지 구현, DB 관리, 유저 인증, API 서버, Routing, 사이트맵, 세션 관리, Library 등.. 각 기능을 한데 묶어 담은 구조(뼈대) 또는 작업도구로 볼 수 있습니다.
예시로 Next.JS Framework CNA(crate-next-app)를 통해 웹페이지 및 페이지 이동을 개발 해봅시다.
-
우선, 프로젝트를 생성하게 되면, 아래와 같은 구조로 만들어집니다.
-
여기서 다음과 같이 컴포넌트를 pages폴더 안에 about.js, 폴더 밖에 content.js 컴포넌트롤 만들었습니다.
-
그리고 서버를 띄우고 ”http://localhost:3000/about”에 접속하면 아래 그림과 같이 웹페이지를 볼 수 있습니다. 하지만 ”http://localhost:3000/content”에 접속하면 웹페이지를 찾을수 없다고 보입니다.
위의 과정을 통해 개발자는 프레임워크가 제공한 pages폴더 안에 컴포넌트를 만들어 내보냈을 뿐인데 Next.js Framework에서 파일이름에 url매핑을 해주고 해당주소에 접근하면 웹페이지로 보여준다는 것과 pages폴더 밖에 만든 컴포넌트는 url매핑 기능을 제공 받지 못했다는 것을 알 수있습니다.
즉, Framework가 전체적인 흐름(Flow)의 주도성을 가지고, 사용자가 그 안에서 필요한 코드를 코딩하며 개발하는 방식입니다.
정리하자면 Framework 특징으로는 아래와 같이 있습니다.
- 개발자들이 개발 할때 따라야 할 가이드라인을 가진다.
- 개발할 수 있는 범위가 정해져 있다.
- 개발하기 위한 다양한 기능을 가진 도구들이 지원 된다. (Library 포함)
-
개발자가 작성한 코드를 Framework에서 제어한다. (제어의 역전[Ioc])
그렇기에 Framework 장단점으로는 아래와 같이 있습니다.
- 개발의 자유도가 떨어집니다.
- 개발의 편의성과 생산성이 오릅니다.
- 어느 정도의 코드 품질을 보장합니다.
- 유지 보수하기가 수월해집니다.
2. Library
Library는 특정 언어의 개발 환경에서 바로 실행될 수 있도록 모듈화된 프로그램 모음입니다.
예시로 React.JS Library CRA(crate-react-app)를 통해 웹페이지 및 페이지 이동을 개발 해봅시다.
-
우선, 프로젝트를 생성하게 되면, 아래와 같은 구조로 만들어집니다.
-
그리고 사용자가 자유롭게 필요 없는 파일과 코드들을 정리해서 아래와 같이 바꿀 수 있습니다.
-
서버를 띄우고 ”http://localhost:3000/“에 접속하면 웹페이지에 성공적으로 접속 할 수있습니다.
- Next.js처럼 페이지 이동 기능은 제공하지 않기에 추가적으로 필요한 기능을 개발 하기위해 React-Router-Dom을
npm -i react-router-dom
추가적으로 설치 해줘야합니다. -
자유롭게 파일을 만들고 페이지를 이동할 컴포넌트롤 만들고 설치한 react-router-dom Libarary 기능을 사용하여 url매핑과 컴포넌트를 연결해주고 정해준 주소로 접근하면 웹페이지로 보여준다는 것을 알 수 있습니다.
위의 과정을 통해 개발자는 필요한 기능을 직접 구현하지 않고 필요한 기능을 가진 Library를 활용하여 쉽게 url매핑과 컴포넌트 연결을 할 수 있습니다.
즉, 사용자가 전체적인 흐름(Flow)의 주도성을 가지고, Libarary를 사용하여 이미 구현되어 있는 기능들을 활용하여 개발 하는 방식입니다.
Library 장단점으로는 아래와 같이 있습니다.
- 이미 구현되어 있는 기능들을 가져다 쓸 수 있어 코딩 시간을 단축할 수 있다.
- 전체적인 흐름(Flow)을 직접 제어해야 하기에 Framework에 비해 개발의 생산성이 떨어진다.
-
Library사용에 대한 제어는 사용자이기에 개발을 자유롭게 할 수 있다.
결론적으로 Framework와 Library의 큰 차이점은 Application의 Flow(흐름)을 누가 쥐고 있는냐에 달려있습니다.
Next.js의 기본 특징
1.Pages
pages경로 아래의 [name].js 컴포넌트를 만들고 아래 형식으로 구성요소를 내보내는 것으로 nextjs에서 url를 매핑 시켜줍니다.
예시) url : /about -> folder : pages/about.js
// url : /about -> folder : pages/about.js
export default function TestComponent() {}
// Function name은 url매핑과 관련이 없다.
//or
const TestComponent = () => {};
export default TestComponent;
//or
export default () => {};
참고로 index.js는 url이 ”/“로 잡혀 있습니다.
2. Pre Rendering
Next.js의 좋은 기능 중 하나로 볼 수 있습니다. 빌드 타임 때 해당하는 각 페이지별로 각각의 HTML 문서를 미리 생성해 가지고 있다가 요청이 들어올 때 알맞은 페이지를 반환해 주는 것입니다.
위의 그림을 참고해서 이야기 하자면 React.js App에서는 자바스크립트가 로딩이 끝나고 코드를 읽어 클라이언트 단에서 모든 추가 렌더링을 담당했다면, Next.js Framework에서는 미리 생성된 HTML이 보여진 다음 자바스크립트가 로딩 되었을 때, 기본적으로 이미 존재하는 것들과 연결(hook)이 되어서 일반적인 React.js앱이 됩니다.
그리고 Next.js에서 Pre-Rendering을 하기 위해 두가지 형식이 있습니다.
- Static-Generation (추천) : HTML을 빌드 타임에 각 페이지별로 생성하고 해당 페이지로 요청이 올 경우 이미 생성된 HTML 문서를 반환한다.
- Server-Side-Rendering : 요청이 올 때 마다 해당하는 HTML 문서를 그때 그때 생성하여 반환한다.
3. CSS Support
- Styled JSX (CSS in JS 방식)
또 다른 CSS 적용 방법으로는 Styled JSX가 있습니다.
<div className="test"></div>
<style jsx>{`
.test {
text-decoration: none;
}
`}</style>
컴포넌트 내에서 위에 구조를 잡아주고 안에 css 코드를 넣어주면 됩니다. 주의할 점으로는 해당 컴포넌트에 있는 엘리먼트들만 적용됩니다.
// compontnts/Test.js
export default function Test() {
return (
<a className="test"></a>
);
}
// /pages/test1.js
<Test />
<a className="test1"></a>
<style jsx global>{`
a {
text-decoration: none;
}
`}</style>
jsx뒤에 global을 추가해주면 이 컴포넌트 내에 있는 “모두”에게 적용 시켜줄 수 있습니다. 대신 다른 페이지에 이동하게되면 그 페이지 컴포넌트 내에도 추가 적용해줘야합니다.
- CSS Modules (External CSS방식)
Next.js에서 CSS를 추가하는 방법은 [name].module.css 파일을 만들어서 적용하는 방법이 있습니다. 그리고 css style을 활용할 컴포넌트에서는 import styles from ”./[name].module.css” 임포트를 하면됩니다.
예시)
//[name].module.css ( .nav {} )
import styles from "./[name].module.css";
<div className={styles.nav}></div>;
// -> <div class=".jsx-3751109d2af3e369">
또 하나 장점은 Next.js에서 같은 클래스이름이 충돌하지 않도록 무작위화 해줍니다.
- Custom App Component (External CSS방식)
마지막으로 Global Styles이 있습니다.
이 특정 컴포넌트는 Next.js에 의해 사용되는데 *.css를 호츌해서 적용될 수 있으며 렌더링하길 원하는 페이지 컴포넌트를 Component Prop으로 넣어서 자동으로 랜더링합니다.
개발자가 렌더링하기 위해 템플릿을 설정하기 원한다면 _app.js파일을 정의해주면 됩니다.
예시)
/* /component/NavBar.module.css */
.link {
text-decoration: none;
}
.active {
color: black;
}
// /component/NavBar.js
import Link from "next/link";
import { useRouter } from "next/router";
import styles from "./NavBar.module.css";
export default function NavBar() {
const router = useRouter();
return (
<nav>
<Link href="/">
<a>Home</a>
</Link>
<Link href="/about">
<a>About</a>
</Link>
<Link href="/testcomponent">
<a
className={[
styles.link,
router.pathname === "/testcomponent" ? styles.active : "black",
].join(" ")}
>
TestComponent
</a>
</Link>
<Link href="/testcomponent1">
<a
className={`${styles.link} ${
router.pathname === "/testcomponent1" ? styles.active : "black"
}`}
>
TestComponent1
</a>
</Link>
<Link href="/testcomponent2">
<a
className={`${styles.link} ${
router.pathname === "/testcomponent2" ? styles.active : "black"
}`}
>
TestComponent2
</a>
</Link>
<style jsx>{`
nav {
background-color: tomato;
}
a {
text-decoration: none;
}
`}</style>
</nav>
);
}
// /pages/_app.js
import styles from "../styles/globals.css";
function App({ Component, pageProps }) {
return (
<>
<NavBar />
<Component {...pageProps} />
<style jsx global>{`
a {
color: green;
font-size: 50px;
}
`}</style>
</>
);
}
export default App;
3. Dynamic Router
nextjs에서는 pages경로 아래로 폴더 구조와 파일이름으로 url을 매핑 해줍니다.
예시) url : /[name] -> folder : pages/[name].js
url : / -> folder : pages/index.js
url : /about -> folder : pages/about.js
url : /movies -> folder : pages/movies/index.js
url : /movies/all -> folder : pages/movies/all.js
url : /movies/movie1 -> folder : pages/movies/movie1.js
(Nested Routing)
하지만 정해진 url이 아닌 가변적인 여러 url에 하나의 컴포넌트를 적용해주려면
url : /movies/1 or /movies/2 or /movies/3 -> folder : pages/movies/[variable_name].js
위와 같은 형식으로 해주면 됩니다.
Catch all방식은 파일 이름을 예시로 /movies/[…params].js 해준다면 /movies/1/2/3
모든 주소 경로 내역들을 query안에 params를 키값으로 가지는 배열로 담아줍니다.