CSR, SSR차이 - next.js 설치 및 공사콕 웹앱 폴더 설정
1, next.js
리액트를 위해 만든 오픈소스 자바스크립트 웹 프레임워크로 리액트에선 없는 기능을 제공
- 서버 사이드 렌더링 server-side rendering(SSR)
- 정적 사이트 생성 static site generation(SSG)
- 증분 정적 재생성 incremental static regeneration(ISR)
SSR
- 로딩시간 단축 : 서버사이드 렌더링은 서버에서 자바스크립트를 로딩함으로 클라이언트 측에서는 자바스크립트를 로딩하는 시간이 줄어들게 됨
- SEO : 검색엔진이 자바스크립트를 읽는 게 아닌 서버측에서 자바스크립트, html, css를 만들어 컨텐츠에 직접 업로드 & meta 태그를 자유롭게 추가함으로 SEO를 용이하게 할 수 있음
1, SSR와 CSR의 차이
<aside> 📖 SSR - next.js 브라우저가 html파일 → JS 파일 순으로 다운 받으며, JS를 다운로드 받는 동안 html 렌더링을 시작하기 때문에 웹페이지에 표시가 빠르게 된다. 하지만 JS가 다 받아진 상황이 아니라 제대로 동작하지 않을 수 있다. 페이지를 이동했을 때에도 같은 동작이 반복되기 때문에 렌더링은 빠르나 깜빡임이 생길 수 있다.
CSR - react url요청으로 웹문서가 가지고 있는 모든 정보를 한 번에 가지고 온다. 초기 화면 로드가 느리지만 사이트를 돌아다닐 때에는 사용성이 좋아진다. (예:페이스북) 보통 로드가 될 때 로딩중을 표시하는 화면이 표시되도록 한다. 링크를 이동할 때 JS를 이용하여 동적으로 화면을 바꾸기 때문에 html문서가 가지고 있는 정보가 적어SEO가 나쁨
</aside>
2, SPA (Single Page Application)
리액트는 CSR 방식을 채택한 것이며, Single Page Application의 구축을 가능하게 해줌.
초반에 표시되는 index.html 외 html문서는 없음.
index.html의 내용으로 JS를 이용해 재 렌더링 해주는 방식으로 페이지를 구성하며 표시해야 할 내용은 파일이 아닌 컴포넌트 형식으로 구성
3, Virtual DOM
DOM
- ‘Document Object Model’의 약자로 주로 html 문서 내에 요소
- html, css, javascript 로 만들었던 웹사이트에서는 querySelector 나 getElementbyID 같은 명령어로 직접 DOM 요소를 찾아 직접 조작
- 직접 요소를 조작하는 방식은 페이지 내 상태가 변경될 때 페이지를 새로 로드하기 때문에 페이지 용량이 크면 클수록 느려지는 단점이 있음
Virtual DOM
- CSR 방식으로 한번에 모든 정보를 받고 Virtual DOM 을 이용해 페이지 내에 변한 부분만을 감지해서 그 부분만 변경해주게 되면 훨씬 부담을 줄일 수 있다.
- 유저 인터랙션이 일어나면 Virtual DOM에 의해 구성된 DOM 트리는 이전 페이지와 바뀐 부분들을 감지한다. 그래서 변화된 부분만 재 렌더링
2, 설치 & 설정
node.js는 설치가 되어있다고 가정하고 next.js 설치방법만 작성
npx create-next-app [프로젝트이름]
- 처음엔 카멜케이스 방식의 프로젝트 이름을 사용하여 오류가 났다. (프로젝트 이름은 소문자 혹은 언더스네이크 방식으로 작성)
✔ Would you like to use TypeScript? … No / Yes
- 타입스크립트를 사용할 것인지 물음 (Yes가 기본)
✔ Would you like to use ESLint? … No / Yes
- ESLint를 사용할 것인지 물음 (Yes가 기본)
✔ Would you like to use Tailwind CSS? … No / Yes
- Tailwind CSS를 사용할 것인지 물음 (No가 기본)
✔ Would you like to use src/ directory? … No / Yes
- src/ 방식의 폴더 규칙을 사용할 것인지 물음 (No가 기본)
✔ Would you like to use App Router? (recommended) … No / Yes
- App Router 방식을 사용할 것인지 물음 (Yes가 기본)
- next.js 13버전부터 사용
✔ Would you like to customize the default import alias (@/*)? … No / Yes
- 절대경로를 사용할 것인지 물음 (No가 기본)
공사콕 웹앱 폴더 정리
1, 레파지토리
X
2, url
next.js 13버전부턴 app router 방식을 사용한다. app 폴더 내부에 page.jsx(page.tsx) 로 작성된 파일을 url path로 인식하게 되므로 react의 react-router-dom처럼 별도 라이브러리를 사용하지 않고 router 이용이 가능하다.
page.tsx
// app/dashboard/page.tsx
export default function Layout({
children, // will be a page or nested layout
}: {
children: React.ReactNode;
}) {
return <section>sec{children}</section>;
// 해당 layout 파일이 있는 폴더의 page는 sction 내부에 코드가 렌더링된다.
}
layout.tsx
- 같은 폴더 내에 있는 layout 혹은 상위 폴더의 layout은 다른 page.tsx에서 함께 사용할 수 있다.
- 공용으로 사용해야 하는 컴포넌트 혹은 meta tag 같은 경우 상위 layout 코드에 작성한다.
- 최상위 routeLayout에는 html, body 태그를 작성해야 한다.
- app에서 루트레이아웃을 삭제하고, 폴더 내부에 각각 따로 루트 레이아웃을 작성하여 사용할 수도 있음
// app/layout.tsx
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Next.js!!!!!!",
};
// app/page.tsx에 해당 title tag를 넣으면 router 이동 시 title이 사라지게 됨. 다른 페이지에서도 사용할 수 있게 layout.tsx에 작성
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<nav>nav!</nav>
{children}
</body>
</html>
);
}
3, 기능별 폴더 정리
1, route 지정
<aside> 📌 next.js13 이후 버전에서는 app routing 방식을 사용하기 때문에 app 폴더 내부에 폴더를 생성 & page라는 이름으로 컴포넌트를 생성하면 url path로 이용이 가능하다.
- react-router-dom을 따로 설치할 필요가 없다.
</aside>
- app 폴더에 작성된 page.tsx의 url주소는 https::localhost3000/ 이 된다.
- app>login>page.tsx의 url주소는 https::localhost3000/login
- () 괄호를 이용하여 폴더를 생성한 경우 app 폴더 내부에 생성된 경우더라도 url로 인식하지 않는다.
home에 사용된 파일을 (home) 폴더에 작성하였다.
2, css
css는 css모듈을 사용하고 있다.
page.tsx와 동일한 위치에 {name}.module.css 파일을 생성하여 css 를 작성한다.
// nav/page.tsx
<header className={styles.navWrap}>
<div className={styles.head}>
</div>
</header>
// nav/nav.module.css
.navWrap {
width: 100%;
height: auto;
}
.navWrap a {
width: 100%;
height: auto;
}
.head {
width: 100%;
height: auto;
}
와 같은 방식으로 사용하면 된다.
3, component
레이아웃 혹은 반복 사용되는 구역의 경우 컴포넌트 폴더로 따로 분류하여 사용한다.
4, constans
프로젝트에서 사용하는 stiring 관리 폴더이다.
1, 서버 관리
// url.ts
let currentURL = "relase";
export default function urlPrefixCk() {
if (currentURL === "dev") {
return "<https://devawsback.gongsacok.com>";
} else if (currentURL === "stage") {
return "<https://stageawsback.gongsacok.com>";
} else if (currentURL === "relase") {
return "<https://releaseawsback.gongsacok.com>";
}
}
2, endpoint 관리
// api.ts
import urlPrefixCk from "./url";
export const urlPrefix = urlPrefixCk();
// 로그인
export const urlLogin = urlPrefix + "/pub/login";
// 메인
export const urlLikeSerach = urlPrefix + "/pub/likeSearch";
5, hooks
사용성을 위해 useHook을 만들게 될 경우 /hooks 폴더에 파일을 작성한다.
현재는 사용자의 위치를 파악하는 useGeolocation 파일이 있다.
- 파일 예시
import { useState, useEffect } from "react";
interface locationType {
loaded: boolean;
coordinates?: { lat: number; lng: number };
error?: { code: number; message: string };
}
const useGeolocation = () => {
const [location, setLocation] = useState<locationType>({
loaded: false,
coordinates: { lat: 0, lng: 0 },
});
// 성공에 대한 로직
const onSuccess = (location: {
coords: { latitude: number; longitude: number };
}) => {
setLocation({
loaded: true,
coordinates: {
lat: location.coords.latitude,
lng: location.coords.longitude,
},
});
};
// 에러에 대한 로직
const onError = (error: { code: number; message: string }) => {
setLocation({
loaded: true,
error,
});
};
useEffect(() => {
// navigator 객체 안에 geolocation이 없다면
// 위치 정보가 없는 것.
if (!("geolocation" in navigator)) {
onError({
code: 0,
message: "Geolocation not supported",
});
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}, []);
return location;
};
export default useGeolocation;
6, image
프로젝트에서 사용하는 image파일은 /image 폴더에 저장
이미지는 next/image 로 관리
import Image from "next/image";
import profilePic from "@/image/logo.png";
export default function Head() {
return <Image
src={profilePic}
width={50}
height={50}
alt="공사콕 로고 이미지"
placeholder="blur"
/>
}
8, services
기능에 관련된 폴더 & 파일은 해당 폴더 내부에 작성한다.
현재는 fetch기능과 cookie 기능이 적용되어 있다.
// fetch
export const post = async (url: string, data: any) => {
const handleAwait = await fetch(url, {
method: "post",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify(data),
}).then((response) => response.json());
return handleAwait;
};
// token
"use client";
import { useCookies } from "next-client-cookies";
export const setToken = (accessToken: string) => {
const cookies = useCookies();
cookies.set("TOKEN", accessToken);
};
export const getToken = () => {
const cookies = useCookies();
cookies.get("TOKEN");
};
'front > next' 카테고리의 다른 글
next.js 14 aws cloudfront, s3 (client mode) 배포 (0) | 2024.03.06 |
---|---|
SSR - next.js 설치 SSR, CSR의 차이 (0) | 2024.02.15 |
next.js prisma model 추가 (API 추가 / prisma studio) (0) | 2024.01.31 |
next 간편로그인 (카카오, 네이버) (0) | 2024.01.30 |
next 로그인 커스텀 디자인 (pages signin() 페이지 커스텀 설정 & nextauth이용하여 api 등록) (0) | 2024.01.30 |