Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 104 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,104 @@
# mobi-3rd-next.js
<a href="https://lyrical-brain-e0f.notion.site/mobi-next-js-6590e8579ed041f1a7ebf58bfe6cb3e4">@see</a>

### 기간
```
2024.05.20 ~ 2024.06.01 (일요일 리뷰 가능하도록 PR 남기기, 스프레티드시트에 링크 등록)
2024.06.02 (WIL, 다른 페어 코드 리뷰, 회고 및 느낀점 발표)

* 반드시 리드미에 프로젝트 개요와 설명, 시연 영상 등을 함께 작성해주세요 :)
```

### 페어-편성
```
1페어 Riel - Jeff - Chan
2페어 Gang - Wendy - Brilly
```

### 과제
```
1. NextJS 똑바로 알기
2. NextJS 파일 [라우트] 시스템 알아보기
3. NextJS의 폰트와 이미지 최적화
4. 서버 사이드 랜더링
5. NextJS 12와 13의 차이
6. NextJS 공식 문서와 무료 강의로 러닝하기
7. mark-down을 활용한 나만의 블로그 호스팅하기
8. next-auth를 사용하여 로그인 구현하기
```

### 진행방법
```
1. 페어는 각자 함께 할 수 있는 시간을 선정합니다.
2. 시간 선정이 완료되면 mobi 단톡방에 월~일요일 단위로 올려주세요.
ex)
- Jeff (14:00 ~ 22:00)
- Lucas (08:00 ~ 20:00)
- core-time (20:00~22:00) -- 코어 타임은 매일 매일 가져야합니다. 겹치는 시간을 최대한 활용하고 블락킹 된 부분과 풀이한 부분을 공유할 것

화 ...
...
목 - 리프레쉬 데이 (같은 페어일 경우 요일 고정)
...
- 20:00~22:00 WIL
- 22:00~23:00 1주차 회고 및 느낀점
- 23:00~01:00 각 페어 코드 리뷰 -- 반드시 PR로 문서화할 것


2. 과제는 스스로 풀어본 이후에 코어 타임에는 반드시 페어와 함께 고민하고 블락킹 된 부분의 해소와 풀이를 공유해야합니다.
3. 매일 매일 풀이한 과제는 해당 레포지토리에 브랜치에 Pair-n으로 commit-push 합니다. (리프레쉬 제외 1일 1커밋 준수)
4. 학습 시간에는 모비 항상 디스코드에 접속해서 학습을 진행해주셔야 합니다.
```
# Mobi-3rd-next.js

## 프로젝트 개요

- Task1 ~ Task8을 학습하며 SSR방식을 사용하는 프레임워크`Nextjs`에 대해 학습합니다.

## 프로젝트 기간

- 2024.05.20 ~ 2024.06.01

## TASK.1 NextJS 똑바로 알기

### 👍next와 react의 차이점은?

- Task1 에서는 next와 react의 차이점인 `랜더링 방식(ssr vs csr)`을 중심으로 장단점을 비교해봤습니다.
> 1.속도 2.로드방식 3.비용 4.SEO 5.어떤 프로젝트에 사용하면 좋은지?

### 📃Task1 Link주소 : [next와 react의 차이점 알아보기](https://github.com/mobi-community/mobi-3rd-next.js/tree/Pair1-Chan/Task1)

## TASK.2 NextJS 파일 [라우트] 시스템 알아보기

### 👍파일 라우트 시스템에 대한 이해

- react는 라이브러리기때문에 routing또한 직접 설정해야 했습니다.
- 반면 next에서는 app || page 폴더 아래에`폴더생성 & page.tsx`를 배치하는 것만으로 라우팅을 지원해주는데 이에대한 사용방법을 알아봅시다.

### 👍`use client`를 사용해하하는 이유

- `useRouter` 혹은 `useSearchParams` 를 next에서 사용하기 위해서는 해당컴포넌트에 `use client` keyword를 입력해야 사용가능합니다.
- 이를 이해하기 위해서는 nextjs에서 server component와 client component가 무엇인지 이해야하고 랜더링 과정또한 이해해야합니다.

### 📃Task2 Link주소 : [파일 라우트시스템 적용하기](https://github.com/mobi-community/mobi-3rd-next.js/tree/Pair1-Chan/Task2)

## TASK.3 NextJS의 폰트와 이미지 최적화

### 👍 Font 와 Image의 최적화지원

- react프로젝트에서는 외부 font를 사용하거나 image를 로드할때 `최적화`라는 것을 고려해야했습니다.
- 그 이유는 CLS(로딩시점에 따른 layout의 변화)을 높혀야 core web vitals 를 향상시킬수 있기때문
- Next13버전 부터는 개발자들에게 이런점을 고려하지않아도 스스로 최적화를 해주는 Image,font로딩 방식을 지원해줍니다.
- Task3에서는 최적화라는 관점에서 어떻게 동작하고 어떤점이 효과적인지 정리했습니다.

