상세 컨텐츠

본문 제목

[Next.js] Next.js 시작하기 (nextJs 설치 / 클라이언트렌더링, 서버렌더링 - use client / page / layout / url설정 / url:key값 설정)

React

by developia_yeso 2025. 4. 17. 18:35

본문

 

환경설정

- node 20.10.0

- next.js15.2.4

- react 19.1.0

- react-dom 19.1.0

 

개요

- 프론트엔드 영역에서 React, Vue + SSR렌더링 요구 증가 ->  Next.js 가 요구되어지는 곳들이 많아짐. 

- Next.js 사이트들도 제법 많아서 활용해보기로 함

 

 

1. Next.js 시작하기 ( 가장 최신버전으로 설치 ) 

-수동버전 설치 : npm install react@latest next@latest react-dom@latest 

-package.json설정 : "license" : "MIT"로 변경, "scripts" : { "dev" : "next dev" } 로 설정

-app 폴더안에 page.jsx 혹은 page.tsx 파일 생성  (타입스크립트를 사용하는 경우, tsx 파일로 생성)

**현재 프로젝트의 경우, 타입스크립트를 이용했으므로 편의상 tsx 파일로 칭하겠다. 

 

- 자동버전 설치 : npx create-next-app@latest --typescript(타입스크립트 설치 필요시 기재)

 

package.json 환경설정

 

 

2. 서버렌더링과 클라이언트 렌더링 - "use client" 관련

 

앞서 next.js가 렌더링 되는 방식을 우리는 알 필요가 있다. 이러한 방식은 컴포넌트를 구성하고 설정하는데 많은 도움이 된다.

 

- 일단 기존 React.js의 렌더링 방식을 먼저 살펴보자

* 여기서 렌더링의 의미? 자바스크립트를 가져와서 브라우저가 이해할 수 있는 html로 변환하는 작업을 의미

 

* 리액트의 동작방식 = 클라이언트 사이드 렌더링( 모든 ui 구축 작업이 모두 클라이언트 측에서 일어나는 것을 의미)

렌더링을 위해 브라우저가 스크립트를 모두 불러오고나서야 ui가 구현되어진다. = 클라이언트 사이드 렌더링 방식 

과정) 1. 자바스크립트 로드 2. ui 빌드

 

+ 문제점?

 

1) 렌더링 되는 시간동안 아무것도 보여지지않는 빈화면(이땐 실제로 html에 ui가 없으므로)이 노출되고나서

관련된 모든 스크립트가 다 불려지면 화면이 구현된다. 자바스크립트는 불러오는데 시간이 걸리므로 자바스크립트가

비활성화 되어있는 경우, 화면 ui가 구현되어지지않는다. (요즘은 대개 자바스크립트가 비활성화 되어있는 경우는 없겠지만)

ex. 데이터 연결상태가 좋지 않는 경우 - 엘레베이터안, 터널안

 

2) SEO 검색 엔진 최적화 문제 

구글에 노출되기 바란다면, html의 빈페이지를 보여주는게 좋지 않다. 구글은 페이지의 html을 본다

 

 

 

* Next.js가 동작하는 방식 = 우선 모든 컴포넌트들을 서버에서 렌더링한다(**무조건 서버측에서 먼저 렌더링**)

 

** 모든 컴포넌트들을 서버에서 렌더링 (html들을 브라우저에 request, response로 넘김)

-> 클라이언트 컴포넌트(use client)는 다시 react.js, next.js로 렌더링함 (=hydration)

과정) 백엔드 서버에서 클라이언트 컴포넌트, 서버 컴포넌트를 렌더링 -> 클라이언트 컴포넌트는 프론트에서 다시 렌더링하거나

hydration(단순 html을 리액트 어플리케이션, next 어플리케이션으로 초기화하는 작업)이 된다.

 

ex. /about-us 클릭 -> html(서버에서 렌더링 된 아주 지루한 html(인터랙티브하지않은 전형적인 브라우저 html) = 자바스크립트,

프레임워크 로드 안된 상태의 페이지가 열림(사용자가 확인하는 첫 화면) -> 사용자 화면 확인 -> 초기 html(인터랙티브x)위에

리액트 어플리케이션, next 어플리케이션 버전 html(인터랙티브함) 로드 = 리액트 컴포넌트형식으로 변환(프레임워크 초기화)

 

+ 주의할점?

= hydration이 모든 컴포넌트에 적용되는 것은 아니다. use client 컴포넌트에만 적용이 된다.

**서버사이드렌더링은 모든 컴포넌트에 적용되지만 클라이언트 즉 hydrate되는 컴포넌트는 지정된

컴포넌트 영역(use client)에서만 적용된다 **

 

 

++ 장점 

1) 자바스크립트가 활성화되어있지 않아도 사용자가 html을 확인할 수 있다 -> 적어도 최초의 ui빌드를 자바스크립트에 의존하지 않는다.

