Nextjs

jinjoo-jung·2024년 8월 13일

폴더 경로

  • 직접적인 page.tsx 파일이 없는 폴더는 실제 페이지 없이 그저 경로의 일부분이 될 뿐! , company라는 경로가 실제로 보이게 만들려면, 해당 폴더 안에서 page.tsx를 꼭 생성해야 한다.

  • 매번 Nextjs에게 어떤 경로에서 어떤 컴포넌트를 불러오라고 말 해줄 필요가 없다. (react-router와 달리) 우리는 그저 폴더를 만들고 그 폴더를 보여주고 싶다면 그 폴더안에 Page 파일을 만든다.

  • 사용자가 Url로부터 보게 될 요소는 page.tsx라는 것만 이해하자, 이 파일이 사용자가 해당 url에 접근했을 때 모든 걸 보여주는 요소이다.

특별한 파일 3개의 파일

  • layout, page, not-found.tsx!

nextjs가 application을 render하는 방식을 이해해야 하는데
=> 여기서 렌더링이란 nextjs가 우리의 react component를 가져와서 브라우저가 이해할 수 있는 Html로 변환하는 작업.

기존 리액트 렌더링 방식

  • 원래 리액트가 렌더되는 방식은 CSR이다. 그건 브라우저가 렌더링 작업을 한다는 것을 뜻한다.
  • 소스코드를 보면 페이지의 실제 소스코드는 비어있음 UI가 없음.즉 유저가 이 페이지에 도착한 시점에는 빈화면임. 브라우저가 이모든 자바스크립트 파일을 다운로드하고 실행한 후에야 화면이 보여짐.
  • 브라우저의, 자바스크립트 엔진에 의해 추가됨.
  • 새로고침하면 순간 아무것도 없을거임. 자바스크립트 파일을 다운로드하고 실행시키는데 시간이 걸린다는 것.

한계

  1. 데이터가 잘 안되거나, 데이터가 잘 안터지는 곳에 있다면 모든 자바스크립트 파일을 다운로드받기 위해 오래 걸리고 아무 UI없는 빈 화면을 훨씬 더 오래볼것임.

  2. SEO 최적화
    구글은 페이지의 html을 보기 때문에 빈 페이지를 보여주지않는 것이 좋다. 가끔 구글이 페이지의 자바스크립트를 실행시키기도 하지만 위험감수하는 것보단 html에 실제 데이터가 들어가는게 낫겟지?
    그리고 아마 다른 검색 엔진들은 페이지에서 자바스크립트를 실행시키지 않을것임 .모두 클라이언트 측에서. 자바스크립트를 로드하고 그 후에 자바스크립트가 UI를 빌드해

nextjs는?

nextjs로 웹 사이트를 빌드할때는 자동적으로 기본값으로 서버사이드렌더링이 된다. 자바스크립가 활성화되어있지 않아도 사용자가 HTML을 볼수 있게된다는 것. 자바스크립트가 비활성화 되어있어도 잘 작동한다. 이 HTML을 보여주는데에는 자바스크립트가 필요 없기때문.

기억 해야할것은,
1. nextjs application의 모든 페이지 안의 모든 컴포넌트들은 nextjs가 그것들을 우선 서버에서 렌더한다는 것 . UI는 이미 빌드되어 있고 HTML도 이미 존재한다. 자바스크립트를 기다릴 필요가 없어 !!!
2. 모든 컴포넌트에 대해 발생한다는 것, 클라이언트 컴포넌트 서버컴포넌트 모두, useClient를 갖고 있는 컴포넌트이든 모든 컴포넌트는 우선 서버사이드렌더링. "use client"는 별로라고 생각한다.. 왜냐? => 사람들이 혼란스러워함. 이 컴포넌트는 서버 측에서가 아니라 클라인트 단에서만 렌더되는 것이라고 생각한다. 이보다 잘못된건 있을 수 없다? => 보다시피 컴포넌트가 백엔드 서버에서 렌더된다는 것을 알 수 있음 (자바스크립트 비활성화하니까 서버쪽 터미널에서 콘솔로그가 찍힘).
모든 컴포넌트와 페이지들은 먼저 백엔드에서 렌더되고 HTML로 변환될거, 그 HTML이 브라우저에 넘겨질것이다. 이건 좋다. 사용자들이 페이지에 접근해서 바로 UI를 볼 수 있으므로 .. !

