벌써 2주차 후기라니 시간이 너무 빠르다.
일주일이 어떻게 흘렀는지도 모를만큼 빠른 진도였다.
정신차리고 수업 따라가는 데만 해도 많은 에너지를 썼다.
한 주 동안 배운 내용
드디어 리액트를 마무리하고 Next.js 파트로 넘어갔다.
솔직히 리액트 심화 부분도 어려운데(메모이제이션 부분ㅠ) Next를 따라갈 수 있을까 걱정했는데 생각보다 그렇게 어렵지는 않다. 물론 생각보다 어렵지 않다는 거지 모든 게 이해간다는 건 아니다...
강사님께서 Next의 꽃인 라우팅 부분에 대해서 오랜 시간을 들여 가르쳐 주셨다. 이전에 Next.js 살짝 찍먹해 봤을 때는 app 라우터보다는 page 라우터가 대세여서 page 라우터로 Next.js를 배웠는데, 불과 5개월만에 대세가 완전히 바뀌었나 보다. 강사님께서도 이제는 최신 버전인 app 라우터를 쓰는 게 좋다고 말씀하셔서 이런 게 프론트엔드 개발자의 세계구나 하는 걸 다시 한 번 느꼈다.
뭐 Next 15버전 나온다는 걸 들었던 때에 비하면 충격이 덜한 편이긴 하다.😂 정말 끊임없이 공부해야 하는구나 다시 한 번 되새기게 되었다.
어쨌든 새롭게 Next.js에 대해 배운 김에 이번 주는 6월 7일 기록한 Next.js 이론에 대해 포스팅해보려고 한다.
다음주에 Next.js 수업을 더 이어나가겠지만 우선 배운 내용을 기록해보겠다.
Next.js 이론(기초, app 라우팅)
🥰 Next.js
- 프레임워크(Next.js) ↔ 라이브러리(리액트)
프레임워크 vs 라이브러리
- 라이브러리는 파일의 구조나 폴더 구조 및 필요한 개발의 모든 것을 개발자가 직접 세팅한다.(react-routing) 개발자의 자유도가 높다.
- 프레임워크는 정해진 rule(문법, 규약, 폴더구조)을 따라야 한다.
라우팅 방식
- 페이지 라우팅
- 앱 라우팅 (최신버전 방식)
- 두 개 섞어서 쓸 수도 있다. (마이그레이션 가능)
보일러 플레이트(boilerplate) 설치
- 보일러 플레이트: 주로 프로그래밍이나 법률 문서에서 반복적으로 사용되는 표준화된 코드나 텍스트를 의미. 리액트에서 대표적인 보일러 플레이트는
create-app
,cretate-vite
가 있다.
npx create-next-app@latest
npx create-next-app@latest . //현재 폴더에 설치
메타데이터
https://nextjs.org/docs/app/api-reference/functions/generate-metadata
- 메타데이터는 템플릿을 이용해 각 페이지마다 적용할 수 있다.
2초 뒤에 타이틀이 바뀌도록 (async, await 사용)
export const generateMetadata = async () => {
const title = await new Promise(resolve);
setTimeout(() => {
resolve("Async Title");
}, 2000);
return { title };
};
라우터 이해하기
App 라우터
/login 경로로 이동하면 해당 page 정보가 렌더링된다.
주소 이름은 오로지 폴더명에만 영향을 받는다.
중첩경로
동적 라우트
catchall segments ⇒ 포괄적 경로 지정
- […slug] 하위 경로를 일괄적으로 받아 처리하기 위한 방법
- 하위 경로를 모두 slug 아래 page로 이동시켜줌
- 실무에서 사용해 본 적 없음(강사님 피셜)
라우팅하는 법
a 태그 이용: 새로고침됨
Link 태그: 새로고침X, 변경된 부분만 변경해서 사용자에게 보여줌
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import Link from "next/link";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: {
template: "%s | yesol",
default: "Next.JS | yesol",
},
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<h1>Root Header</h1>
<body className={inter.className}>{children}</body>
<Link href="/login">로그인</Link>
<h2>Root Footer</h2>
</html>
);
}
"use client";
import { useRouter } from "next/navigation";
import React, { useState } from "react";
export default function page() {
const router = useRouter();
console.log(router);
const onClickHandler = () => {
console.log("click");
};
return (
<div>
page<button onClick={onClickHandler}>클릭</button>
</div>
);
}
- push:
router.push("/login")
현재 내가 보고 있는 페이지를 기록하고 로그인 컴포넌트로 이동, 뒤로가기 시 이전 페이지로 이동 가능, 일반 페이지에 적용(ex. 장바구니, 물건목록보기, 마이페이지 등등) - replace:
router.replace("/replace")
현재 내가 보고 있는 페이지를 기록하지 않고 이동, 뒤로가기 시 홈화면으로 이동, 다시 돌아오면 안 되는 페이지에 적용(ex. 결제 페이지)
+로그인 세션 풀렸을 때는 if문을 이용해서 redirect(”/”)
사용
- prefetch: 페이지를 미리 로드하여 빠른 탐색을 가능하게 한다. 단, 프로덕션(상용) 모드에서만 지원
private 경로
_auth
폴더 > pages.tsx
해당 경로에 접근하지 못함. 404 not found 뜸
새로운 프로젝트 제공할 때, 개발 시에는 이렇게 사용하고 개발 완료하면 일반 폴더로 돌리는 식으로 사용 가능
그룹 경로
()
로 묶어줌. 하위 페이지를 단순 그룹화하는 용도
실무에서도 빈번하게 사용함.
Not Found 커스텀
src > app > not-found.tsx
파일 생성 및 파일 내용 작성으로 not found 페이지 커스텀이 가능
Layout 구조
- 나와 같은 경로의 layout부터 찾는다. ⇒ layout을 찾지 못하면 root layout까지 찾아 올라간다.
- 실무에서는 레이아웃을 2중첩하는 경우도 찾아보기 힘듬
경로: 쿼리스트링을 사용하는 2가지 방법 (useSearchParams(), params)
http://localhost:3000/blog?page=2
1. useSearchParams
next에서 제공하는 hook
"use client";
import { useSearchParams } from "next/navigation";
export default function BlogPage() {
//페이지의 쿼리스트링을 받아서 처리할 수 있다.
const searchParams = useSearchParams();
console.log(searchParams.get("lang"));
console.log(searchParams.get("page"));
return (
<>
<h1>BlogPage Component</h1>
</>
);
}
2. params 사용
type TPageParams = {
params: {};
searchParams: {
page: string;
};
};
export default function BlogPage(params: TPageParams) {
console.log(params);
const { searchParams } = params;
console.log(searchParams.page);
return (
<>
<h1>BlogPage Component</h1>
</>
);
}
params, searchParams
type TPageParams = {
params: {
blogId: string;
};
searchParams: {
page: string;
};
};
export default function BlogDetail({ params, searchParams }: TPageParams) {
const { blogId } = params;
const { page } = searchParams;
return (
<>
<h1>BlogDetail Component</h1>
<h2>
Query String: {blogId}, {page}
</h2>
</>
);
}
페이지 경로를 알려주는 Hook: usePathname Hook
페이지 구분을 가능하게 해주는 hook
"use client";
import { usePathname } from "next/navigation";
export default function Login() {
const pathname = usePathname();
console.log(pathname);
return (
<>
<h1>Login Component</h1>
</>
);
}
컴포넌트
서버 컴포넌트: 화면에 보이기 전에 실행되는 컴포넌트
클라이언트 컴포넌트: 웹 브라우저에 코드가 불러와지고 실행되는 컴포넌트
SSR과 CSR
SSR (서버)
- 네트워크에서 페이지를 불러올 때, 불러와지는 파일에는 화면에 보이는 모든 내용이 완성되어 있는 상태로 사용자에게 전달된다.
- 서버에서 사용자에게 보여줘야 하는 내용을 만들어서 내려주는 동작방식.
- 웹 브라우저 입장에서는 자바스크립트에서 작동한 내용을 보여주는 게 아니라 서버에서 내려준 내용을 보여주기만 하는 것
- 로딩 화면 깜빡임 없음.
CSR (웹브라우저)
- Client-side Rendering(CSR)은 웹 페이지의 콘텐츠를 클라이언트(브라우저)에서 렌더링하는 방식
- 서버에서 HTML, CSS, JavaScript 파일을 클라이언트로 보내고, 클라이언트에서 JavaScript를 실행하여 동적인 웹 페이지를 생성하게 된다.
- 이로 인해 서버의 부하가 감소하고, 인터랙티브한 기능을 제공할 수 있게 된다. 자주 사용되는 웹 프레임워크로는 React, Angular, Vue.js 등이 있다.
Next.JS는 SSR + CSR 두 개 다 함 (렌더링을 두 번 함)
- JS 처리가 필요없는 부분은 서버에서 모두 처리해서 client에게 내려준다. 사용자는 이렇게 처리된 화면을 보게 된다. (서버 렌더링 속도 매우 빠름)
- JS에 의한 코드 부분은 2차로 client side에서 처리되어 화면에 보여지게 된다.
🚫 주의: "use client"
키워드가 붙어있는 클라이언트 컴포넌트도 1차적으로는 서버사이드에서 실행된다.
Hydration
- 정적인 HTML에 JS를 붙이는 과정 (2차 렌더링 과정에서 발생)
- 정적인 HTML(뼈대)를 서버에서 전달해 주면, 여기에 클라이언트 렌더링의 JS(사용자와 상호작용, 동적인 동작)을 더해주는 과정을 Hydration이라고 한다.
- JS의 기능을 군데 군데 붙이는데, 그렇다고 전체화면을 다시 그리는 게 아니고, HTML 뼈대에 JS를 적용하는 것이다.
- 따라서 2번 렌더링한다고 크게 성능에 부담되지 않음 + client 내용 없으면 굳이 2번 렌더링하지 않는다.(클라이언트 렌더링 없이 서버 렌더링만 수행)
Build
npm run build
- SSG: 정적파일로 빌드되는 것
- dynamic한 파일은 SSG로 불가능(블로그 [id]…)
⇒ 정적/동적인 파일은 별도로 빌드된다.
폰트 최적화
export default function Home() {
return (
<>
<h1 className="roboto">Home Component</h1>
</>
);
}
@tailwind base;
@tailwind components;
@tailwind utilities;
@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap");
.roboto-regular {
font-family: "Roboto", sans-serif;
}
import { Roboto } from "next/font/google";
const roboto = Roboto({ weight: ["400", "700"], subsets: ["latin"] });
export default function Home() {
return (
<>
<h1 className="roboto">Home Component</h1>
<h1 className={roboto.className}>Home Component</h1>
</>
);
}
폰트 최적화 패키지를 이용해 가져온 폰트는 로딩 시 깜빡임이 없다.
→ 구글 패키지의 경우 서버에서 폰트를 가져오기 때문에, 깜빡임이 일어나지 않는다.
본 후기는 [유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 1기 과정(B-log) 리뷰로 작성 되었습니다.
'Developer > 웹개발 교육 프로그램' 카테고리의 다른 글
[유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 1기 - 사전직무교육 1주차 후기 (0) | 2024.06.02 |
---|---|
[에이블런] TIL(24.05.22): 자바스크립트 2 (0) | 2024.05.22 |
[에이블런] TIL(24.05.20): 자바스크립트 1 (0) | 2024.05.20 |
[에이블런] TIL(24.05.16): Git 2 (0) | 2024.05.18 |
[에이블런] TIL(24.05.14): Git (0) | 2024.05.18 |
[에이블런] TIL(24.05.09): 컴퓨터 구조 (0) | 2024.05.18 |