NEXT
https://nextjs.org/learn
NEXT 14를 사용하자
리액트 베이스의 풀스택이다!
폴더가 라우터다
(폴더이름)내 맘대로 만들고
그안에 들어가는 구성요소는 page, layout, template 이름 고정이다
ex) about 폴더
1. mkdir app/about (Route Folder)
2. make app/about/layout.tsx
3. make app/about/page.tsx
4. nav to page from Home(app/page.tsx)
서버에서 이루어진다.
위쪽에 “use client”는 Next.js 13 이상에서 도입된 기능으로, 컴포넌트가 클라이언트 컴포넌트임을 명시하는 선언입니다.
프리티어(위에 임포트 순서 설정)
.prettierrc
{
"singleQuote": true,
"jsxSingleQuote": true,
"semi": true,
"trailingComma": "es5",
"plugins": ["@trivago/prettier-plugin-sort-imports"],
"importOrder": [
"^next$",
"^next/\\w*$",
"^next/(.*)$",
"^react$",
"^react/(.*)$",
"^@/lib/(.*)$",
"^[./]"
]
}
>에서 importOrder의 내부 순서를 바꾸어주면 import되는것들의 순서를 지정해줄 수 있다.
yarn dev
yarn build -> yarn start
차이를 알아두기(dev에서는 계속 시간같은거 업데이트 가능하지만, start에서는 배포용이라서 딱 그 시점?이 올라감, 따라서 다이나믹하게 만들어줘야함)
useRouter (only Client Component)
'use client'; > 이거는 이제 클라이언트(=브라우저)에서 실행이 되게끔한다!!!
//클라이언트 컴포넌트에서는 어싱크(async)를 못 쓴다.
// useRouter
import { useRouter } from 'next/navigation'
const router = useRouter()
router.push('/dashboard', { scroll: false });
// another functions
router.back();
useSearchParam
??
다이나믹하게 페이지
// /hi/[time]/page.tsx
export default function HiTime({ params }: { params: { time: string } }) {
return <div>Good {params.time}!</div>
}
()는 경로에 영향을 미치지 않음(정리용)
/app
/(auth)
/login/page.tsx
/dashboard/page.tsx
여기서 (auth)는 그냥 더 가독성 좋게 보일려고하는거임
인터셉트
client router와 server router를 다르게 표현
next/link/Link를 이용해야 intercepting 됨.
A → B(intercept) → B(refresh)
(.) 같은 레벨/depth
(..) 하나 위 레벨
(...) Root 레벨
(..)(..) 두개 위 레벨
원래 원본의 파일이 있는데 그 파일로 이동하는 것이 아닌 내가 만든 인터셉트 페이지로 이동을 시킨다(이것은 새로고침하면 원본페이지로 이동이 된다),
(.)/ (..) / (…) 같은경우는 그냥 폴더 위치에 따른 경로 느낌
[[]] 대괄호 두개
[[...params]]와 같은 형태는 Next.js에서 Catch-All 라우팅을 사용할 때, 대괄호를 2개 사용하는 방식입니다. 이것은 동적 경로를 정의할 때 매우 유용합니다. 대괄호 두 개([[...]])는 특정 경로가 **선택적 동적 경로(선택적 Catch-All)**임을 의미합니다.
1. [...params] (Catch-All 라우팅):
설명: [...]를 사용하면 URL의 나머지 부분을 하나의 배열로 캡처할 수 있습니다.
예시: /pages/blog/[...slug].tsx
이 경우, blog 경로의 하위 모든 경로가 slug 배열로 캡처됩니다.
예를 들어:
/blog/hello/world → { slug: ['hello', 'world'] }
/blog/my-post → { slug: ['my-post'] }
2. [[...params]] (선택적 Catch-All 라우팅):
설명: 대괄호 두 개([[...]])를 사용하면 선택적 동적 경로가 됩니다. 즉, 이 경로는 있어도 되고 없어도 되는 선택적 경로입니다.
예시: /pages/blog/[[...slug]].tsx
이 경우, blog 경로는 동적 경로가 없어도 매칭이 됩니다.
예를 들어:
/blog → { slug: [] } (빈 배열)
/blog/hello/world → { slug: ['hello', 'world'] }
/blog/my-post → { slug: ['my-post'] }
요약:
[...params]: Catch-All 동적 경로로서, 지정한 경로 이후의 모든 부분을 배열로 캡처합니다.
[[...params]]: 선택적 Catch-All 동적 경로로서, 경로가 있어도 되고 없어도 됩니다. 경로가 없을 경우 빈 배열로 반환됩니다.
이 패턴을 통해 유연한 라우팅을 구성할 수 있으며, 다양한 경로 변형을 처리하는 데 매우 유용합니다.
use client 와 asyncs는 같이 사용을 못한다.
"use client"와 async 함수는 각자 다른 환경에서 동작하기 때문에, 서버 컴포넌트와 클라이언트 컴포넌트의 특성 차이로 인해 제약이 발생합니다.
> 왜 use client와 async를 함께 사용할 수 없을까?
클라이언트 컴포넌트는 동기적으로 렌더링:
Next.js에서 클라이언트 컴포넌트는 브라우저에서 동기적으로 렌더링됩니다. 클라이언트 컴포넌트는 동기적인 렌더링 흐름을 가져야 하기 때문에 컴포넌트 자체가 async 함수가 될 수 없습니다.
만약 컴포넌트 전체가 async로 선언되면, 해당 컴포넌트가 반환할 때까지 기다려야 하는데, 이는 브라우저의 동기 렌더링 흐름과 맞지 않기 때문에 에러가 발생합니다.
데이터 가져오기와 렌더링의 분리:
클라이언트 컴포넌트에서는 데이터 가져오기를 위해 React hooks를 사용해야 합니다. useEffect, useState 같은 React hooks로 비동기 작업을 처리하고, 상태 업데이트를 통해 다시 렌더링해야 합니다.
서버 컴포넌트에서는 서버에서 데이터를 미리 가져온 후 그 결과를 클라이언트로 넘겨주지만, 클라이언트 컴포넌트는 브라우저에서 비동기 작업을 별도로 처리하고 렌더링 흐름을 제어해야 합니다.
Image를 사용하기 위한 설정
// for Image component in next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'via.placeholder.com',
port: '',
pathname: '/**',
},
],
},
};
export default nextConfig;
Next Cloudinary Image(사진) 편집???
https://next.cloudinary.dev/
shadcn 설치!!!
https://ui.shadcn.com/docs/installation/next
pnpm dlx shadcn@latest init
아이콘 패키지 설치!!
https://heroicons.com/
$> pnpm add @heroicons/react
Next-auth 설치
$> pnpm add next-auth@beta
$> pnpm dlx auth secret
>> .env.local의 AUTH_SECRET 자동 세팅!