렌더링이란

자바스크립트 함수를 가져와서 브라우저가 이해할 수 있는 HTML로 변환하는 작업이다. 브라우저는 코드를 이해하지 못하기 때문에 이 코드를 가져다가 HTML로 변환해야 함. 그게바로 nextjs가 우리의 어플리케이션의 모든 컴포넌트와 페이지들에 대해 서버 측에서 먼저 하는 일이다. 그 HTML결과물이 브라우저에게 주어지는 거고, 그게 자바스크립트를 활성화하든 말든 상관이 없다.

hydration

= interactive 하게 된다는 것.

평범한 a태그는 없다.
click이 발생하게 되면 Link component가 처리하게 된다.
이 Link component는 clien side only navigation을 수행하고 있음.

-> about us가 있고 0이 쓰여진 버튼이 사용자에게 주어지고, 이게 현재 사용자가 볼 수 있는 유일하고, 기뻐하고, 즉시 뒤쪽에서 프레임워크를 로드하고 프레임워크가 initialize되는 때에 비로소 그 버튼은 우리가 만든 onClick eventListner가 연결된 버튼이 되는 것이다.

그리고 페이지는 interactive하게 될 것이고, 이게 바로 hydration process이다.

hydration은 단순 HTML을 React application로 초기화하는 작업이다.
먼저 0이쓰인것 외에 아무것도 없는 버튼을 받고 리액트를 초기화하여 온클릭을 부착해 여기 작성한 기능을 수행할 수 있도록한다 (상태나,, 클릭 등)

server side render된 지루한 초기 HTML들이 있고 사용자가 그 HTML을 얻으면 그 HTML위에 React application과 next.js application을 생성한다. 그 지루한 HTML을 interactive하게 하기 위해서이다.

이 hydration과정이 모든 컴포넌트에 대해 발생하지 않는다. 다시 말하면 server side render는 모든 컴포넌트에서 발생한다. 모든 컴포넌트들이 서버사이드에서 먼저 렌더된다.

client에서 hydrate되는 componentes는 , client에서 interactive 하게 만들어질 componentes는 오직 use client 지시어를 맨 위에 갖고있는 컴포넌트들 뿐이다.

그저 app을 프로그래밍하고 components를 만들면돼. 그러면 에러를 보게 될것이다.
=> 예를 들어 무언가에 useState를 하려고 하는데 use client를 쓰는 것을 잊어버렸다고 해보자.

그러면 오류가 발생해서 프레임워크가 '이봐 너 지금 useState사용하고 있어'라고 말해줄 것이다. 즉 이 컴포넌트가 interactive하다는 것이다.
=> 따라서 use client는 오직 client에서만 렌더된다는 것을 의미하지 않는다. 백엔드에서 렌더되고 프론트에서 htdrate 됨을 의미한다.

만약 use hydrate였다면 더 명확햇을텐데 ?

  • client에서만 렌더되는 것이 아니라, 백엔드에서 렌더되고 프론트에서 하이드레이트 및 인터랙티드 됨을 의미한다.

그러면 Server Component는?

  • use client component를 사용하지 않는 모든 것들은 server component가 될 것이다.
  • use server를 따로 작성할 필요는 없다.
  • 하지만 use client components도 server에서 먼저 렌더되고 나서 하이드레이트 돼.
    서버 컴포넌트는 서버에서 먼저 렌더되고 하이드레이트는 되지 않는다.
    => 이건 사용자가 자바스크립트를 더 적게 다운받아도 된다는 의미이므로 좋은것

