https://nextjs.org/learn/dashboard-app
Invoice Dashboard를 통해 NextJs 14의 기능을 배우는 튜토리얼이였습니다
페이지를 개발하고 수정할때 Page routing에 대해 설명하거나 찾아보기 어려울때가 있는데 폴더 구조로된 NEXT 만의 장점으로 편리하게 개발을 할 수 있었습니다
global.css를 사용하면서도 @tailwind base; 같은 몇가지 지시문을 통해 개발하는 NEXT만의 CSS 개발 환경 NEXT를 가장 많이 접하진 않았지만 이젠 TailwindCSS가 익숙하다고 느껴집니다
on off 값과 같은 상태변화에 따라 바뀌는 값을 CSS로 편하게 설정할 수 있는 CLSX 라이브러리
글꼴은 디자인에서 중요한 역할이지만서도 글꼴을 로드하여 가져오기 때문에 성능에도 영향을 미칠 수 있습니다
NEXT는 모듈을 사용할때 자동으로 최적화하여 정적 자산과 함께 호스팅하여 네트워크 요청을 추가로 하지 않습니다
이미지를 최적화를 수동화로 구현하지 않고 NEXT는 자동으로 이미지 최적화 기능을 제공합니다
<a herf>
를 통한 페이지 이동이아닌
<Link>
를 통해 어플레이션 페이지 간 연결을 할 수 있습니다
a태그와 차별화된점은 무엇인가를 말씀드리면 일단 반응속도가 확실하게 빠른게 느껴집니다 이러한 이유는
NEXT는 경로 세그먼트별로 자동으로 코드를 분할하기 때문입니다 분할은 격리를 의미하고 특정페이지에서 오류가 발생하더라고 나머지 어플리케이션 부분은 계속 작동을 의미합니다
또한 프로 덕션 환경에서
<Link>
구성요소가 뷰포트에 나타날때 경로에 대한 코드를 미리 가져와서 페이지 전환이 거의 즉각적으로 이루어집니다.
기존 리액트에서는 이동하려는 페이지의 정보를 가져와서 라우팅을 하는 방식이라면 'use client'와 usePathname()을 이용해 경로를 확인하고 패턴을 사용할 수 있는 후크를 제공합니다
실무에서 개발할땐 postgres를 사용하여 개발하지만 vercel 자체 기능으로 데이터 베이스를 만들기도 합니다 하지만 prisma를 이용해 orm 사용해 개발하는 경우가 현재는 더 많은거 같아 추가 후술하겠지만 이 부분은 좀 더 공부가 필요할것으로 생각됩니다
seed.js 파일을 통해 초기 데이터베이스를 구축하여 진행하였습니다
https://haesoo9410.tistory.com/404
SSG, SSR, ISR 여러가지 랜더링 방식이있지만 NEXT 튜토리얼 문서에서는 RSC를 채택하여 장점을들 여러개 가지고 있는데 가장 큰 장점은 Server Components는 서버에서 실행되기 때문에 별도의 API 계층 없이 데이터베이스에 직접 쿼리할 수 있는 NEXT.js 풀스택 개발이 가능하단것입니다
지금 NEXT14버전을 사용하는 회사는 많지 않을거라고 생각합니다 12 또는 13버전을 사용한다고 필자는 생각하지만 prisma업시 데이터베이스에 직접 쿼리하는 방법을 후술해보려합니다
vercel 팀에서 재공하는 라이브러리를 이용하여
const invoiceCountPromise = sql`SELECT COUNT(*) FROM invoices`;
const customerCountPromise = sql`SELECT COUNT(*) FROM customers`;
이렇게 변수에 값을 간편하게 넣을 수있습니다
데이터를 가져오다 보면 지나치게 요청이 밀려서 폭포수처럼 쏟아질때가 있는데 이럴땐 await Promise.all을 사용하여 모든 약속을 동시에 시작할 수 있습니다
Next.js API unstable_noStore나 데이터 가져오기 기능을 사용하여 정적 렌더링을 거부할 수 있습니다.
unstable noStore란 캐싱하지말고 동적으로 작동할때 사용하는 함수입니다
정적, 동적 랜더링의 저마다의 장점이 존재하는데 정적 랜더링의 장점은
1. 사전 랜더링된 콘텐츠로 인한 빠르고 안정적인 액세스 빠른 로드시간
2. SEO로 크롤링하기 더 쉽고 유용하다
동적 랜더링에 관해서는 다음 스트리밍과 같이 설명합니다
스트리밍이란 경로를 더 작은 청크로 나누고 준비가되면 서버에서 클라이언트로 점진적으로 스트리밍하는 데이터 전송 기술로써 라이브 동영상을 생각하면 이해가 편합니다
NEXT 에선 스트리밍을 구현하는 방법이 두가지가 존재합니다
1. loading.tsx
2. 특정 구성요소에 대한 Suspense 함수사용
두가지 방법을 나눈이유를 명확하게 구분해보자면 전체 페이지에 대한 스트리밍 기술은 loading.tsx
부분적인 콘텐츠를 스트리밍하려면 Suspense 함수를 사용하는게 옳다고 생각합니다
업데이트를 처리하고 suspense 함수를 사용하는 방법에 대해 더 공부해야하된다는 생각이 들었습니다
(위 2개의 방법으로는 스트리밍 처리가 쉽지않다는 생각입니다)
Suspense 방법으로 처리할 수 있다는 생각?! 이 듭니다
URL 검색 매개 변수를 사용하는 이유는 무엇인지에 대해 설명하려고 합니다
1. 검색 메개 변수를 사용하면 페이징을 북마크 처리가 가능합니다
2.서버 측 렌더링 및 초기 로드가 가능하다는데 이게 URL 매개변수일때와 아닌점에 대해서는 더 알아봐야할거같습니다
3. 분석 및 추적에 용이한 점 URL에 그대로 노출되어 사용자 행동 추적이 더 간편합니다
검색 기능에 관련해서 NEXT 라우팅 처리에서는 미들웨어를 타지 않는다는 얘기를 들은거 같습니다
미들웨어를 굳이 타지 않아도 되지만 미들웨어를 타고 처리가 필요한 부분에 있어서는 추가적인 부분이 필요합니다.
"use client" 를 사용하여 이벤트 리스너와 후크를 사용할 수 있게됩니다
usePathname을 이용해서 현재의 주소를 받아 replace 함수를 이용해 URL을 업데이트하는 방식으로 진행합니다
검색어 값과 페이지 값을 입력하여 URL로 업데이트하여 Page.tsx에 보낸뒤 usePathname을 받아서 해당 변수들의 값을 읽고 저장하여 Table 함수에 넣어서 값을 출력하는 방식입니다
하지만 값을 입력할대마다 콘솔에서는 키보드에서 입력한 값에 따라 지속적으로 요청을 보내오는데 불필요한 지속적인 요청이라고 판단되면 디바운싱 기능 라이브러리를 불러와 특정 시간마다 요청을 보내게 설정할 수 있습니다
npm i use-debounce
클라이언트 상태 대신 URL 검색 매개변수를 사용하여 검색 및 페이지 매김을 처리한 후 서버에서 데이터를 가져온뒤 useRouter를 사용하지 않고 라우터 훅을 사용해 페이지 변환을 구현했습니다
백엔드 없이 서버작업을 진행하는 NEXT의 강점은 POST요청, 암호화된 폐쇄, 엄격한 입력 확인, 오류 메시지 해싱 , 호스트 제한과 같은 기능을 이용할 수 있다고 기술해놓았다
invoice를 추가하는 서버 작업이 진행되는과정
1. 사용자 입력을 받을 양식을 만듭니다
2. 서버 작업을 만들고 양식에서 데이터를 호출합니다
3. 서버 작업내에서 formData 개체에서 데이터를 추출합니다
4. 데이터 베이스에 삽입할 내용에 데이터를 검증합니다
5. 데이터를 삽입하고 오류를 처리합니다
6. 캐시를 재검증하고 리턴값을 다시 리디렉션 합니다
sql문이 정상적으로 작동하면 revalidatePath 함수로 캐시를 무효화 시킨뒤
redirect 함수로 페이지를 리디랙션 할 수 있습니다
invoice 업데이트도 비슷한 방식으로 진행되지만 삭제의 경우는 redirect 함수가 필요없습니다.
error.tsx 파일로 모든 오류를 처리하는 페이징을 할 수 있지만
notFound 함수를 사용하여 코드에 작성하면 not-found.tsx 파일로 라우팅됩니다
양식 접근성을 개선하기위한 방법 두가지 ESLint와 Prettier 을 설명드리면
기본적으로는 ESLint를 Next 프로젝트를 만들때부터 추천하지만 Prettier 를 이용한 프로젝트가 있어 Prettier를 사용하여 개발할 예정입니다
양식 유효성 검사에는 3가지 방법이 있다고 생각합니다
프론트단 백단 데이터베이스단에서 양식의 유효성을 검사해서 데이터 처리를 한다고 생각하는데
어떤게 정답인지는 알 수 없으나 각각 비지니스 모델마다 중점을 두가지로 두자면
대용량트래픽에 걸리는 시간복잡도와 안전호환성이라고 생각합니다
프론트단에서 양식 유효성을 검사하는 방법은 input 태그에 required를 넣는 방식이있고
백단에서 검증하는 방법 즉 서버측 검증 방법은 useFormState라는 훅을 사용합니다
클라이언트 측 유효성 검사는 악의적인 사용자가 데이터를 가공할 수 있지만 서버측 유효성 검증은 이러한 위험이 없습니다
useFormState에 대해 알아보면 두개의 인수를 받고 두개의 값을 반환합니다
두개의 인수에 대해 알아보면 Action.ts에 서버작업, initialState라는 임의의 객체를 사용합니다
action.ts에서 Zod를 사용하여 양식 데이터 유효성을 검사한뒤 useFormState의 인수인 Action.ts의 서버작업에 두 매개변수를 허용하도록 작업을 진행합니다
formData는 이전과 같고 prevState 후크에서 전달된 상태를 포함합니다 Zod의 safeParse 함수를 사용하여 success 또는 필드를 포함하는 객체를 반환합니다
마지막으로 try/catch문을 활용하여 sql오류에 대해 유효성 검사를 별도로 처리하므로 데이터베이스 오류에 대해 특정 메시지를 반환할 수 있습니다
인증 통해 신원을 확인한 다음 승인을 통해 사용자가 사용할 수 있는 어플래케이션의 부분이 결정됩니다
Google Authenticator와 같은 외부 앱을 사용할 수 있습니다
NextAuth를 이용한 인증으로 AUTH_SECRET 키를 openssl로 입력받은다음
root 폴더에 auth.config.ts 파일을 생성해 로그인 페이지로 리디렉션하게 만듭니다
앱과 운영체제의 사이의 미들웨어로 부터 경로를 보호하기 위한 구문을 추가하고
middleware.ts의 작업을 통해 미들웨어가 인증을 확인할 때까지 보호된 경로가 렌더링을 시작하지 않아 앱의 보안과 성능이 모두 향상됩니다 그다음으로 비밀번호를 해싱한 뒤 bcrypt라이브러리를 이용해 비밀번호가 일치하는지 확인합니다.
SEO 및 공유성을 위한 메타데이터를 추가할 수 있습니다