= 사용자들이 페이지에 접근해서 바로 ui(첫 화면)를 볼 수 있음을 의미

 

2) 프레임워크에게 서버컴포넌트와 클라이언트 컴포넌트를 알려주는 건 매우 효율적이다 -> 다운로드해야 할 자바스크립트의 수가

줄어듦을 의미한다.

= 페이지 로딩속도를 개선

 

 

* use client (클라이언트 컴포넌트 설정) = 프레임워크에 hydration이 필요함을 명시하는 뜻

서버에서 렌더링이 된 후, 프론트에서 hydrate 및 인터랙티브가 됨을 의미한다

**오직 클라이언트에서 렌더링 됨을 의미하는게 아니다**

 

use client를 선언하지 않으면 기본적으로 모두 서버 컴포넌트이다. 서버 컴포넌트는 서버에서 렌더가 되고 나서도 hydrate가 필요하지 않다 -> 불필요한 자바스크립트를 다운하지 않는다 = 사용자가 자바스크립트를 적게 다운받아도 됨을 의미한다.

 

그렇다면 언제 클라이언트 컴포넌트를 가지게 될까? -> **상호작용이 필요한 부분! (상태관리)**

ex. useState, useEffect, useRouter 등 브라우저 전용 훅들, 디바이스 api, 지리위치 등등..

 

usePathname()을 사용하기 위해선 use client 선언이 필요하다

 

현재 위치한 페이지를 파악하기 위해서 usePathname을 사용해야 했는데 이를 이용하기 위해선 use client 선언이 필요했다.

 

 

 

onClick 이벤트 사용을 위해서도 use client 선언이 필요하다

 

 

마찬가지로 useRouter() 사용과 onClick과 같은 이벤트 실행의 인터랙티브한 동작을 위해선 hydration이 필요하므로 use client 선언을 해주어야한다.

 

 

 

+ 주의 해야 할 점?

서버컴포넌트내에선 클라이언트 컴포넌트를 가질 수 있지만, 클라이언트 컴포넌트내에선 서버 컴포넌트를 가질 수 없다

클라이언트 컴포넌트는 클라이언트 컴포넌트만 가질 수 있다.

 

 

 

 

3. Next.js 특징 파악하기 

[1] page.jsx 혹은 page.tsx 파일 = Next.js의 기본 ui를 의미

 app폴더내 page.tsx 파일의 의미는 URL = '/' 이다. 기본 ui의 컴포넌트라고 할 수 있다

 = 사용자가 기본적으로 보게 될 요소 (첫 화면)

 

우리가 여기서 알아야할 점은 next.js는 ** 어떠한 import나 경로 설정없이 자동으로 경로가 설정이 되고 렌더링 된다. ***

그러므로 page.tsx는 next.js의 특징 및 규칙상 첫 화면의 ui가 된다. 여기서 우리는 Next.js가 가지는 URL 설정을

먼저 알 필요성이 있다.

 

 

[2] app 폴더내에 생성하는 폴더들은 경로설정을 의미한다.

ex. recommand 라는 폴더를 생성하면 1) /recommand 가 URL 경로로 형성이 되고 2) 이 폴더내 page.jsx 및 page.tsx파일을 만드는 경우 

 /recommand 의 기본 ui가 된다.

 

 

url설정을 의미하는 파일

 

 

app 파일내 만들어지는 모든 파일은 URL을 의미한다. 위의 이미지처럼 about-us, recommand 요소들은 모두 URL이다.

ex. /about-us , /recommand

이러한 규칙은 따로 import , router를 통한 설정도 필요하지 않다. Next.js의 편리함이자 장점인 요소이다.

 

/recommand 주소를 가진 URL

 

 

이러한 폴더내 page.tsx가 있다면 그 파일은 자동으로 그 폴더의 기본 ui가 된다.

-> 폴더내 page.tsx 생성시 /recommand url을 통한 기본 첫 ui 화면 구현

 

 

 

[3] () 괄호안에 들어간 폴더명은 URL 경로를 설정하지 않는다.

 

(movies) 라는 폴더내 page.tsx가 있다

 

url을 생성하지 않은 (movies) (movies)

 

 

()괄호안에 생성한 파일명은 URL을 형성하지 않는다 -> Next.js의 규칙이다.  

이러한 경우, 따로 import 또는 router를 설정하지 않는 이상 URL을 생성하지 않는다.

이런 규칙은 URL이 필요없는 파일들에 매우 유용하게 사용할 수 있다. 예를 들어 /movies/1234 와 같이 한 형식의 페이지를

무한대로 증식해 사용해야 하는 경우이다.

기존의 params를 통해 react-router에서 사용했던  /movies/:id 의 기능을 활용하기에 좋다.

 

 

[4] Dynamic Routes : [] 중괄호를 사용한 폴더명 - [] 중괄호안의 텍스트는 params의 key값이다