만약 프레임워크에게 어떤 컴포넌트가 인터랙티브 해지고 어떤 컴포넌트가 그저 멍청하고 지루한 HTML이 될지 말해주면 그건 사용자가 다운로드 받을 자바스크립트의 양이 적어지는 것이다.

사용자는 use client를 가진 컴포넌트의 자바스크립트 코드만 다운받게 되고 만약 use client가 없는 컴포넌트들은 서버 컴포넌트에 대한 자바스크립트 코드를 다시 다운로드 받을 필요가 없다.

이게 바로 SSR 과 hydration, 그리고 use client이론이다.

server component는 데이터 페칭을 할 때 엄청난 결과를 가져오기때문에 서버 컴포넌트를 사용하는 것은 매우좋다. . . 일반 리액트 .. .어플리케이션에서 비교하면 , useQuery, react query, swr, useState, useEffecty는 모두 끝난거라고 볼 수 있다. . .

use client는 client만 render한다는 의미가 아닌 , client에서도 render가 된다는 의미이다. 모든 컴포넌트는 백엔드에서 렌더될 것이고 (서버컴포넌트이든 클라이언트 컴포넌트이든) 백엔드에서 먼저 server side render로 pre render될 것이다. use client명령어가 있든 없든. 모든 것이 pre render되어서 HTML로 변환돼. 그게 사용자에게 넘어가고 그 후에 clinet component만이 hydrate되고 interactive하게 되는것이다. 다른 컴포넌트들은 interactive 될 필요가 없기 떄문에 interactive하게 되지 않는다.

Layouts

  • about-us로 이동하면 nextJS는 이 layout 컴포넌트를 렌더링하고 이동하려는 페이지를 URL을 통해 인식하여 layout 컴포넌트 안에 해당 페이지를 렌더링 하게 된다.
    어떤 페이지로 이동할 때마다 이 레이아웃 컴포넌트가 렌더링된다는것. 내가 가려고 하는 페이지가 children이 되는 것이다.
    새페이지를 이동할 때마다 해당 페이지는 layout 컴포넌트의 children prop이 될 것이다.

레이아웃은 상쇄가 아닌 중첩. 서로 대체하지 않는다.

NextJS는 URL을 통해 폴더로 들어가서 그 폴더가 레이아웃이 있는지 확인하고 , 레이아웃이 있다면 그 레이아웃을 밖에 있는 다른 레이아웃 안에 렌더링해. 그래서 AboutUsLayout을 밖에 있는 레이아웃 (Layout)안에 렌더링 해준다.

Metadata