### 📃Task3 Link주소 : [nextjs에서 font,image의 최적화지원](https://github.com/mobi-community/mobi-3rd-next.js/tree/Pair1-Chan/Task3)

## TASK.4 서버 사이드 랜더링

### 👍알아본내용

- 미해결... 아직못했습니다. 일요일날 꼭 해보겠습니다.!

### 📃Task4 Link주소 :[]()

## TASK.5 NextJS 12와 13의 차이

### 👍알아본내용

- 미해결... 아직못했습니다. 일요일날 꼭 해보겠습니다.!

### 📃Task5 Link주소 :[]()

## TASK.6 NextJS 공식 문서와 무료 강의로 러닝하기

### 👍 Nomad 강의 후기

- 무료강의를 통해 nextjs의 아키텍처에 대해 배웠습니다.
- 라이브러리인 react와 프레임워크인 nextjs가 어떤점이 다른지 배웠습니다.
- ssr 방식의 nextjs로 프로젝트를 생성하는 과정을 배웠습니다.
_(강의를 듣고 따로정리를 안해서 생각나는 부분들만 README.md에 작성했습니다..)_

### 📃Task6 Link주소 :[app router](https://github.com/mobi-community/mobi-3rd-next.js/tree/Pair1-Chan/nomad)

### 📃Task6 Link주소 :[page router](https://github.com/mobi-community/mobi-3rd-next.js/tree/Pair1-Chan/nextjs-nomad)

## TASK.7 Mark-down을 활용한 나만의 블로그 호스팅하기

### 👍 사용 라이브러리