= 리액트의 react-router와 같은 개념이지만 hook이 따로 필요하지 않다.

 

앞서 말한 기존 params를 통해 react-router에서 사용했던  /movies/:id 의 기능은 next.js에서 어떻게 구현할까?

= []중괄호를 사용한 폴더명을 이용하면 된다

-> [] 중괄호를 사용한 폴더명은 next.js에게 /폴더명/ 뒤에 무엇이 들어가도 괜찮다는 것을 next.js에게 알려주는 일이다.

 

 

[]중괄호에 id폴더명을 입력한 예시

 

이미지와 관련해 URL을 설명해보자면 /movies/1234(id값) 이 들어가도 next.js에게 괜찮다는 것을 알려줌을 의미한다.

이땐 [id]내 있는 page.tsx 파일에서 **props로 무엇을 받는지** 확인을 해야한다. (params값 확인) 

주의해야할 점은 params로 받는 key값이 []중괄호안의 텍스트로 형성된다는 점이다.

여기선 [id]이므로 id가 key값이 된다.

 

 

+ 막간을 이용한 지식

props 값으로는 params, searchParams 두 가지를 얻을 수 있다. 

params는 key값을 searchParams의 경우, url에서 필터 역할이 된다.

ex. http://localhost:3000/movies/111111?region=kr&page=2 가 예시일 경우, 

params: { id: '111111' } searchParams: { region : "kr", page : "2"} 로 표시가 된다 = 검색페이지를 구축할 때 많이 사용된다.

 

[id]값을 props로 받아와 url로 적용한 사례 = 파라미터가 url의 변수값이 되어 적용되어졌다.

 

 

 

 

[5] layout.tsx 의미 -> 폴더를 전반적으로 감싸는 layout을 의미 

 

 

 Next.js에서 layout이란 어떤 의미일까? -> 먼저 **next.js의 렌더링 순서를 파악**하자 

 

1) Next.js 렌더링 순서 = app내의 page.tsx를 찾은 다음 가장 가까운 layout을 찾기 시작 -> 레이아웃을 통해 하위항목을 렌더링

 

2) URL이동 = url 클릭 -> 이동하려는 url의 페이지를 찾은 다음, 가장 가까운 layout을 찾기 시작 -> 상위폴더로 이동하여

레이아웃이 있는지 확인 후 레이아웃을 사용하여 하위 항목을 렌더링 -> 점차적으로 root 레이아웃으로 접근

-> app파일이 가진 layout 접근해 모든 레이아웃이 중첩되어져 실행

= 프레임워크(Next.js)는 이동하려는 페이지에 가장 가까운 레이아웃을 찾으려 시도 

ex. page.tsx -> layout.tsx -> 상위폴더 -> 상위폴더 layout -> root 폴더 -> root폴더 layout.tsx 찾기 -> root폴더가 가진 layout파일들이 중첩되어져 실행

 

ex. about-us내에서도 layout폴더를 중복으로 만들 수 있다. 이 경우, about-us의 하위 항목들이 이 레이아웃에 모두 렌더링 되어진다.

 

app폴더의 layout

 

 

app폴더내 layout.tsx의 경우 {children} 영역안으로 하위폴더들이 렌더링 된다.

navigation의 경우, 모든 컴포넌트에 적용되는 공통이므로 개별적으로 컴포넌트에 삽입하는 것이 아닌 layout.tsx 컴포넌트 자체에

기입해 모든 컴포넌트에 적용이 될 수 있도록 했다. 

app폴더내 about-us 폴더 컴포넌트 구성요소로 풀어보자면 이렇게 설명 할 수 있다.

 

ex. <Layout>

             <about-usLayout>

                        <about-us/>

             </about-usLayout>

       </Layout>

 

 

이미 눈치챘겠지만, layout.tsx는 한 번만 적용이 될까? = **그렇지 않다**

 

폴더 생성시 page파일을 생성해 폴더의 기본 ui 구현을 이루는 것 처럼  layout 파일의 경우도 layout 파일을 새로운 폴더내 중복으로 만들 수 있다. (* 주의 할 점은 한 폴더 내 page.tsx, layout.tsx 등의 파일은 하나여야 한다 = 프레임워크의 규칙)

ex. app폴더내 layout.tsx 파일이 있어도 about-us폴더내 layout.tsx파일을 생성할 수 있다. 

= 이것은 레이아웃이 서로 상쇄되는 것이 아니라 중첩이 가능을 의미한다. 

 

app폴더의 layout.tsx와 about-us내 layout.tsx가 서로 중첩하고 있다.

 

 

또한 app폴더의 layout.tsx의 경우 따로 생성하지 않아도 npm run dev를 터미널에 입력하고 실행시 자동으로 생성된다.

 

 

 

 

 

 

 

 

 

 

 

 

관련글 더보기