Next.js 프레임워크의 이해
강호준2024-07-13
문법Next.jsNext.js 14취준포폴
공식문서
Getting Started: Project Structure
packege.json 생성
- npm init -y
패키지 설치
- npm install react next react-dom
실행
- package.json에서 scripts에서 dev 모드 next dev 바인딩으로 수정
- npm run dev 하면 next js 기반으로 개발자 모드 실행
app/url/page.tsx
- 기본적으로 app 디렉토리에서 url 이름으로 폴더를 생성한 뒤 page.tsx 이름으로 파일을 생성하여 아래의 export defalut가 반드시 있어야 한다. 이름으로 찾기 때문에 next는 이렇게 해줘야함ㅇ
export default function Tomato(){
return <h1>NextJs!</h1>
}
이름이 정해져 있는 파일들
page.tsx
- ui로 인식하는 하나의 메인 파일ㅇㅇ
디렉토리(url)
- page파일이 있는 폴더를 하나의 url로 인식함.
not-found.tsx
- 이건 오류 페이지임 ㅇㅇ 제일 상위에 1개만 만들어도 됨.
navigation.tsx
- 이건 네비게이션임.
layout.tsx
- 이거 layout임 baseComponents와 똑같음. 여기서 푸터랑 이거저거 하기 ㅇㅇ
- 해당 파일은 해당 디렉토리의 baseComponents임.
- 이를 테면 root에 하면 root 디렉토리의 베이스 컴포넌트가 되지만, about us 디렉토리에 넣으면 root에선 보이지 않고 about us의 하위 디렉토리부터 about us까지의 베이스 컴포넌트가 되는 것임ㅇ
loading.tsx
- 로딩 페이지 만들기
- 이건 page와 항상 같은 레벨에 있어야 함.
error.tsx
- 에러 페이지
- 부모 page와 같은 레벨에 존재 부모 page가 사용한 자식의 함수에서 에러가 발생해도 부모 페이지에선 멀쩡히 작동하고, 자식 부분에서 에러 발생
- 항상 use client 여야 함.
함수 & 기능
usePathname()
- 현재 경로명을 가져오는 함수 CSR에서만 사용 가능
- 페이지 상단에 “use client” 붙여야 함.
use client
- 모든 페이지(SSR, CSR)는 백엔드 단에서 먼저 렌더링
- 이후 CSR들만 js 파일을 계속 렌더 시켜줌
- defalut 값은 SSR인데 CSR을 그럼 어떻게 설정하냐? → ‘use client’ 최상단에 바인딩
- 우린 hydratin 하게 갈 예정 CSR을 꼭 필요한 부분에만 사용하면 시간을 굉장히 아끼는 거임 ㅇㅇ
- client 사이드에서 server 사이드로 가는 건 불가능
- 즉, 메인이 되는 page.tsx는 client 없이 서버 사이드에서만 돌린다면 해당 파일의 js는 클라이언트로 넘어가는 일이 없음. 여기서 DB와 통신하고 api key를 사용해도 보안에 전혀 문제가 없다는 사실
디렉토리명 ()로 감싸주기
- (home) → 이렇게 하면 그룹화임 url로 바꿔주는 것이 아닌 그저 그룹으로 묶어줌ㅇㅇ
Meta Data
-
client에게 주는 정보임ㅇㅇ 이걸 이용해서 SEO에 좋은 영향을 미칠 수 있음.
-
이걸 잘 써야 하는데, 내가 생각한 걸론 블로그의 유저 마다 타이틀 및 배너 마다 타이틀과 디스크립션을 다르게 줄 수 있음. 정말 어썸함.
-
아래는 메인 레이아웃의 어썸한 코드 각각 page.tsx에서 title만 바인딩 해주면 어썸하게 변경
export const metadata :Metadata = {
title: {template: "%s | Next Movies",
default: "Loading...",
},
description: 'The Best Movies on the best',
};
디렉토리에 대한 정보
- 소괄호 → 디렉토리로서 사용하겠다는 의미임. url 취급 x
- 대괄호 → 동적 라우터로 사용하겠다는 의미임. 상위 url/뭐가 오든 동적으로 인정
- 아래 같은 경우 /movies/아무거나
- 괄호 없음. → 정적 라우터로 사용하겠다는 의미임.
동적 라우팅
- 대괄호 디렉토리를 쓰면 됨.
- 아래와 같이 props로 받은 map 데이터를 살펴보면 디렉토리명인 id를 키로 url이 전송된 것을 확인할 수 있음. 이걸 이용해서 DB와 연동하고 재미있는 작업을 많이 할 수 있을 것 같음.
- 이런 식으로 url의 region, page 등 searchParams로 받아올 수 있음. 이걸 이용해서 또 재미있는 것들 할 수 있을 것 같음. 이를 테면 내 블로그 글을 page로 해서 읽을 수 있게 하거나 하는 등ㅇㅇ
CSR에서의 fetch → 일반적인 프레임워크는 이렇다
- useState로 관리 / Loding Page의 상태 등을 직접 관리 해야함.
- client 방식이기에 API KEY가 노출 될 위험이 있음.
'use client';
import { useEffect, useState } from "react";
// export const metadata = {
// title: "Home",
// }
export default function Page(){
const [isLoading, setIsLoading] = useState(true);
const [movies, setMovies] = useState();
const getMovies = async () => {
const response = fetch("https://nomad-movies.nomadcoders.workers.dev/movies");
const json = await (await response).json();
setMovies(json);
setIsLoading(false);
}
useEffect(() => {
getMovies();
})
return (
<div>
{isLoading? "Loading...." : JSON.stringify(movies)}
</div>
)
}
SSR에서의 fetch
export const metadata = {
title: "Home",
}
const URL = "https://nomad-movies.nomadcoders.workers.dev/movies";
async function getMovies() {
return fetch(URL).then(response => response.json());
}
export default async function HomePage(){
const movies = await getMovies();
return (
<div> {JSON.stringify(movies)} </div>
)
}
fetch에서의 비동기 처리(구버젼)
- fetch를 하는데 순차적으로 이루어지면 문제가 있음 ㅇㅇ
- 만약에 아래처럼 두개의 함수가 있으면 순차적으로 실행이 아니라 동시에 가져와야 함ㅇㅇ
- 그럴 때 바로 이렇게 해야함
- Promise.all 함수를 사용해서 배열 형태로 묶어서 await를 한번에 주는 것 그러면 동시에 시작
fetch에서의 비동기 처리(개정판)
- 위에서 한 방식은 좋은 방식일지도 모르나, 모든 함수가 끝나야만 실행이 됨. 경우에 따라 좋을 수도 있음.
- 동시에 병행으로 진행하고 먼저 된 부분만 보여주면 나머지도 기다리기 좋지 않을까?
- 이런 생각이 들었다면 Suspense를 사용해야함.
- Suspense는 React에서 제공하는 강력한 기능
- 아래와 같이 컴포넌트 디렉토리에 따로 만들어두기