- [velite](https://velite.js.org/)
- [tailwind-typography](https://github.com/tailwindlabs/tailwindcss-typography)
- [shadcn](https://ui.shadcn.com/)

### 👍 nextjs를 활용한 blog구현

- 마크다운 언어로된 mdx파일을 읽어오는 라이브러리 Velite를 사용해서 나만의 블로그를 만들었습니다.

### 📃Task7 Link주소 :[Chan's Log](https://github.com/mobi-community/mobi-3rd-next.js/tree/Pair1-Chan/blog)

## TASK.8 next-auth를 사용하여 로그인 구현하기

### 👍알아본내용

- 미해결... 아직못했습니다. 일요일날 꼭 해보겠습니다.!

### 📃Task8 Link주소 :[]()

## 회고

react를 사용할땐 csr이 무엇이고 라이브러리와 프레임워크의 차이를 이해하지 못했습니다.
이번 task를 진행하면서 csr, ssr의 개념을 확실하게 알게됬습니다.<br><br>
이전 task들을 진행하며 사실 core web vtial, ssr,csr 과같은 개념적인 내용을 어떻게 이해해야
하고 내 프로젝트에서 고려해야 하는지 이해하지 못했었는데 react와 nextjs의 차이를 이해하면서 지금까지 배웠던 것들이 다 필요한 내용이었고 어떻게 적용되는지 알게되서 좋았습니다.<br><br>
이를 바탕으로 프로젝트의 목적에맞는 랜더링방식을 고려해서 프로젝트설계를 할 수 있을것 같습니다.

task를 다끝내지 못해서 아쉽습니다... 재밌는 내용들인데 본격적으로 프로젝트에 들어가기전에 꼭 다해보겠습니다.
36 changes: 36 additions & 0 deletions Task1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Server side rendering vs Client side rendering

## 속도

- ssr은 서버에서 모든 HTML을 만들어서 클라이언트 측으로 보내주기때문에 클라이언트는 페이지 로드시 완성된 HTML을 바로 볼 수 있다.
- csr은 클라이언트 측에서 HTML을 요청하면 최소한의 HTML과 함께 자바스크립트 파일을 넘겨받는다. 서버측에서 모든 자원요청이 끝난후 클라이언트 측에서 자바스크립트 엔진을 실행후 완료되면 사용자가 볼 수 있다.
- 따라서 첫 페이지 로드시에 ssr은 화면을 더빠르게 볼 수 있다.

## 로드방식

- ssr은 클라이언트측에서 HTML을 요청시 완성된 HTML을 보내주고 즉시 사용자가 정적인 HTML파일을 볼 수 있다. 또한 모든 HTML을 받아온후 자바스크립트 엔진을 실행시켜 동적 컴포넌트를 hydration시켜주기때문에 js를 실행후 사용자는 페이지와 상호작용이 가능하다.
- csr은 빈 HTML을 로드받은후 api요청, 동적컴포넌트생성이 완료된 후 페이지를 보기때문에 페이지가 로드된후 바로 페이지와 상호작용이 가능하다.

## 비용

- ssr은 서버로부터 모든 정보를 요청하기때문에 비용측면에서 더 비싼 작업이라고 할 수 있다.
- csr은 서버로부터 api요청, 컴포넌트 구성에 필요한 js파일들을 요청후 클라이언트 측에서 실행하기때문에 서버측 부담이 줄어든다.

## SEO

- ssr은 서버측에서 완성된 HTML을 받기때문에 SEO가 해당페이지에 어떤 정보들이 있는지 파악하기가 쉽다.
- csr은 초기에 빈 HTML을 받고 그후에 동적으로 컴포넌트가 생성됨으로 구글의 `크롤링 봇`이 해당페이지에 어떤내용이 있는지 파악하기 어렵다.

## 언제사용하면 좋지?

- ssr은 사용자와 상호작용이 적고, 페이지의 정보들이 많이 바뀌지않는 서비스에 유리하다.
SEO면에서 유리하고 서버비용까지 고려해서 방향을 설정해야한다.
- csr은 사용자와 상호작용이 많은경우 유리하다. SEO면에서는 불리하지만 SEO를 향상시켜줄 라이브러리를 사용해서 이를 해소하고, 사용자와의 상호작용이 많기때문에 페이지의 정보들이 자주바뀌는 서비스라면 csr방식을 고려해도 좋을것 같다.

# convenience

- react는 라이브러리기때문에 코드를 작성하는 사람이 모든 것을 설정해야한다.
따라서 폴더구조또한 react-router-dom과같은 라이브러리를 사용해서 직접경로를 설정해줘야한다. 자율성이 높아 원하는 구조로 프로젝트를 만들어나갈수 있는 장점이 있는 반면,모든것을 다 설정해줘야하는 것은 단점이 될 수 있다.
- nextjs는 프레임워크이기 때문에 사용법에 맞게 사용한다면 나머지는 프레임워크측에서 알아서 처리를 해준다. nextjs에서는 경로를 따로설정해줄 필요없이 page or app(13버전) 폴더아래 파일을 생성해주기만해도 바로 url로 연결해주기에 개발속도측면에서 유리하다.
- nextjs에서는 img로드시 layout-shift를 자동으로 막아주고 자동으로 최적화 해준다. 또한
구글 폰트가 내장돼있어 별도의 요청없이 사용가능하다.
37 changes: 37 additions & 0 deletions Task2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
.env
5 changes: 5 additions & 0 deletions Task2/app/(home)/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const LoadingHome = () => {
return <h1>Loading .... Wait</h1>
}

export default LoadingHome
23 changes: 23 additions & 0 deletions Task2/app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Metadata } from "next"
import dynamic from "next/dynamic"

export const metadata: Metadata = {
title: "Home",
}

const NoSSRPost = dynamic(() => import("./post-id"), { ssr: false })

const Home = () => {
return (
<div
className="flex flex-col items-center justify-center gap-5"
use-client="true"
>
<h1>Welcome Home</h1>
<h2>Check Some Post</h2>
<NoSSRPost />
</div>
)
}

export default Home
40 changes: 40 additions & 0 deletions Task2/app/(home)/post-id.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"use client"

import Link from "next/link"
import { useRouter } from "next/navigation"

const PostIdArr = () => {
const arr = Array.from({ length: 8 }, () => generateNumber())

const router = useRouter()

const onClickBtn = (num) => {
router.push(`/post/${num}`)
}
return (
<div className="w-fit">
{arr.map((num, idx) => (
<div className="flex gap-5 mt-2" key={idx}>
<Link href={`/post/${num}`}>
<span className="hover:bg-blue-200 w-[5rem] flex items-center justify-center border-2 cursor-pointer rounded-lg">
{num}
</span>
</Link>
<button
onClick={() => onClickBtn(num)}
className="bg-black text-white hover:bg-white hover:text-black p-2 rounded-3xl"
>
Check out Post
</button>
</div>
))}
</div>
)
}

export default PostIdArr

const generateNumber = () => {
const randomNumber = Math.floor(Math.random() * 10000 + 1)
return randomNumber
}
27 changes: 27 additions & 0 deletions Task2/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

body {
font-family: "Trebuchet MS", "Lucida Sans Unicode", "Lucida Grande",
"Lucida Sans", Arial, sans-serif;
}

@layer base {

h1 {
@apply text-6xl;
}
h2 {
@apply text-5xl;
}
h3 {
@apply text-4xl;
}
h4 {
@apply text-3xl;
}
h5 {
@apply text-2xl;
}
}
21 changes: 21 additions & 0 deletions Task2/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Metadata } from "next"
import "./globals.css"
export const metadata: Metadata = {
title: {
template: `%s | Chan`,
default: "Chan",
},
description: "Chan's Task #2",
}

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
12 changes: 12 additions & 0 deletions Task2/app/post/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
type PostIdProps = {
params: { id: string }
}

export const generateMetadata = ({ params: { id } }: PostIdProps) => {
return { title: id }
}

const PostWithId = ({ params: { id } }: PostIdProps) => {
return <h1>PostId{id}</h1>
}
export default PostWithId
10 changes: 10 additions & 0 deletions Task2/app/post/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Metadata } from "next"

export const metadata: Metadata = {
title: "Post",
}

const Post = () => {
return <h1>Post Page</h1>
}
export default Post
Loading