위와 같이 괄호안에 쓴 폴더이름은, URL에 영향을 미치지 않는다. /home, /movies 또한 생성되지 않는다. (괄호가 감싸고 있는한, 프레임워크가 그것을 무시하고 URL이나 어떤 것도 수정하지 않을 것이다

  • layout과 not-found는 일반적이고 ,기본적으로 모든 routes에 공유되기 때문에 가장 상위에 작성해야 하지만, (home)안에 page.tsx는 home에만 관련되어 있기 때문에 여기에 추가적으로 컴포넌트를 넣어서 그룹화할 수도 있다.

metadata란, 꼭 내보내야 하는 object이고 메타데이터로 불린다.

  • 페이지나 레이아웃만 메타데이터를 내보낼 수 있다!! , 컴포넌트에서는 metadata를 내보낼 수 없고 또 metadata는 서버 컴포넌트에만 있을 수 있고 클라이언트 컴포넌트에 있을 수 없다. **중요

메타 데이터에 대한 템플릿?

  • 직접 head에 꼭 무언가 넣을 필요가 없다. 무언가 설치 안 해도 되고, 컴포넌트를 사용할 필요도 없다. 단지 해야할 일은 메타데이터라는 개체를 내보내는 것뿐이다. metadata:Metadate
  • 레이아웃과 페이지만 메타데이터를 export 한다! 기억하기.

=> 만약 메타데이터가 동적이면?
만약 페이지의 이름이 API에서 왔더라면?

dynamic routes

/about-us는 dynamic routes가 아니다. 이건 동적이 아닌 정적 route이다. 정적 route는 항상 똑같이 보인다.
동적 라우트는 /movies/1231243 이런식으로 사용자가 입력한 숫자가 들어가거나 !
여기에 변수가 있다. 리액트 라우터를 써봤더라면 /movies/:id ---> Map으로 컴포넌트들을 보여줬다.

  • react router에서 했던 것과 동일한 걸 어떻게 하는지 배우게 될 것
  1. id를 변수로
  2. 파일 시스템 이용 (app router가 작동하는 방법이기 때문)

이 때 URL에 있는 ID를 가져오고 싶다면?

  • 영화 세부정보 페이지에서 어떤 prop을 받는지. console.log로 알아봤을 때
    이런식으로 뜨는데, 파라이터는 URL에서 변수이다. 그래서 바로 폴더에 있는 [id]는 대괄호로 표시가 된다.

우리는 영화 상세 페이지에서 두 개의 종류 props을 얻을 수 있다. parameter와 searchParams.

정리

  • 처음에 백엔드 서버에서, 클라이언트 컴포넌트와 서버컴포넌트 모두 렌더링 되고 클라이언트 컴포넌트만 프론트엔드에서 다시 렌더링 되거나 다시 hydrate 된다.
  • 클라이언트 컴포넌트의 js는 사용자가 다운로드하여 실행하고 서버컴포넌트의 js는 사용자가 다운로드 하지 않는다. 왜? 그럴 필요가 없기 떄문. 서버 컴포넌트는 딱 한번만 서버에 의해 실행되고 유저는 따분한 HTML을 얻게된다, 그 다음 클라이언트가 hydrate된다. hydarate라는 것은 상호작용이 가능하게 된다는 것. 모든 이벤트 리스너가 추가되고 리액ㅌ 마법은 클라이언트 컴포넌트에서만 발생한다.
  • 그리고 원하는 경우 클라이언트 컴포넌트를 서버 컴포넌트 내에 포함할 수 있지만 반대로 서버 컴포넌트를 클라이언트 컴포넌트 내에는 포함할 수 없다.
  • 서버컴포넌트는 '서버 컴포넌트'라고 따로 표기할 필요가 없다. use client를 쓰지 않는 이상 기본적으로 모든 컴포넌트는 서버컴포넌트이고 클라이언트를 사용 해야하는 때는 상호 작용 같은 부분들이 필요할 때.
    State를 사용해야 하거나 디바이스 API, 지리 위치같은 것이 필요할때 클라이언트 컴포넌트를 사용하면 된다~!
  1. 레이아웃
  • 레이아웃은 페이지 사이에 넣고싶을 때 쓰는 컴포넌트이다. 많은 레이아웃을 다른 곳에있어도 중첩이 되고 NextJS는 우리의 페이지들을 레이아웃으로 래핑할것이다.
  1. 메타데이터
  • 그냥 객체일뿐이고 내보내주기만 하면된다. 무엇을 넣은 웹의 head에 보여질 것이다. 템플릿 기능은 똑같은 걸 계속 반복하지 않아도 되고 병합도 된다. (= description을 가진 메타데이터가 없으면 모든 것이 병합되고 오버라이드 되지 않을 것이다. )모두 동일한 description.
  1. routes 그룹화
  • 폴더(ex. (home), (movies) 등) 이런 폴더로 그룹화할 수 있다. URL에 전혀 영향을 주지 않고.
    괄호안에 그룹의 이름을 적어주면 된다.
  1. dynamic 페이지를 얻는 방법
  • [id] 대괄호 안에 이름을 넣자. 그다음은 NextJs가 알아서 URL에 있는 id를 인식하여 page컴포넌트를 호풀해준다.
profile
개인 개발 공부, 정리용 🔗

0개의 댓글